From ff3dc65b0f7845184458fb25b3d566fa079cd232 Mon Sep 17 00:00:00 2001 From: enne Date: Thu, 9 Jun 2016 17:52:09 -0700 Subject: [PATCH] Optimize render passes with single quads Many effects (masks, replicas, filters) generate render passes for simplicity in the code. However, in the cases where the pass contains a single quad with a texture, that resulting texture could just be used as the input texture instead of the render pass itself. The complication is mostly that render passes and tile textures are flipped relative to each other (oops) and so some knowledge of this has to leak into drawing render passes. This is done by detecting such render passes inside of DirectRenderer, storing the TileQuad that would have been drawn, skipping allocating the pass and rendering it, and then calling a slightly modified version of DrawRenderPassQuad with the TileQuad's resource. The check for which render passes can be supported is conservative to start. This optimization usually will not be supported on mac because skia does not support textures with texture rectangle targets as input. BUG=254639,606672 CQ_INCLUDE_TRYBOTS=tryserver.blink:linux_blink_rel Review-Url: https://codereview.chromium.org/1960543002 Cr-Commit-Position: refs/heads/master@{#399060} --- cc/output/direct_renderer.cc | 23 ++- cc/output/direct_renderer.h | 8 + cc/output/gl_renderer.cc | 142 ++++++++++++++---- cc/output/gl_renderer.h | 7 + .../data/rotated_drop_shadow_filter_gl.png | Bin 2250 -> 2141 bytes .../data/rotated_drop_shadow_filter_sw.png | Bin 1643 -> 1650 bytes cc/test/solid_color_content_layer_client.cc | 18 ++- cc/test/solid_color_content_layer_client.h | 12 +- cc/trees/layer_tree_host_pixeltest_filters.cc | 12 +- cc/trees/layer_tree_host_pixeltest_masks.cc | 36 +++++ .../WebKit/LayoutTests/TestExpectations | 23 +++ .../effect-all-on-background-hw-expected.html | 34 ----- 12 files changed, 243 insertions(+), 72 deletions(-) delete mode 100644 third_party/WebKit/LayoutTests/css3/filters/effect-all-on-background-hw-expected.html diff --git a/cc/output/direct_renderer.cc b/cc/output/direct_renderer.cc index 7554a97e35432..59bd670c0416a 100644 --- a/cc/output/direct_renderer.cc +++ b/cc/output/direct_renderer.cc @@ -141,14 +141,26 @@ DirectRenderer::DirectRenderer(RendererClient* client, DirectRenderer::~DirectRenderer() {} +const TileDrawQuad* DirectRenderer::CanPassBeDrawnDirectly( + const RenderPass* pass) { + return nullptr; +} + void DirectRenderer::DecideRenderPassAllocationsForFrame( const RenderPassList& render_passes_in_draw_order) { + render_pass_bypass_quads_.clear(); + std::unordered_map render_passes_in_frame; - for (size_t i = 0; i < render_passes_in_draw_order.size(); ++i) + for (size_t i = 0; i < render_passes_in_draw_order.size(); ++i) { + RenderPass* pass = render_passes_in_draw_order[i].get(); + if (const TileDrawQuad* tile_quad = CanPassBeDrawnDirectly(pass)) { + render_pass_bypass_quads_[pass->id] = *tile_quad; + continue; + } render_passes_in_frame.insert(std::pair( - render_passes_in_draw_order[i]->id, - RenderPassTextureSize(render_passes_in_draw_order[i].get()))); + pass->id, RenderPassTextureSize(pass))); + } std::vector passes_to_delete; for (auto pass_iter = render_pass_textures_.begin(); @@ -405,6 +417,11 @@ void DirectRenderer::FlushPolygons( void DirectRenderer::DrawRenderPassAndExecuteCopyRequests( DrawingFrame* frame, RenderPass* render_pass) { + if (render_pass_bypass_quads_.find(render_pass->id) != + render_pass_bypass_quads_.end()) { + return; + } + DrawRenderPass(frame, render_pass); bool first_request = true; diff --git a/cc/output/direct_renderer.h b/cc/output/direct_renderer.h index 53339a69e81c9..9f15ca40d467b 100644 --- a/cc/output/direct_renderer.h +++ b/cc/output/direct_renderer.h @@ -13,6 +13,7 @@ #include "cc/output/ca_layer_overlay.h" #include "cc/output/overlay_processor.h" #include "cc/output/renderer.h" +#include "cc/quads/tile_draw_quad.h" #include "cc/raster/task_graph_runner.h" #include "cc/resources/resource_provider.h" #include "cc/resources/scoped_resource.h" @@ -39,6 +40,11 @@ class CC_EXPORT DirectRenderer : public Renderer { bool disable_picture_quad_image_filtering) override; virtual void SwapBuffersComplete() {} + // If a pass contains a single tile draw quad and can be drawn without + // a render pass (e.g. applying a filter directly to the tile quad) + // return that quad, otherwise return null. + virtual const TileDrawQuad* CanPassBeDrawnDirectly(const RenderPass* pass); + struct CC_EXPORT DrawingFrame { DrawingFrame(); ~DrawingFrame(); @@ -152,6 +158,8 @@ class CC_EXPORT DirectRenderer : public Renderer { std::unique_ptr, RenderPassIdHash> render_pass_textures_; + std::unordered_map + render_pass_bypass_quads_; OutputSurface* output_surface_; ResourceProvider* resource_provider_; std::unique_ptr overlay_processor_; diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc index 7cf5a00face44..b7528aaa4f696 100644 --- a/cc/output/gl_renderer.cc +++ b/cc/output/gl_renderer.cc @@ -589,7 +589,8 @@ void GLRenderer::DrawDebugBorderQuad(const DrawingFrame* frame, static sk_sp WrapTexture( const ResourceProvider::ScopedReadLockGL& lock, - GrContext* context) { + GrContext* context, + bool flip_texture) { // Wrap a given texture in a Ganesh platform texture. GrBackendTextureDesc backend_texture_description; GrGLTextureInfo texture_info; @@ -600,7 +601,8 @@ static sk_sp WrapTexture( backend_texture_description.fConfig = kSkia8888_GrPixelConfig; backend_texture_description.fTextureHandle = skia::GrGLTextureInfoToGrBackendObject(texture_info); - backend_texture_description.fOrigin = kBottomLeft_GrSurfaceOrigin; + backend_texture_description.fOrigin = + flip_texture ? kBottomLeft_GrSurfaceOrigin : kTopLeft_GrSurfaceOrigin; return SkImage::MakeFromTexture(context, backend_texture_description); } @@ -612,16 +614,19 @@ static sk_sp ApplyImageFilter( const gfx::RectF& dst_rect, const gfx::Vector2dF& scale, sk_sp filter, - ScopedResource* source_texture_resource, + const Resource* source_texture_resource, SkIPoint* offset, - SkIRect* subset) { + SkIRect* subset, + bool flip_texture) { if (!filter || !use_gr_context) return nullptr; ResourceProvider::ScopedReadLockGL lock(resource_provider, source_texture_resource->id()); - sk_sp src_image = WrapTexture(lock, use_gr_context->context()); + sk_sp src_image = + WrapTexture(lock, use_gr_context->context(), flip_texture); + if (!src_image) { TRACE_EVENT_INSTANT0("cc", "ApplyImageFilter wrap background texture failed", @@ -636,7 +641,7 @@ static sk_sp ApplyImageFilter( SkIRect clip_bounds = gfx::RectFToSkRect(dst_rect).roundOut(); clip_bounds.offset(-src_rect.x(), -src_rect.y()); filter = filter->makeWithLocalMatrix(local_matrix); - SkIRect in_subset = SkIRect::MakeWH(src_image->width(), src_image->height()); + SkIRect in_subset = SkIRect::MakeWH(src_rect.width(), src_rect.height()); sk_sp image = src_image->makeWithFilter(filter.get(), in_subset, clip_bounds, subset, offset); @@ -852,7 +857,9 @@ sk_sp GLRenderer::ApplyBackgroundFilters( ResourceProvider::ScopedReadLockGL lock(resource_provider_, background_texture->id()); - sk_sp src_image = WrapTexture(lock, use_gr_context->context()); + bool flip_texture = true; + sk_sp src_image = + WrapTexture(lock, use_gr_context->context(), flip_texture); if (!src_image) { TRACE_EVENT_INSTANT0( "cc", "ApplyBackgroundFilters wrap background texture failed", @@ -910,14 +917,82 @@ gfx::QuadF MapQuadToLocalSpace(const gfx::Transform& device_transform, return local_quad; } +const TileDrawQuad* GLRenderer::CanPassBeDrawnDirectly(const RenderPass* pass) { + // Can only collapse a single tile quad. + if (pass->quad_list.size() != 1) + return nullptr; + // If we need copy requests, then render pass has to exist. + if (!pass->copy_requests.empty()) + return nullptr; + + const DrawQuad* quad = *pass->quad_list.BackToFrontBegin(); + // Hack: this could be supported by concatenating transforms, but + // in practice if there is one quad, it is at the origin of the render pass. + if (!quad->shared_quad_state->quad_to_target_transform.IsIdentity()) + return nullptr; + // The quad is expected to be the entire layer so that AA edges are correct. + if (gfx::Rect(quad->shared_quad_state->quad_layer_bounds) != quad->rect) + return nullptr; + if (quad->material != DrawQuad::TILED_CONTENT) + return nullptr; + + const TileDrawQuad* tile_quad = TileDrawQuad::MaterialCast(quad); + // Hack: this could be supported by passing in a subrectangle to draw + // render pass, although in practice if there is only one quad there + // will be no border texels on the input. + if (tile_quad->tex_coord_rect != gfx::RectF(tile_quad->rect)) + return nullptr; + // Tile quad features not supported in render pass shaders. + if (tile_quad->swizzle_contents || tile_quad->nearest_neighbor) + return nullptr; + // BUG=skia:3868, Skia currently doesn't support texture rectangle inputs. + // See also the DCHECKs about GL_TEXTURE_2D in DrawRenderPassQuad. + GLenum target = + resource_provider_->GetResourceTextureTarget(tile_quad->resource_id()); + if (target != GL_TEXTURE_2D) + return nullptr; +#if defined(OS_MACOSX) + // On Macs, this path can sometimes lead to all black output. + // TODO(enne): investigate this and remove this hack. + return nullptr; +#endif + + return tile_quad; +} + void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, const RenderPassDrawQuad* quad, const gfx::QuadF* clip_region) { - ScopedResource* contents_texture = - render_pass_textures_[quad->render_pass_id].get(); - DCHECK(contents_texture); - DCHECK(contents_texture->id()); - + auto bypass = render_pass_bypass_quads_.find(quad->render_pass_id); + if (bypass != render_pass_bypass_quads_.end()) { + TileDrawQuad* tile_quad = &bypass->second; + // RGBA_8888 here is arbitrary and unused. + Resource tile_resource(tile_quad->resource_id(), tile_quad->texture_size, + ResourceFormat::RGBA_8888); + // The projection matrix used by GLRenderer has a flip. As tile texture + // inputs are oriented opposite to framebuffer outputs, don't flip via + // texture coords and let the projection matrix naturallyd o it. + bool flip_texture = false; + DrawRenderPassQuadInternal(frame, quad, clip_region, &tile_resource, + flip_texture); + } else { + ScopedResource* contents_texture = + render_pass_textures_[quad->render_pass_id].get(); + DCHECK(contents_texture); + DCHECK(contents_texture->id()); + // See above comments about texture flipping. When the input is a + // render pass, it needs to an extra flip to be oriented correctly. + bool flip_texture = true; + DrawRenderPassQuadInternal(frame, quad, clip_region, contents_texture, + flip_texture); + } +} + +void GLRenderer::DrawRenderPassQuadInternal(DrawingFrame* frame, + const RenderPassDrawQuad* quad, + const gfx::QuadF* clip_region, + const Resource* contents_texture, + bool flip_texture) { SkMatrix scale_matrix; scale_matrix.setScale(quad->filters_scale.x(), quad->filters_scale.y()); gfx::RectF dst_rect(quad->filters.MapRect(quad->rect, scale_matrix)); @@ -1022,7 +1097,6 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, SkScalar color_matrix[20]; bool use_color_matrix = false; gfx::Size texture_size = contents_texture->size(); - bool flip_texture = true; gfx::Point src_offset; if (!quad->filters.IsEmpty()) { sk_sp filter = RenderSurfaceFilters::BuildImageFilter( @@ -1057,13 +1131,12 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, SkIPoint offset; SkIRect subset; gfx::RectF src_rect(quad->rect); - filter_image = ApplyImageFilter(ScopedUseGrContext::Create(this, frame), - resource_provider_, src_rect, dst_rect, - quad->filters_scale, std::move(filter), - contents_texture, &offset, &subset); - if (!filter_image) { + filter_image = ApplyImageFilter( + ScopedUseGrContext::Create(this, frame), resource_provider_, + src_rect, dst_rect, quad->filters_scale, std::move(filter), + contents_texture, &offset, &subset, flip_texture); + if (!filter_image) return; - } filter_image_id = skia::GrBackendObjectToGrGLTextureInfo( filter_image->getTextureHandle(true)) ->fID; @@ -1074,6 +1147,7 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, gfx::RectF(src_rect.x() + offset.fX, src_rect.y() + offset.fY, subset.width(), subset.height()); src_offset.SetPoint(subset.x(), subset.y()); + // If the output of the filter needs to be flipped. flip_texture = filter_image->getTexture()->origin() == kBottomLeft_GrSurfaceOrigin; } @@ -1199,6 +1273,8 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, gl_->Uniform4f(locations.tex_transform, tex_rect.x(), 1.0f - tex_rect.y(), tex_rect.width(), -tex_rect.height()); } else { + // Tile textures are oriented opposite the framebuffer, so can use + // the projection transform to do the flip. gl_->Uniform4f(locations.tex_transform, tex_rect.x(), tex_rect.y(), tex_rect.width(), tex_rect.height()); } @@ -1214,16 +1290,24 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, mask_uv_rect.Scale(quad->mask_texture_size.width(), quad->mask_texture_size.height()); } - - // Mask textures are oriented vertically flipped relative to the framebuffer - // and the RenderPass contents texture, so we flip the tex coords from the - // RenderPass texture to find the mask texture coords. - gl_->Uniform2f( - locations.mask_tex_coord_offset, mask_uv_rect.x(), - mask_uv_rect.height() / tex_rect.height() + mask_uv_rect.y()); - gl_->Uniform2f(locations.mask_tex_coord_scale, - mask_uv_rect.width() / tex_rect.width(), - -mask_uv_rect.height() / tex_rect.height()); + if (flip_texture) { + // Mask textures are oriented vertically flipped relative to the + // framebuffer and the RenderPass contents texture, so we flip the tex + // coords from the RenderPass texture to find the mask texture coords. + gl_->Uniform2f( + locations.mask_tex_coord_offset, mask_uv_rect.x(), + mask_uv_rect.height() / tex_rect.height() + mask_uv_rect.y()); + gl_->Uniform2f(locations.mask_tex_coord_scale, + mask_uv_rect.width() / tex_rect.width(), + -mask_uv_rect.height() / tex_rect.height()); + } else { + // Tile textures are oriented the same way as mask textures. + gl_->Uniform2f(locations.mask_tex_coord_offset, mask_uv_rect.x(), + mask_uv_rect.y()); + gl_->Uniform2f(locations.mask_tex_coord_scale, + mask_uv_rect.width() / tex_rect.width(), + mask_uv_rect.height() / tex_rect.height()); + } last_texture_unit = 1; } diff --git a/cc/output/gl_renderer.h b/cc/output/gl_renderer.h index 5a74c08d3a9d2..6df1fdf041075 100644 --- a/cc/output/gl_renderer.h +++ b/cc/output/gl_renderer.h @@ -177,9 +177,16 @@ class CC_EXPORT GLRenderer : public DirectRenderer { ScopedResource* background_texture, const gfx::RectF& rect); + const TileDrawQuad* CanPassBeDrawnDirectly(const RenderPass* pass) override; + void DrawRenderPassQuad(DrawingFrame* frame, const RenderPassDrawQuad* quadi, const gfx::QuadF* clip_region); + void DrawRenderPassQuadInternal(DrawingFrame* frame, + const RenderPassDrawQuad* quad, + const gfx::QuadF* clip_region, + const Resource* contents_texture, + bool is_render_pass_input); void DrawSolidColorQuad(const DrawingFrame* frame, const SolidColorDrawQuad* quad, const gfx::QuadF* clip_region); diff --git a/cc/test/data/rotated_drop_shadow_filter_gl.png b/cc/test/data/rotated_drop_shadow_filter_gl.png index 211c9c66e912cbaaa48571dca316f3d452a3835d..82b55f57efa67d7280fc477676e0a3ec395fbeb9 100644 GIT binary patch literal 2141 zcmd5;Yfuws6b*K?tAG%25Dl6+wt469Ncv%pyK8 z_Ti)jd6+Vd?N|hbVhY6AD6fJ7W^9ZBVvt>95)!J9qc&_nmvs zxp(K=(}^Ua{VMlWC=|+m*G|GGD3lEjzJO&AGL3QbL7@P@U4(6)v8!~$!GBudxNJPr38TP1AdIgfA=55jb@|G z!oxBL3{6rZmPj}Z2E)vL(W{EGkjU(pcYZjdN|FJi1(qo}Ctju!W=13!I9{U@k_DYM zGGQ^fP^yVmPX~_cj%e1Nh^S#Onask%%Bb|AG!=098ChnGGsOrqD_L#BIbj@gVeRpW zV^YPU*8Ql((9bDZv=p1dPS0n#t66Q;Las3>Re4b;&V&fcF{XKoB~8|KiyK<}OGtm7 z(v}dSK7PEfN#Wt;RZ~^9V3d*jYoj@OO^5PEu8i1yLdY4|PH7RFr(iL; zC3B*#+lxOxb87VrND(ccI&)1TL?=tHmkONeoPR9FHg3!iYTkHmz==7r5SS;?^yn4Jo6U-s@;?$FsI}WYvZ4U}*w`RjKBOay6fB<@h9K4O} zZ2DVFq2QzC^%CLd-EZgH8q06&TNiTMSv}^GLkxh5?*CFbc)b)ml)dSEp2tuM!ix2v z$wCgi$_P_HB`OCk)++p=mrJP&PvYnm@M;*qw1y(}1;>S3V{~;s+sC6iH_5KyEg|D) z1~~X25Y|#zS~RHDY9X;+-=~9Z!{aYs_JkG$H68Mn*45R$f)6%ktCtI~9{4UmydKvC zW(@>E9c*a?eP9U649G7X0r`zm-IzPGoY6L%EOn0)t?=|^MkGV4$hA?$RochiTXu|{ zs|ZG3Ak$;N1$Nbip9sc|xkBzQ5g%MBzmyKqWz$zWI5=QN!`Y{JP^qtX+CmTB%}^(I zi#+#od1%wa}%k^M^Dv`KFY9BD5w%o#?B(LW{_ohDT^lf9v41CKkRW6@lu z<@#ld&mUZgu;h$!wE3G8l$no6GO9*ZLgq67?Oy-U0=1W2XD|&^>ZEPx)Fv?2H4q=y z{d@UZ0ro&f=h*=#m#sz9xMJXfor^l>Mw>{q6Vu_!Tv{Z4n zi~55tC9E};#1%yezzg4ZeQdmglj{GOaz4!7pIel%zElDIHlTKGClRjV_nr6?;$o*< literal 2250 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 pLmMdQASnnMyQ7?;6d)hti{00perGsa6 canvas = sk_ref_sp(recorder.beginRecording(gfx::RectToSkRect(clip))); + canvas->clear(SK_ColorTRANSPARENT); + + if (border_size_ != 0) { + SkPaint paint; + paint.setStyle(SkPaint::kFill_Style); + paint.setColor(border_color_); + canvas->drawRect( + SkRect::MakeXYWH(clip.x(), clip.y(), clip.width(), clip.height()), + paint); + } + SkPaint paint; paint.setStyle(SkPaint::kFill_Style); paint.setColor(color_); - - canvas->clear(SK_ColorTRANSPARENT); canvas->drawRect( - SkRect::MakeXYWH(clip.x(), clip.y(), clip.width(), clip.height()), paint); + SkRect::MakeXYWH(clip.x() + border_size_, clip.y() + border_size_, + clip.width() - 2 * border_size_, + clip.height() - 2 * border_size_), + paint); DisplayItemListSettings settings; settings.use_cached_picture = false; diff --git a/cc/test/solid_color_content_layer_client.h b/cc/test/solid_color_content_layer_client.h index d765f94d346d7..d8fcd70c48a85 100644 --- a/cc/test/solid_color_content_layer_client.h +++ b/cc/test/solid_color_content_layer_client.h @@ -16,7 +16,15 @@ namespace cc { class SolidColorContentLayerClient : public ContentLayerClient { public: explicit SolidColorContentLayerClient(SkColor color, gfx::Size size) - : color_(color), size_(size) {} + : color_(color), size_(size), border_size_(0), border_color_(0) {} + explicit SolidColorContentLayerClient(SkColor color, + gfx::Size size, + int border_size, + SkColor border_color) + : color_(color), + size_(size), + border_size_(border_size), + border_color_(border_color) {} gfx::Rect PaintableRegion() override; @@ -29,6 +37,8 @@ class SolidColorContentLayerClient : public ContentLayerClient { private: SkColor color_; gfx::Size size_; + int border_size_; + SkColor border_color_; }; } // namespace cc diff --git a/cc/trees/layer_tree_host_pixeltest_filters.cc b/cc/trees/layer_tree_host_pixeltest_filters.cc index 9455da3acf340..5e974fe3530ac 100644 --- a/cc/trees/layer_tree_host_pixeltest_filters.cc +++ b/cc/trees/layer_tree_host_pixeltest_filters.cc @@ -5,9 +5,11 @@ #include #include "build/build_config.h" +#include "cc/layers/picture_layer.h" #include "cc/layers/solid_color_layer.h" #include "cc/test/layer_tree_pixel_test.h" #include "cc/test/pixel_comparator.h" +#include "cc/test/solid_color_content_layer_client.h" #include "third_party/skia/include/effects/SkColorFilterImageFilter.h" #include "third_party/skia/include/effects/SkColorMatrixFilter.h" #include "third_party/skia/include/effects/SkOffsetImageFilter.h" @@ -585,8 +587,14 @@ class RotatedDropShadowFilterTest : public LayerTreeHostFiltersPixelTest { gfx::Rect rect(50, 50, 100, 100); - scoped_refptr child = - CreateSolidColorLayer(rect, SK_ColorBLUE); + // Use a border to defeat solid color detection to force a tile quad. + // This is intended to test render pass removal optimizations. + SolidColorContentLayerClient blue_client(SK_ColorBLUE, rect.size(), 1, + SK_ColorBLACK); + scoped_refptr child = PictureLayer::Create(&blue_client); + child->SetBounds(rect.size()); + child->SetPosition(gfx::PointF(rect.origin())); + child->SetIsDrawable(true); gfx::Transform transform; transform.Translate(50.0f, 50.0f); diff --git a/cc/trees/layer_tree_host_pixeltest_masks.cc b/cc/trees/layer_tree_host_pixeltest_masks.cc index a638078147028..9ca88ff0e376c 100644 --- a/cc/trees/layer_tree_host_pixeltest_masks.cc +++ b/cc/trees/layer_tree_host_pixeltest_masks.cc @@ -13,6 +13,7 @@ #include "cc/playback/drawing_display_item.h" #include "cc/test/layer_tree_pixel_resource_test.h" #include "cc/test/pixel_comparator.h" +#include "cc/test/solid_color_content_layer_client.h" #include "third_party/skia/include/core/SkImage.h" #include "third_party/skia/include/core/SkPictureRecorder.h" #include "third_party/skia/include/core/SkSurface.h" @@ -178,6 +179,41 @@ TEST_P(LayerTreeHostMasksPixelTest, MaskWithReplica) { background, base::FilePath(FILE_PATH_LITERAL("mask_with_replica.png"))); } +// Test collapsing of render passes containing a single tile quad and +// drawing them directly with masks and replicas. +TEST_P(LayerTreeHostMasksPixelTest, ContentLayerMaskWithReplica) { + scoped_refptr background = + CreateSolidColorLayer(gfx::Rect(100, 100), SK_ColorWHITE); + + gfx::Size mask_bounds(50, 50); + MaskContentLayerClient client(mask_bounds); + scoped_refptr mask = PictureLayer::Create(&client); + mask->SetBounds(mask_bounds); + mask->SetIsDrawable(true); + mask->SetIsMask(true); + + // Use a border to defeat solid color detection to force a tile quad. + SolidColorContentLayerClient green_client(kCSSGreen, mask_bounds, 1, + SK_ColorBLACK); + scoped_refptr green = PictureLayer::Create(&green_client); + green->SetBounds(mask_bounds); + green->SetIsDrawable(true); + background->AddChild(green); + green->SetMaskLayer(mask.get()); + + gfx::Transform replica_transform; + replica_transform.Rotate(-90.0); + + scoped_refptr replica = Layer::Create(); + replica->SetTransformOrigin(gfx::Point3F(25.f, 25.f, 0.f)); + replica->SetPosition(gfx::PointF(50.f, 50.f)); + replica->SetTransform(replica_transform); + green->SetReplicaLayer(replica.get()); + + RunPixelResourceTest( + background, base::FilePath(FILE_PATH_LITERAL("mask_with_replica.png"))); +} + TEST_P(LayerTreeHostMasksPixelTest, MaskWithReplicaOfClippedLayer) { scoped_refptr background = CreateSolidColorLayer( gfx::Rect(100, 100), SK_ColorWHITE); diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index 96fd581b1068e..2085a3344f187 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations @@ -1290,6 +1290,29 @@ crbug.com/587779 [ Linux Mac10.9 Mac10.10 Mac10.11 Retina ] fast/dynamic/window- crbug.com/588103 fast/xmlhttprequest/xmlhttprequest-responsetype-arraybuffer.html [ Pass Failure ] +crbug.com/254639 compositing/masks/direct-image-mask.html [ NeedsRebaseline ] +crbug.com/254639 compositing/reflections/nested-reflection-anchor-point.html [ NeedsRebaseline ] +crbug.com/254639 compositing/reflections/nested-reflection-animated.html [ NeedsRebaseline ] +crbug.com/254639 compositing/reflections/nested-reflection-opacity.html [ NeedsRebaseline ] +crbug.com/254639 css3/blending/effect-background-blend-mode-stacking.html [ NeedsRebaseline ] +crbug.com/254639 css3/filters/composited-reflected.html [ NeedsRebaseline ] +crbug.com/254639 css3/filters/effect-all-on-background-hw.html [ NeedsRebaseline ] +crbug.com/254639 css3/filters/effect-brightness-clamping-hw.html [ NeedsRebaseline ] +crbug.com/254639 css3/filters/effect-brightness-hw.html [ NeedsRebaseline ] +crbug.com/254639 css3/filters/effect-contrast-hw.html [ NeedsRebaseline ] +crbug.com/254639 css3/filters/effect-grayscale-hw.html [ NeedsRebaseline ] +crbug.com/254639 css3/filters/effect-hue-rotate-hw.html [ NeedsRebaseline ] +crbug.com/254639 css3/filters/effect-reference-colorspace-hw.html [ NeedsRebaseline ] +crbug.com/254639 css3/filters/effect-reference-hidpi-hw.html [ NeedsRebaseline ] +crbug.com/254639 css3/filters/effect-reference-hw.html [ NeedsRebaseline ] +crbug.com/254639 css3/filters/effect-reference-ordering-hw.html [ NeedsRebaseline ] +crbug.com/254639 css3/filters/effect-reference-subregion-hw.html [ NeedsRebaseline ] +crbug.com/254639 css3/filters/effect-reference-zoom-hw.html [ NeedsRebaseline ] +crbug.com/254639 css3/filters/effect-saturate-hw.html [ NeedsRebaseline ] +crbug.com/254639 css3/filters/effect-sepia-hw.html [ NeedsRebaseline ] +crbug.com/254639 compositing/reflections/nested-reflection-transformed.html [ NeedsRebaseline ] +crbug.com/254639 compositing/reflections/nested-reflection-transformed2.html [ NeedsRebaseline ] + crbug.com/594672 fast/events/iframe-object-onload.html [ Failure Pass ] crbug.com/594672 fast/events/scale-and-scroll-iframe-body.html [ Failure Pass ] crbug.com/594672 fast/events/updateLayoutForHitTest.html [ Failure Pass ] diff --git a/third_party/WebKit/LayoutTests/css3/filters/effect-all-on-background-hw-expected.html b/third_party/WebKit/LayoutTests/css3/filters/effect-all-on-background-hw-expected.html deleted file mode 100644 index 6d8fd2e662185..0000000000000 --- a/third_party/WebKit/LayoutTests/css3/filters/effect-all-on-background-hw-expected.html +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - -
    -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -