Commit f8ca0167 authored by Xida Chen's avatar Xida Chen Committed by Commit Bot

Refactor Canvas2DLayerBridge

In our current implementation, we have a Canvas2DImageBufferSurface that
inherits from ImageBufferSurface. The Canvas2DImageBufferSurface keeps
a RefPtr to Canvas2DLayerBridge, and pretty much all the functions in
Canvas2DImageBufferSurface directly calls the functions in Canvas2DLayerBridge.
The reason for this design is that Canvas2DLayerBridge is a RefCounted
class, so that the MailboxInfo could keep a pointer to Canvas2DLayerBridge.

This CL does a refactor in a way that makes Canvas2DLayerBridge directly
inherits from ImageBufferSurface.

Bug: None
Cq-Include-Trybots: master.tryserver.chromium.linux:linux_layout_tests_slimming_paint_v2
Change-Id: Iceaff82d7561f1d064a0e2cc546f47098dd8e110
Reviewed-on: https://chromium-review.googlesource.com/576994Reviewed-by: default avatarJustin Novosad <junov@chromium.org>
Commit-Queue: Xida Chen <xidachen@chromium.org>
Cr-Commit-Position: refs/heads/master@{#491827}
parent 99b95b83
......@@ -68,7 +68,6 @@
#include "core/probe/CoreProbes.h"
#include "platform/Histogram.h"
#include "platform/RuntimeEnabledFeatures.h"
#include "platform/graphics/Canvas2DImageBufferSurface.h"
#include "platform/graphics/CanvasHeuristicParameters.h"
#include "platform/graphics/CanvasMetrics.h"
#include "platform/graphics/ImageBuffer.h"
......@@ -930,7 +929,7 @@ HTMLCanvasElement::CreateAcceleratedImageBufferSurface(OpacityMode opacity_mode,
if (context_provider_wrapper->ContextProvider()->IsSoftwareRendering())
return nullptr; // Don't use accelerated canvas with swiftshader.
auto surface = WTF::MakeUnique<Canvas2DImageBufferSurface>(
auto surface = WTF::MakeUnique<Canvas2DLayerBridge>(
Size(), *msaa_sample_count, opacity_mode,
Canvas2DLayerBridge::kEnableAcceleration, GetCanvasColorParams());
if (!surface->IsValid()) {
......
......@@ -12,7 +12,6 @@
#include "core/loader/EmptyClients.h"
#include "core/paint/StubChromeClientForSPv2.h"
#include "core/testing/DummyPageHolder.h"
#include "platform/graphics/Canvas2DImageBufferSurface.h"
#include "platform/graphics/Canvas2DLayerBridge.h"
#include "platform/graphics/WebGraphicsContext3DProviderWrapper.h"
#include "platform/graphics/gpu/SharedGpuContext.h"
......@@ -66,8 +65,9 @@ class HTMLCanvasPainterTestForSPv2 : public ::testing::Test,
return chrome_client_->HasLayer(layer);
}
RefPtr<Canvas2DLayerBridge> MakeCanvas2DLayerBridge(const IntSize& size) {
return AdoptRef(new Canvas2DLayerBridge(
std::unique_ptr<Canvas2DLayerBridge> MakeCanvas2DLayerBridge(
const IntSize& size) {
return WTF::WrapUnique(new Canvas2DLayerBridge(
size, 0, kNonOpaque, Canvas2DLayerBridge::kForceAccelerationForTesting,
CanvasColorParams()));
}
......@@ -89,10 +89,9 @@ TEST_P(HTMLCanvasPainterTestForSPv2, Canvas2DLayerAppearsInLayerTree) {
attributes.setAlpha(true);
CanvasRenderingContext* context =
element->GetCanvasRenderingContext("2d", attributes);
RefPtr<Canvas2DLayerBridge> bridge =
std::unique_ptr<Canvas2DLayerBridge> bridge =
MakeCanvas2DLayerBridge(IntSize(300, 200));
element->CreateImageBufferUsingSurfaceForTesting(WTF::WrapUnique(
new Canvas2DImageBufferSurface(bridge, IntSize(300, 200))));
element->CreateImageBufferUsingSurfaceForTesting(std::move(bridge));
ASSERT_EQ(context, element->RenderingContext());
ASSERT_TRUE(context->IsComposited());
ASSERT_TRUE(element->IsAccelerated());
......
......@@ -21,7 +21,6 @@
#include "modules/canvas2d/CanvasGradient.h"
#include "modules/canvas2d/CanvasPattern.h"
#include "modules/webgl/WebGLRenderingContext.h"
#include "platform/graphics/Canvas2DImageBufferSurface.h"
#include "platform/graphics/CanvasHeuristicParameters.h"
#include "platform/graphics/RecordingImageBufferSurface.h"
#include "platform/graphics/StaticBitmapImage.h"
......@@ -129,7 +128,7 @@ class CanvasRenderingContext2DTest : public ::testing::Test {
void TearDown() override;
void UnrefCanvas();
PassRefPtr<Canvas2DLayerBridge> MakeBridge(
std::unique_ptr<Canvas2DLayerBridge> MakeBridge(
const IntSize&,
Canvas2DLayerBridge::AccelerationMode);
......@@ -247,10 +246,10 @@ void CanvasRenderingContext2DTest::TearDown() {
SharedGpuContext::SetContextProviderFactoryForTesting(nullptr);
}
PassRefPtr<Canvas2DLayerBridge> CanvasRenderingContext2DTest::MakeBridge(
std::unique_ptr<Canvas2DLayerBridge> CanvasRenderingContext2DTest::MakeBridge(
const IntSize& size,
Canvas2DLayerBridge::AccelerationMode acceleration_mode) {
return AdoptRef(new Canvas2DLayerBridge(
return WTF::WrapUnique(new Canvas2DLayerBridge(
size, 0, kNonOpaque, acceleration_mode, CanvasColorParams()));
}
......@@ -931,11 +930,9 @@ TEST_F(CanvasRenderingContext2DTest, MAYBE_GetImageDataDisablesAcceleration) {
CreateContext(kNonOpaque);
IntSize size(300, 300);
RefPtr<Canvas2DLayerBridge> bridge =
std::unique_ptr<Canvas2DLayerBridge> bridge =
MakeBridge(size, Canvas2DLayerBridge::kEnableAcceleration);
std::unique_ptr<Canvas2DImageBufferSurface> surface(
new Canvas2DImageBufferSurface(bridge, size));
CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface));
CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(bridge));
EXPECT_TRUE(CanvasElement().GetImageBuffer()->IsAccelerated());
EXPECT_EQ(1u, GetGlobalAcceleratedImageBufferCount());
......@@ -1000,11 +997,9 @@ TEST_F(CanvasRenderingContext2DTest, TextureUploadHeuristics) {
CreateContext(kNonOpaque);
IntSize size(dst_size, dst_size);
RefPtr<Canvas2DLayerBridge> bridge =
std::unique_ptr<Canvas2DLayerBridge> bridge =
MakeBridge(size, Canvas2DLayerBridge::kEnableAcceleration);
std::unique_ptr<Canvas2DImageBufferSurface> surface(
new Canvas2DImageBufferSurface(bridge, size));
CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface));
CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(bridge));
EXPECT_TRUE(CanvasElement().GetImageBuffer()->IsAccelerated());
EXPECT_EQ(1u, GetGlobalAcceleratedImageBufferCount());
......@@ -1532,13 +1527,11 @@ TEST_F(CanvasRenderingContext2DTestWithTestingPlatform,
ElementRequestsCompositingUpdateOnHibernateAndWakeUp) {
CreateContext(kNonOpaque);
IntSize size(300, 300);
RefPtr<Canvas2DLayerBridge> bridge =
std::unique_ptr<Canvas2DLayerBridge> bridge =
MakeBridge(size, Canvas2DLayerBridge::kEnableAcceleration);
// Force hibernatation to occur in an immediate task.
bridge->DontUseIdleSchedulingForTesting();
std::unique_ptr<Canvas2DImageBufferSurface> surface(
new Canvas2DImageBufferSurface(bridge, size));
CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface));
CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(bridge));
EXPECT_TRUE(CanvasElement().GetImageBuffer()->IsAccelerated());
......
......@@ -848,7 +848,6 @@ component("platform") {
"graphics/BitmapImageMetrics.h",
"graphics/BoxReflection.cpp",
"graphics/BoxReflection.h",
"graphics/Canvas2DImageBufferSurface.h",
"graphics/Canvas2DLayerBridge.cpp",
"graphics/Canvas2DLayerBridge.h",
"graphics/CanvasColorParams.cpp",
......
/*
* Copyright (C) 2013 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef Canvas2DImageBufferSurface_h
#define Canvas2DImageBufferSurface_h
#include "platform/graphics/Canvas2DLayerBridge.h"
#include "platform/graphics/ImageBufferSurface.h"
#include "platform/graphics/StaticBitmapImage.h"
#include "third_party/skia/include/core/SkRefCnt.h"
namespace blink {
// This shim is necessary because ImageBufferSurfaces are not allowed to be
// RefCounted.
class Canvas2DImageBufferSurface final : public ImageBufferSurface {
public:
Canvas2DImageBufferSurface(
const IntSize& size,
int msaa_sample_count,
OpacityMode opacity_mode,
Canvas2DLayerBridge::AccelerationMode acceleration_mode,
const CanvasColorParams& color_params)
: ImageBufferSurface(size, opacity_mode, color_params),
layer_bridge_(AdoptRef(new Canvas2DLayerBridge(size,
msaa_sample_count,
opacity_mode,
acceleration_mode,
color_params))) {
Init();
}
Canvas2DImageBufferSurface(PassRefPtr<Canvas2DLayerBridge> bridge,
const IntSize& size)
: ImageBufferSurface(size,
bridge->GetOpacityMode(),
bridge->color_params()),
layer_bridge_(std::move(bridge)) {
Init();
}
~Canvas2DImageBufferSurface() override { layer_bridge_->BeginDestruction(); }
// ImageBufferSurface implementation
void FinalizeFrame() override { layer_bridge_->FinalizeFrame(); }
void DoPaintInvalidation(const FloatRect& dirty_rect) override {
layer_bridge_->DoPaintInvalidation(dirty_rect);
}
void WillOverwriteCanvas() override { layer_bridge_->WillOverwriteCanvas(); }
PaintCanvas* Canvas() override { return layer_bridge_->Canvas(); }
void DisableDeferral(DisableDeferralReason reason) override {
layer_bridge_->DisableDeferral(reason);
}
bool IsValid() const override { return layer_bridge_->CheckSurfaceValid(); }
bool Restore() override { return layer_bridge_->RestoreSurface(); }
WebLayer* Layer() const override { return layer_bridge_->Layer(); }
bool IsAccelerated() const override { return layer_bridge_->IsAccelerated(); }
void SetFilterQuality(SkFilterQuality filter_quality) override {
layer_bridge_->SetFilterQuality(filter_quality);
}
void SetIsHidden(bool hidden) override { layer_bridge_->SetIsHidden(hidden); }
void SetImageBuffer(ImageBuffer* image_buffer) override {
layer_bridge_->SetImageBuffer(image_buffer);
}
void DidDraw(const FloatRect& rect) override { layer_bridge_->DidDraw(rect); }
void Flush(FlushReason) override { layer_bridge_->Flush(); }
void FlushGpu(FlushReason) override { layer_bridge_->FlushGpu(); }
bool WritePixels(const SkImageInfo& orig_info,
const void* pixels,
size_t row_bytes,
int x,
int y) override {
return layer_bridge_->WritePixels(orig_info, pixels, row_bytes, x, y);
}
RefPtr<StaticBitmapImage> NewImageSnapshot(AccelerationHint hint,
SnapshotReason reason) override {
return layer_bridge_->NewImageSnapshot(hint, reason);
}
private:
void Init() {
Clear();
if (IsValid())
layer_bridge_->Flush();
}
RefPtr<Canvas2DLayerBridge> layer_bridge_;
};
} // namespace blink
#endif
......@@ -198,8 +198,10 @@ Canvas2DLayerBridge::Canvas2DLayerBridge(const IntSize& size,
int msaa_sample_count,
OpacityMode opacity_mode,
AccelerationMode acceleration_mode,
const CanvasColorParams& color_params)
: context_provider_wrapper_(SharedGpuContext::ContextProviderWrapper()),
const CanvasColorParams& color_params,
bool is_unit_test)
: ImageBufferSurface(size, opacity_mode, color_params),
context_provider_wrapper_(SharedGpuContext::ContextProviderWrapper()),
logger_(WTF::WrapUnique(new Logger)),
weak_ptr_factory_(this),
image_buffer_(0),
......@@ -224,9 +226,12 @@ Canvas2DLayerBridge::Canvas2DLayerBridge(const IntSize& size,
TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation",
TRACE_EVENT_SCOPE_GLOBAL);
StartRecording();
if (!is_unit_test)
Init();
}
Canvas2DLayerBridge::~Canvas2DLayerBridge() {
BeginDestruction();
DCHECK(destruction_in_progress_);
#if USE_IOSURFACE_FOR_2D_CANVAS
ClearCHROMIUMImageCache();
......@@ -234,6 +239,12 @@ Canvas2DLayerBridge::~Canvas2DLayerBridge() {
layer_.reset();
}
void Canvas2DLayerBridge::Init() {
Clear();
if (CheckSurfaceValid())
FlushInternal();
}
void Canvas2DLayerBridge::StartRecording() {
DCHECK(is_deferral_enabled_);
recorder_ = WTF::WrapUnique(new PaintRecorder);
......@@ -535,7 +546,7 @@ void Canvas2DLayerBridge::Hibernate() {
return;
}
if (!CheckSurfaceValid()) {
if (!IsValid()) {
logger_->ReportHibernationEvent(kHibernationAbortedDueGpuContextLoss);
return;
}
......@@ -800,7 +811,7 @@ bool Canvas2DLayerBridge::WritePixels(const SkImageInfo& orig_info,
y + orig_info.height() >= size_.Height()) {
SkipQueuedDrawCommands();
} else {
Flush();
FlushInternal();
}
DCHECK(!have_recorded_draw_commands_);
// call write pixels on the surface, not the recording canvas.
......@@ -848,7 +859,7 @@ void Canvas2DLayerBridge::FlushRecordingOnly() {
}
}
void Canvas2DLayerBridge::Flush() {
void Canvas2DLayerBridge::FlushInternal() {
if (!did_draw_since_last_flush_)
return;
TRACE_EVENT0("cc", "Canvas2DLayerBridge::flush");
......@@ -859,8 +870,12 @@ void Canvas2DLayerBridge::Flush() {
did_draw_since_last_flush_ = false;
}
void Canvas2DLayerBridge::FlushGpu() {
Flush();
void Canvas2DLayerBridge::Flush(FlushReason reason) {
FlushInternal();
}
void Canvas2DLayerBridge::FlushGpuInternal() {
FlushInternal();
gpu::gles2::GLES2Interface* gl = ContextGL();
if (IsAccelerated() && gl && did_draw_since_last_gpu_flush_) {
TRACE_EVENT0("cc", "Canvas2DLayerBridge::flushGpu");
......@@ -869,6 +884,10 @@ void Canvas2DLayerBridge::FlushGpu() {
}
}
void Canvas2DLayerBridge::FlushGpu(FlushReason reason) {
FlushGpuInternal();
}
gpu::gles2::GLES2Interface* Canvas2DLayerBridge::ContextGL() {
// Check on m_layer is necessary because contextGL() may be called during
// the destruction of m_layer
......@@ -876,7 +895,7 @@ gpu::gles2::GLES2Interface* Canvas2DLayerBridge::ContextGL() {
!destruction_in_progress_) {
// Call checkSurfaceValid to ensure the rate limiter is disabled if the
// context is lost.
if (!CheckSurfaceValid())
if (!IsValid())
return nullptr;
}
return context_provider_wrapper_
......@@ -884,6 +903,10 @@ gpu::gles2::GLES2Interface* Canvas2DLayerBridge::ContextGL() {
: nullptr;
}
bool Canvas2DLayerBridge::IsValid() const {
return const_cast<Canvas2DLayerBridge*>(this)->CheckSurfaceValid();
}
bool Canvas2DLayerBridge::CheckSurfaceValid() {
DCHECK(!destruction_in_progress_);
if (destruction_in_progress_)
......@@ -907,7 +930,7 @@ bool Canvas2DLayerBridge::CheckSurfaceValid() {
return surface_.get();
}
bool Canvas2DLayerBridge::RestoreSurface() {
bool Canvas2DLayerBridge::Restore() {
DCHECK(!destruction_in_progress_);
if (destruction_in_progress_ || !IsAccelerated())
return false;
......@@ -1093,13 +1116,13 @@ void Canvas2DLayerBridge::FinalizeFrame() {
if (frames_since_last_commit_ >= 2) {
if (IsAccelerated()) {
FlushGpu();
FlushGpuInternal();
if (!rate_limiter_) {
rate_limiter_ =
SharedContextRateLimiter::Create(MaxCanvasAnimationBacklog);
}
} else {
Flush();
FlushInternal();
}
}
......@@ -1119,11 +1142,11 @@ RefPtr<StaticBitmapImage> Canvas2DLayerBridge::NewImageSnapshot(
SnapshotReason) {
if (IsHibernating())
return StaticBitmapImage::Create(hibernation_image_);
if (!CheckSurfaceValid())
if (!IsValid())
return nullptr;
if (!GetOrCreateSurface(hint))
return nullptr;
Flush();
FlushInternal();
// A readback operation may alter the texture parameters, which may affect
// the compositor's behavior. Therefore, we must trigger copy-on-write
// even though we are not technically writing to the texture, only to its
......
......@@ -79,7 +79,7 @@ class SharedContextRateLimiter;
class PLATFORM_EXPORT Canvas2DLayerBridge
: public NON_EXPORTED_BASE(cc::TextureLayerClient),
public RefCounted<Canvas2DLayerBridge> {
public ImageBufferSurface {
WTF_MAKE_NONCOPYABLE(Canvas2DLayerBridge);
public:
......@@ -93,7 +93,8 @@ class PLATFORM_EXPORT Canvas2DLayerBridge
int msaa_sample_count,
OpacityMode,
AccelerationMode,
const CanvasColorParams&);
const CanvasColorParams&,
bool is_unit_test = false);
~Canvas2DLayerBridge() override;
......@@ -103,26 +104,26 @@ class PLATFORM_EXPORT Canvas2DLayerBridge
out_release_callback) override;
// ImageBufferSurface implementation
void FinalizeFrame();
void DoPaintInvalidation(const FloatRect& dirty_rect);
void WillOverwriteCanvas();
PaintCanvas* Canvas();
void DisableDeferral(DisableDeferralReason);
bool CheckSurfaceValid();
bool RestoreSurface();
WebLayer* Layer() const;
bool IsAccelerated() const;
void SetFilterQuality(SkFilterQuality);
void SetIsHidden(bool);
void SetImageBuffer(ImageBuffer*);
void DidDraw(const FloatRect&);
void FinalizeFrame() override;
void DoPaintInvalidation(const FloatRect& dirty_rect) override;
void WillOverwriteCanvas() override;
PaintCanvas* Canvas() override;
void DisableDeferral(DisableDeferralReason) override;
bool IsValid() const override;
bool Restore() override;
WebLayer* Layer() const override;
bool IsAccelerated() const override;
void SetFilterQuality(SkFilterQuality) override;
void SetIsHidden(bool) override;
void SetImageBuffer(ImageBuffer*) override;
void DidDraw(const FloatRect&) override;
bool WritePixels(const SkImageInfo&,
const void* pixels,
size_t row_bytes,
int x,
int y);
void Flush();
void FlushGpu();
int y) override;
void Flush(FlushReason) override;
void FlushGpu(FlushReason) override;
OpacityMode GetOpacityMode() { return opacity_mode_; }
void DontUseIdleSchedulingForTesting() {
dont_use_idle_scheduling_for_testing_ = true;
......@@ -168,6 +169,10 @@ class PLATFORM_EXPORT Canvas2DLayerBridge
private:
void ResetSurface();
bool IsHidden() { return is_hidden_; }
bool CheckSurfaceValid();
void Init();
void FlushInternal();
void FlushGpuInternal();
#if USE_IOSURFACE_FOR_2D_CANVAS
// All information associated with a CHROMIUM image.
......@@ -177,7 +182,6 @@ class PLATFORM_EXPORT Canvas2DLayerBridge
struct MailboxInfo {
gpu::Mailbox mailbox_;
sk_sp<SkImage> image_;
RefPtr<Canvas2DLayerBridge> parent_layer_bridge_;
#if USE_IOSURFACE_FOR_2D_CANVAS
// If this mailbox wraps an IOSurface-backed texture, the ids of the
......
......@@ -32,6 +32,8 @@ class SharedGpuContextTest : public Test {
SharedGpuContext::SetContextProviderFactoryForTesting(nullptr);
}
bool IsUnitTest() { return true; }
FakeGLES2Interface gl_;
};
......@@ -80,9 +82,11 @@ TEST_F(SharedGpuContextTest, Canvas2DLayerBridgeAutoRecovery) {
EXPECT_FALSE(SharedGpuContext::IsValidWithoutRestoring());
IntSize size(10, 10);
CanvasColorParams color_params;
RefPtr<Canvas2DLayerBridge> bridge = AdoptRef(new Canvas2DLayerBridge(
size, 0, /*msaa sample count*/
kNonOpaque, Canvas2DLayerBridge::kEnableAcceleration, color_params));
std::unique_ptr<Canvas2DLayerBridge> bridge =
WTF::WrapUnique(new Canvas2DLayerBridge(
size, 0, /*msaa sample count*/
kNonOpaque, Canvas2DLayerBridge::kEnableAcceleration, color_params,
IsUnitTest()));
EXPECT_TRUE(bridge->IsAccelerated());
EXPECT_TRUE(SharedGpuContext::IsValidWithoutRestoring());
bridge->BeginDestruction();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment