Commit 3b34b815 authored by Stefan Zager's avatar Stefan Zager Committed by Chromium LUCI CQ

Separate contents_opaque logic on canvas cc::Layer from GraphicsLayer

contents_opaque on the canvas cc::Layer shouldn't depend on its host
GraphicsLayer; and the host GraphicsLayer shouldn't use any special
logic to determine contents_opaque.

This also fixes a CAP-specific bug where the paint code would emit a
background DisplayItem for a canvas even when the canvas has
responsibility for its own background.

As a side effect, this appears to fix a Mac-specific webgl bug that was
hidden due to bad test expectations files added by:

https://chromium-review.googlesource.com/c/chromium/src/+/1005017/

Bug: 1069546
Change-Id: I2a347a6d4a04d2d8b4e299dd0cb10a3c57acbfb1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2607423Reviewed-by: default avatarXianzhu Wang <wangxianzhu@chromium.org>
Commit-Queue: Stefan Zager <szager@chromium.org>
Cr-Commit-Position: refs/heads/master@{#840071}
parent 7be9e7be
......@@ -27,6 +27,7 @@
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h"
#include "third_party/blink/renderer/core/html/canvas/html_canvas_element.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/page/page.h"
......@@ -68,6 +69,23 @@ void LayoutHTMLCanvas::CanvasSizeChanged() {
SetNeedsLayout(layout_invalidation_reason::kSizeChanged);
}
bool LayoutHTMLCanvas::DrawsBackgroundOntoContentLayer() const {
auto* canvas = To<HTMLCanvasElement>(GetNode());
if (canvas->SurfaceLayerBridge())
return false;
CanvasRenderingContext* context = canvas->RenderingContext();
if (!context || !context->IsComposited() || !context->CcLayer())
return false;
if (StyleRef().HasBoxDecorations() || StyleRef().HasBackgroundImage())
return false;
// If there is no background, there is nothing to support.
if (!StyleRef().HasBackground())
return true;
// Simple background that is contained within the contents rect.
return ReplacedContentRect().Contains(
PhysicalBackgroundRect(kBackgroundClipRect));
}
void LayoutHTMLCanvas::InvalidatePaint(
const PaintInvalidatorContext& context) const {
NOT_DESTROYED();
......
......@@ -46,6 +46,8 @@ class CORE_EXPORT LayoutHTMLCanvas final : public LayoutReplaced {
void CanvasSizeChanged();
bool DrawsBackgroundOntoContentLayer() const final;
void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override;
const char* GetName() const override {
......
......@@ -81,6 +81,7 @@ class CORE_EXPORT LayoutReplaced : public LayoutBox {
NOT_DESTROYED();
return false;
}
virtual bool DrawsBackgroundOntoContentLayer() const { return false; }
virtual void PaintReplaced(const PaintInfo&,
const PhysicalOffset& paint_offset) const {
NOT_DESTROYED();
......
......@@ -89,12 +89,6 @@ static PhysicalRect ContentsRect(const LayoutObject& layout_object) {
return To<LayoutBox>(layout_object).PhysicalContentBoxRect();
}
static PhysicalRect BackgroundRect(const LayoutObject& layout_object) {
if (const auto* box = DynamicTo<LayoutBox>(layout_object))
return box->PhysicalBackgroundRect(kBackgroundClipRect);
return PhysicalRect();
}
static inline bool IsTextureLayerCanvas(const LayoutObject& layout_object) {
if (layout_object.IsCanvas()) {
auto* canvas = To<HTMLCanvasElement>(layout_object.GetNode());
......@@ -106,33 +100,10 @@ static inline bool IsTextureLayerCanvas(const LayoutObject& layout_object) {
return false;
}
static inline bool IsSurfaceLayerCanvas(const LayoutObject& layout_object) {
if (layout_object.IsCanvas()) {
auto* canvas = To<HTMLCanvasElement>(layout_object.GetNode());
return canvas->SurfaceLayerBridge();
}
return false;
}
static bool HasBoxDecorationsOrBackgroundImage(const ComputedStyle& style) {
return style.HasBoxDecorations() || style.HasBackgroundImage();
}
static bool ContentLayerSupportsDirectBackgroundComposition(
const LayoutObject& layout_object) {
// No support for decorations - border, border-radius or outline.
// Only simple background - solid color or transparent.
if (HasBoxDecorationsOrBackgroundImage(layout_object.StyleRef()))
return false;
// If there is no background, there is nothing to support.
if (!layout_object.StyleRef().HasBackground())
return true;
// Simple background that is contained within the contents rect.
return ContentsRect(layout_object).Contains(BackgroundRect(layout_object));
}
static WebPluginContainerImpl* GetPluginContainer(LayoutObject& layout_object) {
if (auto* embedded_object = DynamicTo<LayoutEmbeddedObject>(layout_object))
return embedded_object->Plugin();
......@@ -195,9 +166,7 @@ static bool NeedsDecorationOutlineLayer(const PaintLayer& paint_layer,
}
CompositedLayerMapping::CompositedLayerMapping(PaintLayer& layer)
: owning_layer_(layer),
pending_update_scope_(kGraphicsLayerUpdateNone),
draws_background_onto_content_layer_(false) {
: owning_layer_(layer), pending_update_scope_(kGraphicsLayerUpdateNone) {
CreatePrimaryGraphicsLayer();
}
......@@ -273,30 +242,7 @@ void CompositedLayerMapping::UpdateContentsOpaque() {
// not graphics_layer_, and so don't contribute to the opaqueness of the
// latter.
bool should_check_children = !foreground_layer_.get();
if (IsTextureLayerCanvas(GetLayoutObject())) {
CanvasRenderingContext* context =
To<HTMLCanvasElement>(GetLayoutObject().GetNode())->RenderingContext();
cc::Layer* layer = context ? context->CcLayer() : nullptr;
// Determine whether the external texture layer covers the whole graphics
// layer. This may not be the case if there are box decorations or
// shadows.
if (layer && layer->bounds() == graphics_layer_->CcLayer().bounds()) {
// Determine whether the rendering context's external texture layer is
// opaque.
if (!context->CreationAttributes().alpha) {
graphics_layer_->SetContentsOpaque(true);
} else {
graphics_layer_->SetContentsOpaque(
!Color(layer->background_color()).HasAlpha());
}
} else {
graphics_layer_->SetContentsOpaque(false);
}
} else if (IsSurfaceLayerCanvas(GetLayoutObject())) {
// TODO(crbug.com/705019): Contents could be opaque, but that cannot be
// determined from the main thread. Or can it?
graphics_layer_->SetContentsOpaque(false);
} else if (BackgroundPaintsOntoScrollingContentsLayer()) {
if (BackgroundPaintsOntoScrollingContentsLayer()) {
DCHECK(scrolling_contents_layer_);
// Backgrounds painted onto the foreground are clipped by the padding box
// rect.
......@@ -420,7 +366,7 @@ bool CompositedLayerMapping::UpdateGraphicsLayerConfiguration(
} else if (layout_object.IsCanvas()) {
graphics_layer_->SetContentsToCcLayer(
To<HTMLCanvasElement>(layout_object.GetNode())->ContentsCcLayer(),
/*prevent_contents_opaque_changes=*/false);
/*prevent_contents_opaque_changes=*/true);
layer_config_changed = true;
}
......@@ -986,21 +932,10 @@ void CompositedLayerMapping::UpdateDrawsContentAndPaintsHitTest() {
scrolling_contents_layer_->SetPaintsHitTest(paints_hit_test);
}
draws_background_onto_content_layer_ = false;
if (has_painted_content && IsTextureLayerCanvas(GetLayoutObject())) {
CanvasRenderingContext* context =
To<HTMLCanvasElement>(GetLayoutObject().GetNode())->RenderingContext();
// Content layer may be null if context is lost.
if (cc::Layer* content_layer = context->CcLayer()) {
if (ContentLayerSupportsDirectBackgroundComposition(GetLayoutObject())) {
has_painted_content = false;
draws_background_onto_content_layer_ = true;
Color contents_layer_background_color =
GetLayoutObject().ResolveColor(GetCSSPropertyBackgroundColor());
graphics_layer_->SetContentsLayerBackgroundColor(
contents_layer_background_color);
}
}
if (has_painted_content && GetLayoutObject().IsCanvas() &&
To<LayoutHTMLCanvas>(GetLayoutObject())
.DrawsBackgroundOntoContentLayer()) {
has_painted_content = false;
}
// FIXME: we could refine this to only allocate backings for one of these
......
......@@ -247,10 +247,6 @@ class CORE_EXPORT CompositedLayerMapping final : public GraphicsLayerClient {
bool AdjustForCompositedScrolling(const GraphicsLayer*,
IntSize& offset) const;
bool DrawsBackgroundOntoContentLayer() const {
return draws_background_onto_content_layer_;
}
private:
// Returns true for layers with scrollable overflow which have a background
// that can be painted into the composited scrolling contents layer (i.e.
......@@ -460,8 +456,6 @@ class CORE_EXPORT CompositedLayerMapping final : public GraphicsLayerClient {
unsigned pending_update_scope_ : 2;
bool draws_background_onto_content_layer_;
friend class CompositedLayerMappingTest;
};
......
......@@ -46,9 +46,19 @@ void HTMLCanvasPainter::PaintReplaced(const PaintInfo& paint_info,
bool flatten_composited_layers =
paint_info.GetGlobalPaintFlags() & kGlobalPaintFlattenCompositingLayers;
if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled() &&
!flatten_composited_layers) {
if (auto* layer = canvas->ContentsCcLayer()) {
if (auto* layer = canvas->ContentsCcLayer()) {
// TODO(crbug.com/705019): For a texture layer canvas, setting the layer
// background color to an opaque color will cause the layer to be treated as
// opaque. For a surface layer canvas, contents could be opaque, but that
// cannot be determined from the main thread. Or can it?
if (layout_html_canvas_.DrawsBackgroundOntoContentLayer()) {
Color background_color =
layout_html_canvas_.ResolveColor(GetCSSPropertyBackgroundColor());
layer->SetBackgroundColor(background_color.Rgb());
}
if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled() &&
!flatten_composited_layers) {
IntRect pixel_snapped_rect = PixelSnappedIntRect(paint_rect);
layer->SetBounds(gfx::Size(pixel_snapped_rect.Size()));
layer->SetIsDrawable(true);
......
......@@ -109,12 +109,7 @@ void ReplacedPainter::Paint(const PaintInfo& paint_info) {
}
}
if (should_paint_background) {
if (layout_replaced_.HasLayer() &&
layout_replaced_.Layer()->GetCompositingState() ==
kPaintsIntoOwnBacking &&
layout_replaced_.Layer()
->GetCompositedLayerMapping()
->DrawsBackgroundOntoContentLayer()) {
if (layout_replaced_.DrawsBackgroundOntoContentLayer()) {
// If the background paints into the content layer, we can skip painting
// the background but still need to paint the hit test rects.
BoxPainter(layout_replaced_)
......
......@@ -591,11 +591,6 @@ void GraphicsLayer::SetContentsVisible(bool contents_visible) {
UpdateLayerIsDrawable();
}
void GraphicsLayer::SetContentsLayerBackgroundColor(Color color) {
if (contents_layer_)
contents_layer_->SetBackgroundColor(color.Rgb());
}
bool GraphicsLayer::ContentsOpaque() const {
return CcLayer().contents_opaque();
}
......
......@@ -139,8 +139,6 @@ class PLATFORM_EXPORT GraphicsLayer : public DisplayItemClient,
bool ContentsAreVisible() const { return contents_visible_; }
void SetContentsVisible(bool);
void SetContentsLayerBackgroundColor(Color color);
// Opaque means that we know the layer contents have no alpha.
bool ContentsOpaque() const;
void SetContentsOpaque(bool);
......
......@@ -15,7 +15,6 @@
{
"name": "ContentsLayer for LayoutHTMLCanvas CANVAS id='canvas-simple'",
"bounds": [50, 50],
"contentsOpaque": true,
"backgroundColor": "#008000",
"transform": 1
},
......@@ -33,6 +32,7 @@
{
"name": "LayoutHTMLCanvas CANVAS id='canvas-padding'",
"bounds": [60, 60],
"contentsOpaque": true,
"backgroundColor": "#008000",
"transform": 3
},
......@@ -45,6 +45,7 @@
{
"name": "LayoutHTMLCanvas CANVAS id='canvas-border'",
"bounds": [60, 60],
"contentsOpaque": true,
"backgroundColor": "#008000",
"transform": 4
},
......@@ -57,6 +58,7 @@
{
"name": "LayoutHTMLCanvas CANVAS id='canvas-image'",
"bounds": [50, 50],
"contentsOpaque": true,
"backgroundColor": "#008000",
"transform": 5
},
......@@ -81,6 +83,7 @@
{
"name": "LayoutHTMLCanvas CANVAS id='canvas-opaque-border'",
"bounds": [60, 60],
"contentsOpaque": true,
"backgroundColor": "#008000",
"transform": 7
},
......@@ -88,6 +91,7 @@
"name": "ContentsLayer for LayoutHTMLCanvas CANVAS id='canvas-opaque-border'",
"position": [5, 5],
"bounds": [50, 50],
"contentsOpaque": true,
"transform": 7
},
{
......@@ -99,6 +103,7 @@
{
"name": "ContentsLayer for LayoutHTMLCanvas CANVAS id='canvas-opaque-box-shadow'",
"bounds": [50, 50],
"contentsOpaque": true,
"transform": 8
}
],
......
......@@ -15,13 +15,13 @@
{
"name": "ContentsLayer for LayoutHTMLCanvas CANVAS id='canvas-simple'",
"bounds": [50, 50],
"contentsOpaque": true,
"backgroundColor": "#008000",
"transform": 1
},
{
"name": "LayoutHTMLCanvas CANVAS id='canvas-padding'",
"bounds": [60, 60],
"contentsOpaque": true,
"backgroundColor": "#008000",
"transform": 2
},
......@@ -34,6 +34,7 @@
{
"name": "LayoutHTMLCanvas CANVAS id='canvas-border'",
"bounds": [60, 60],
"contentsOpaque": true,
"backgroundColor": "#008000",
"transform": 3
},
......@@ -46,6 +47,7 @@
{
"name": "LayoutHTMLCanvas CANVAS id='canvas-image'",
"bounds": [50, 50],
"contentsOpaque": true,
"backgroundColor": "#008000",
"transform": 4
},
......
......@@ -9,24 +9,25 @@
{
"name": "LayoutHTMLCanvas CANVAS id='canvas-simple'",
"bounds": [50, 50],
"contentsOpaque": true,
"backgroundColor": "#008000",
"drawsContent": false,
"transform": 1
},
{
"name": "LayoutHTMLCanvas CANVAS id='canvas-simple'",
"bounds": [50, 50],
"backgroundColor": "#008000",
"transform": 1
},
{
"name": "LayoutHTMLCanvas CANVAS id='canvas-transparent-background'",
"bounds": [50, 50],
"backgroundColor": "#00FF0080",
"drawsContent": false,
"transform": 2
},
{
"name": "LayoutHTMLCanvas CANVAS id='canvas-transparent-background'",
"bounds": [50, 50],
"backgroundColor": "#00FF0080",
"transform": 2
},
{
......@@ -70,14 +71,14 @@
{
"name": "LayoutHTMLCanvas CANVAS id='canvas-opaque'",
"bounds": [50, 50],
"contentsOpaque": true,
"backgroundColor": "#008000",
"drawsContent": false,
"transform": 6
},
{
"name": "LayoutHTMLCanvas CANVAS id='canvas-opaque'",
"bounds": [50, 50],
"contentsOpaque": true,
"backgroundColor": "#008000",
"transform": 6
},
{
......
......@@ -9,13 +9,13 @@
{
"name": "LayoutHTMLCanvas CANVAS id='canvas-simple'",
"bounds": [50, 50],
"contentsOpaque": true,
"backgroundColor": "#008000",
"drawsContent": false,
"transform": 1
},
{
"name": "LayoutHTMLCanvas CANVAS id='canvas-simple'",
"bounds": [50, 50],
"backgroundColor": "#008000",
"transform": 1
},
{
......@@ -59,12 +59,13 @@
{
"name": "LayoutHTMLCanvas CANVAS id='canvas-transparent-background'",
"bounds": [50, 50],
"backgroundColor": "#00FF0080",
"drawsContent": false,
"transform": 5
},
{
"name": "LayoutHTMLCanvas CANVAS id='canvas-transparent-background'",
"bounds": [50, 50],
"backgroundColor": "#00FF0080",
"transform": 5
}
],
......
......@@ -16,7 +16,6 @@
{
"name": "ContentsLayer for LayoutHTMLCanvas CANVAS id='canvas-simple'",
"bounds": [75, 75],
"contentsOpaque": true,
"backgroundColor": "#008000",
"transform": 1
},
......@@ -35,6 +34,7 @@
{
"name": "LayoutHTMLCanvas CANVAS id='canvas-padding'",
"bounds": [90, 90],
"contentsOpaque": true,
"backgroundColor": "#008000",
"transform": 3
},
......@@ -47,6 +47,7 @@
{
"name": "LayoutHTMLCanvas CANVAS id='canvas-border'",
"bounds": [90, 90],
"contentsOpaque": true,
"backgroundColor": "#008000",
"transform": 4
},
......@@ -59,6 +60,7 @@
{
"name": "LayoutHTMLCanvas CANVAS id='canvas-image'",
"bounds": [75, 75],
"contentsOpaque": true,
"backgroundColor": "#008000",
"transform": 5
},
......@@ -84,6 +86,7 @@
{
"name": "LayoutHTMLCanvas CANVAS id='canvas-opaque-border'",
"bounds": [90, 90],
"contentsOpaque": true,
"backgroundColor": "#008000",
"transform": 7
},
......@@ -91,6 +94,7 @@
"name": "ContentsLayer for LayoutHTMLCanvas CANVAS id='canvas-opaque-border'",
"position": [7, 8],
"bounds": [75, 75],
"contentsOpaque": true,
"transform": 7
},
{
......@@ -102,6 +106,7 @@
{
"name": "ContentsLayer for LayoutHTMLCanvas CANVAS id='canvas-opaque-box-shadow'",
"bounds": [75, 75],
"contentsOpaque": true,
"transform": 8
}
],
......
......@@ -16,13 +16,13 @@
{
"name": "ContentsLayer for LayoutHTMLCanvas CANVAS id='canvas-simple'",
"bounds": [75, 75],
"contentsOpaque": true,
"backgroundColor": "#008000",
"transform": 1
},
{
"name": "LayoutHTMLCanvas CANVAS id='canvas-padding'",
"bounds": [90, 90],
"contentsOpaque": true,
"backgroundColor": "#008000",
"transform": 2
},
......@@ -35,6 +35,7 @@
{
"name": "LayoutHTMLCanvas CANVAS id='canvas-border'",
"bounds": [90, 90],
"contentsOpaque": true,
"backgroundColor": "#008000",
"transform": 3
},
......@@ -47,6 +48,7 @@
{
"name": "LayoutHTMLCanvas CANVAS id='canvas-image'",
"bounds": [75, 75],
"contentsOpaque": true,
"backgroundColor": "#008000",
"transform": 4
},
......
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