diff options
author | danakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-12 19:51:46 +0000 |
---|---|---|
committer | danakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-12 19:51:46 +0000 |
commit | 4bdeb9865d23bec03b7a16dfb7d74dc69d5f399e (patch) | |
tree | a52f2f39053e073b4aa26c9879d79bd4a7b17d22 | |
parent | b6a6de7a7d4b2b8a1a2fe8abf0b910646a112139 (diff) | |
download | chromium_src-4bdeb9865d23bec03b7a16dfb7d74dc69d5f399e.zip chromium_src-4bdeb9865d23bec03b7a16dfb7d74dc69d5f399e.tar.gz chromium_src-4bdeb9865d23bec03b7a16dfb7d74dc69d5f399e.tar.bz2 |
cc: Fix masks when the RenderPassDrawQuad does not cover the whole pass
If the RenderPassDrawQuad is not the same size as the texture backing
the RenderPass, then we have to scale the texture coordinates when
reading the pass texture.
If the pass has a mask as well, we have to scale those coordinates as
well. However the coordinates given to the mask shader are already
scaled to the size of the contents texture. We further scale and
offset the coordinates but the offset was incorrect.
Tested by:
RendererPixelTest.RenderPassAndMaskWithPartialQuad
LayerTreeHostMasksPixelTest.MaskOfClippedLayer
R=enne
BUG=264534
Review URL: https://codereview.chromium.org/27040003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@228376 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | cc/output/gl_renderer.cc | 7 | ||||
-rw-r--r-- | cc/output/renderer_pixeltest.cc | 113 |
2 files changed, 111 insertions, 9 deletions
diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc index 04c1158..bf76071 100644 --- a/cc/output/gl_renderer.cc +++ b/cc/output/gl_renderer.cc @@ -1011,9 +1011,10 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, // and the RenderPass contents texture, so we flip the tex coords from the // RenderPass texture to find the mask texture coords. GLC(Context(), - Context()->uniform2f(shader_mask_tex_coord_offset_location, - quad->mask_uv_rect.x(), - quad->mask_uv_rect.y() + mask_tex_scale_y)); + Context()->uniform2f( + shader_mask_tex_coord_offset_location, + quad->mask_uv_rect.x(), + quad->mask_uv_rect.y() + quad->mask_uv_rect.height())); GLC(Context(), Context()->uniform2f(shader_mask_tex_coord_scale_location, mask_tex_scale_x, diff --git a/cc/output/renderer_pixeltest.cc b/cc/output/renderer_pixeltest.cc index 278b30a..a98ab84 100644 --- a/cc/output/renderer_pixeltest.cc +++ b/cc/output/renderer_pixeltest.cc @@ -84,12 +84,12 @@ scoped_ptr<DrawQuad> CreateTestRenderPassDrawQuad( quad->SetNew(shared_state, rect, pass_id, - false, // is_replica - 0, // mask_resource_id - rect, // contents_changed_since_last_frame - gfx::RectF(), // mask_uv_rect - FilterOperations(), // foreground filters - FilterOperations()); // background filters + false, // is_replica + 0, // mask_resource_id + rect, // contents_changed_since_last_frame + gfx::RectF(1.f, 1.f), // mask_uv_rect + FilterOperations(), // foreground filters + FilterOperations()); // background filters return quad.PassAs<DrawQuad>(); } @@ -882,6 +882,107 @@ TYPED_TEST(RendererPixelTest, EnlargedRenderPassTextureWithAntiAliasing) { FuzzyPixelOffByOneComparator(true))); } +// This tests the case where we have a RenderPass with a mask, but the quad +// for the masked surface does not include the full surface texture. +TYPED_TEST(RendererPixelTest, RenderPassAndMaskWithPartialQuad) { + gfx::Rect viewport_rect(this->device_viewport_size_); + + RenderPass::Id root_pass_id(1, 1); + scoped_ptr<RenderPass> root_pass = + CreateTestRootRenderPass(root_pass_id, viewport_rect); + scoped_ptr<SharedQuadState> root_pass_shared_state = + CreateTestSharedQuadState(gfx::Transform(), viewport_rect); + + RenderPass::Id child_pass_id(2, 2); + gfx::Transform transform_to_root; + scoped_ptr<RenderPass> child_pass = + CreateTestRenderPass(child_pass_id, viewport_rect, transform_to_root); + scoped_ptr<SharedQuadState> child_pass_shared_state = + CreateTestSharedQuadState(gfx::Transform(), viewport_rect); + + // The child render pass is just a green box. + static const SkColor kCSSGreen = 0xff008000; + scoped_ptr<SolidColorDrawQuad> green = SolidColorDrawQuad::Create(); + green->SetNew(child_pass_shared_state.get(), viewport_rect, kCSSGreen, false); + child_pass->quad_list.push_back(green.PassAs<DrawQuad>()); + + // Make a mask. + gfx::Rect mask_rect = viewport_rect; + SkBitmap bitmap; + bitmap.setConfig( + SkBitmap::kARGB_8888_Config, mask_rect.width(), mask_rect.height()); + bitmap.allocPixels(); + SkBitmapDevice bitmap_device(bitmap); + skia::RefPtr<SkCanvas> canvas = skia::AdoptRef(new SkCanvas(&bitmap_device)); + SkPaint paint; + paint.setStyle(SkPaint::kStroke_Style); + paint.setStrokeWidth(SkIntToScalar(4)); + paint.setColor(SK_ColorWHITE); + canvas->clear(SK_ColorTRANSPARENT); + gfx::Rect rect = mask_rect; + while (!rect.IsEmpty()) { + rect.Inset(6, 6, 4, 4); + canvas->drawRect( + SkRect::MakeXYWH(rect.x(), rect.y(), rect.width(), rect.height()), + paint); + rect.Inset(6, 6, 4, 4); + } + + ResourceProvider::ResourceId mask_resource_id = + this->resource_provider_->CreateResource( + mask_rect.size(), + GL_CLAMP_TO_EDGE, + ResourceProvider::TextureUsageAny, + RGBA_8888); + { + SkAutoLockPixels lock(bitmap); + this->resource_provider_->SetPixels( + mask_resource_id, + reinterpret_cast<uint8_t*>(bitmap.getPixels()), + mask_rect, + mask_rect, + gfx::Vector2d()); + } + + // This RenderPassDrawQuad does not include the full |viewport_rect| which is + // the size of the child render pass. + gfx::Rect sub_rect = gfx::Rect(50, 50, 100, 100); + EXPECT_NE(sub_rect.x(), child_pass->output_rect.x()); + EXPECT_NE(sub_rect.y(), child_pass->output_rect.y()); + EXPECT_NE(sub_rect.right(), child_pass->output_rect.right()); + EXPECT_NE(sub_rect.bottom(), child_pass->output_rect.bottom()); + EXPECT_TRUE(child_pass->output_rect.Contains(sub_rect)); + + // Set up a mask on the RenderPassDrawQuad. + scoped_ptr<RenderPassDrawQuad> mask_quad = RenderPassDrawQuad::Create(); + mask_quad->SetNew(root_pass_shared_state.get(), + sub_rect, + child_pass_id, + false, // is_replica + mask_resource_id, + sub_rect, // contents_changed_since_last_frame + gfx::RectF(1.f, 1.f), // mask_uv_rect + FilterOperations(), // foreground filters + FilterOperations()); // background filters + root_pass->quad_list.push_back(mask_quad.PassAs<DrawQuad>()); + + // White background behind the masked render pass. + scoped_ptr<SolidColorDrawQuad> white = SolidColorDrawQuad::Create(); + white->SetNew( + root_pass_shared_state.get(), viewport_rect, SK_ColorWHITE, false); + root_pass->quad_list.push_back(white.PassAs<DrawQuad>()); + + RenderPassList pass_list; + pass_list.push_back(child_pass.Pass()); + pass_list.push_back(root_pass.Pass()); + + EXPECT_TRUE(this->RunPixelTest( + &pass_list, + PixelTest::NoOffscreenContext, + base::FilePath(FILE_PATH_LITERAL("image_mask_of_layer.png")), + ExactPixelComparator(true))); +} + template <typename RendererType> class RendererPixelTestWithBackgroundFilter : public RendererPixelTest<RendererType> { |