Skip to content

Commit

Permalink
[Reland] Use direct compositing for canvases rendered on the CPU
Browse files Browse the repository at this point in the history
Before this CL, we already had the plumbing for presenting CPU-rendered
canvases via GpuMemoryBuffer for direct compositing.  That code path was
originally implemented to support LowLatency mode. With this change, we
exercise the GpuMemoryBuffer code path for "regular" latency canvases.
This accelerates compositing, especially for pages that have many
canvases.

With this change, MotionMark Images test runs significantly faster on
MacOS with angle/metal enabled.

Reland of original CL: https://chromium-review.googlesource.com/c/chromium/src/+/4081383

Bug: 1363627
Change-Id: I9380c7f722954af934a657a71c36c37122731f45
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4091749
Reviewed-by: Juanmi Huertas <juanmihd@chromium.org>
Commit-Queue: Justin Novosad <junov@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1083400}
  • Loading branch information
junov authored and Chromium LUCI CQ committed Dec 14, 2022
1 parent dd46024 commit c8d899d
Show file tree
Hide file tree
Showing 135 changed files with 352 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,16 @@ TEST_F(HTMLCanvasPainterTest, Canvas2DLayerAppearsInLayerTree) {
std::unique_ptr<Canvas2DLayerBridge> bridge = MakeCanvas2DLayerBridge(size);
element->SetResourceProviderForTesting(nullptr, std::move(bridge), size);
ASSERT_EQ(context, element->RenderingContext());
ASSERT_TRUE(context->IsComposited());
ASSERT_TRUE(element->IsAccelerated());

// Force the page to paint.
element->PreFinalizeFrame();
context->FinalizeFrame();
element->PostFinalizeFrame();
UpdateAllLifecyclePhasesForTest();

ASSERT_TRUE(context->IsComposited());
ASSERT_TRUE(element->IsAccelerated());

// Fetch the layer associated with the <canvas>, and check that it was
// correctly configured in the layer tree.
const cc::Layer* layer = context->CcLayer();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,10 @@ bool CanvasRenderingContext2D::IsOriginTopLeft() const {
}

bool CanvasRenderingContext2D::IsComposited() const {
return IsAccelerated();
if (Canvas2DLayerBridge* layer_bridge = canvas()->GetCanvas2DLayerBridge()) {
return layer_bridge->IsComposited();
}
return false;
}

void CanvasRenderingContext2D::Stop() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,25 @@ bool Canvas2DLayerBridge::IsAccelerated() const {
return ShouldAccelerate();
}

bool Canvas2DLayerBridge::IsComposited() const {
if (IsHibernating()) {
return false;
}

if (UNLIKELY(!resource_host_)) {
return false;
}

CanvasResourceProvider* resource_provider =
resource_host_->ResourceProvider();
if (UNLIKELY(!resource_provider)) {
return false;
}

return resource_provider->SupportsDirectCompositing() &&
!resource_host_->LowLatencyEnabled();
}

static void HibernateWrapper(base::WeakPtr<Canvas2DLayerBridge> bridge,
base::TimeTicks /*idleDeadline*/) {
if (bridge) {
Expand Down Expand Up @@ -268,14 +287,13 @@ CanvasResourceProvider* Canvas2DLayerBridge::GetOrCreateResourceProvider() {

if (resource_provider && resource_provider->IsValid()) {
#if DCHECK_IS_ON()
// If resource provider is accelerated, a layer should already exist.
// If resource provider is composited, a layer should already exist.
// unless this is a canvas in low latency mode.
// If this DCHECK fails, it probably means that
// CanvasRenderingContextHost::GetOrCreateCanvasResourceProvider() was
// called on a 2D context before this function.
if (IsAccelerated()) {
DCHECK(!!layer_ ||
(resource_host_ && resource_host_->LowLatencyEnabled()));
if (IsComposited()) {
DCHECK(!!layer_);
}
#endif
return resource_provider;
Expand Down Expand Up @@ -310,7 +328,7 @@ CanvasResourceProvider* Canvas2DLayerBridge::GetOrCreateResourceProvider() {
// TODO crbug/1090081: Check possibility to move DidDraw inside Clear.
DidDraw();

if (IsAccelerated() && !layer_) {
if (IsComposited() && !layer_) {
layer_ = cc::TextureLayer::CreateForMailbox(this);
layer_->SetIsDrawable(true);
layer_->SetHitTestable(true);
Expand All @@ -320,6 +338,7 @@ CanvasResourceProvider* Canvas2DLayerBridge::GetOrCreateResourceProvider() {
cc::PaintFlags::FilterQuality::kNone);
layer_->SetHDRConfiguration(resource_host_->GetHDRMode(),
resource_host_->GetHDRMetadata());
layer_->SetFlipped(!resource_provider->IsOriginTopLeft());
}
// After the page becomes visible and successfully restored the canvas
// resource provider, set |lose_context_in_background_| to false.
Expand Down Expand Up @@ -747,7 +766,7 @@ void Canvas2DLayerBridge::FinalizeFrame(bool printing) {
constexpr unsigned kMaxCanvasAnimationBacklog = 2;
if (frames_since_last_commit_ >=
static_cast<int>(kMaxCanvasAnimationBacklog)) {
if (IsAccelerated() && !rate_limiter_) {
if (IsComposited() && !rate_limiter_) {
rate_limiter_ = std::make_unique<SharedContextRateLimiter>(
kMaxCanvasAnimationBacklog);
}
Expand All @@ -759,8 +778,9 @@ void Canvas2DLayerBridge::FinalizeFrame(bool printing) {
}

void Canvas2DLayerBridge::DoPaintInvalidation(const gfx::Rect& dirty_rect) {
if (layer_ && raster_mode_ == RasterMode::kGPU)
if (layer_ && IsComposited()) {
layer_->SetNeedsDisplayRect(dirty_rect);
}
}

scoped_refptr<StaticBitmapImage> Canvas2DLayerBridge::NewImageSnapshot() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ class PLATFORM_EXPORT Canvas2DLayerBridge : public cc::TextureLayerClient {
virtual void DidRestoreCanvasMatrixClipStack(cc::PaintCanvas*) {}
virtual bool IsAccelerated() const;

bool IsComposited() const;

// This may recreate CanvasResourceProvider
cc::PaintCanvas* GetPaintCanvas();
bool IsValid();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1019,4 +1019,29 @@ TEST_F(Canvas2DLayerBridgeTest, NonDisplayedCanvasIsNotRateLimited) {
EXPECT_FALSE(bridge->HasRateLimiterForTesting());
}

TEST_F(Canvas2DLayerBridgeTest, SoftwareCanvasIsCompositedIfImageChromium) {
ScopedTestingPlatformSupport<GpuMemoryBufferTestPlatform> platform;
ScopedCanvas2dImageChromiumForTest canvas_2d_image_chromium(true);
const_cast<gpu::Capabilities&>(SharedGpuContext::ContextProviderWrapper()
->ContextProvider()
->GetCapabilities())
.gpu_memory_buffer_formats.Add(gfx::BufferFormat::BGRA_8888);
std::unique_ptr<Canvas2DLayerBridge> bridge =
MakeBridge(gfx::Size(300, 150), RasterMode::kCPU, kNonOpaque);
EXPECT_TRUE(bridge->IsValid());
DrawSomething(bridge.get());
EXPECT_FALSE(bridge->IsAccelerated());
EXPECT_TRUE(bridge->IsComposited());
}

TEST_F(Canvas2DLayerBridgeTest, SoftwareCanvasNotCompositedIfNotImageChromium) {
ScopedCanvas2dImageChromiumForTest canvas_2d_image_chromium(false);
std::unique_ptr<Canvas2DLayerBridge> bridge =
MakeBridge(gfx::Size(300, 150), RasterMode::kCPU, kNonOpaque);
EXPECT_TRUE(bridge->IsValid());
DrawSomething(bridge.get());
EXPECT_FALSE(bridge->IsAccelerated());
EXPECT_FALSE(bridge->IsComposited());
}

} // namespace blink
Original file line number Diff line number Diff line change
Expand Up @@ -705,7 +705,10 @@ void CanvasResourceRasterSharedImage::CopyRenderingResultsToGpuMemoryBuffer(
auto surface = SkSurface::MakeRasterDirect(CreateSkImageInfo(),
gpu_memory_buffer_->memory(0),
gpu_memory_buffer_->stride(0));
surface->getCanvas()->drawImage(image, 0, 0);

SkPixmap pixmap;
image->peekPixels(&pixmap);
surface->writePixels(pixmap, 0, 0);
auto* sii =
ContextProviderWrapper()->ContextProvider()->SharedImageInterface();
gpu_memory_buffer_->Unmap();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<link rel="help" href="http://www.w3.org/TR/css3-images/#the-object-fit">
<link rel="help" href="http://www.w3.org/TR/css3-images/#the-object-position">
<link rel="match" href="object-fit-contain-png-001-ref.html">
<meta name=fuzzy content="maxDifference=0-20;totalPixels=0-2000">
<style type="text/css">
canvas {
border: 1px dashed gray;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<link rel="help" href="http://www.w3.org/TR/css3-images/#the-object-fit">
<link rel="help" href="http://www.w3.org/TR/css3-images/#the-object-position">
<link rel="match" href="object-fit-contain-png-002-ref.html">
<meta name=fuzzy content="maxDifference=0-20;totalPixels=0-2000">
<style type="text/css">
canvas {
border: 1px dashed gray;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<link rel="help" href="http://www.w3.org/TR/css3-images/#the-object-fit">
<link rel="help" href="http://www.w3.org/TR/css3-images/#the-object-position">
<link rel="match" href="object-fit-fill-png-001-ref.html">
<meta name=fuzzy content="maxDifference=0-20;totalPixels=0-3200">
<style type="text/css">
canvas {
border: 1px dashed gray;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<link rel="help" href="http://www.w3.org/TR/css3-images/#the-object-fit">
<link rel="help" href="http://www.w3.org/TR/css3-images/#the-object-position">
<link rel="match" href="object-fit-fill-png-002-ref.html">
<meta name=fuzzy content="maxDifference=0-20;totalPixels=0-3200">
<style type="text/css">
canvas {
border: 1px dashed gray;
Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Verifies that overlay is correctly rendered with emulation scale > 1.
The test passes if the image URL below is 300x600 image containing a 270x420 brown rectangle, without any green or red.
data:image/png;base64,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

Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"layers": [
{
"name": "Scrolling background of LayoutNGView #document",
"bounds": [800, 600],
"contentsOpaque": true,
"backgroundColor": "#FFFFFF"
},
{
"name": "LayoutHTMLCanvas CANVAS id='canvas'",
"position": [8, 8],
"bounds": [100, 100]
}
]
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"layers": [
{
"name": "Scrolling background of LayoutNGView #document",
"bounds": [800, 600],
"contentsOpaque": true,
"backgroundColor": "#FFFFFF"
},
{
"name": "LayoutHTMLCanvas (positioned) CANVAS id='canvas'",
"position": [50, 50],
"bounds": [500, 500]
}
]
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"layers": [
{
"name": "Scrolling background of LayoutNGView #document",
"bounds": [800, 600],
"contentsOpaque": true,
"backgroundColor": "#FFFFFF",
"invalidations": [
[50, 50, 600, 500]
]
},
{
"name": "LayoutHTMLCanvas (positioned) CANVAS id='canvas'",
"position": [50, 50],
"bounds": [500, 500],
"backgroundColor": "#003300"
}
]
}

0 comments on commit c8d899d

Please sign in to comment.