From 6bec38a3e9548f6ba73d300a3722581121da818a Mon Sep 17 00:00:00 2001 From: "danakj@chromium.org" Date: Wed, 8 May 2013 23:52:14 +0000 Subject: cc: Fix readback from non-root layers. The readback was assuming that it was reading from the root render pass, so using the full viewport size when flipping the result, but it should use the size of the currently bound framebuffer. Also, it should not flip if the readback is already in the correct orientation. Tests: LayerTreeHostReadbackPixelTest.ReadbackRootLayer LayerTreeHostReadbackPixelTest.ReadbackRootLayerWithChild LayerTreeHostReadbackPixelTest.ReadbackNonRootLayer LayerTreeHostReadbackPixelTest.ReadbackSmallNonRootLayer LayerTreeHostReadbackPixelTest.ReadbackSmallNonRootLayerWithChild RendererPixelTest.SimpleGreenRect_NonRootRenderPass R=piman@chromium.org BUG=179896 Review URL: https://codereview.chromium.org/15004009 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@199055 0039d316-1c4b-4281-b951-d872f2087c98 --- cc/cc_tests.gyp | 1 + cc/output/direct_renderer.cc | 8 +- cc/output/gl_renderer.cc | 31 +++++-- cc/output/gl_renderer.h | 6 +- cc/output/gl_renderer_unittest.cc | 72 +++++++++++++++ cc/output/renderer_pixeltest.cc | 118 ++++++++++--------------- cc/output/software_renderer.cc | 1 + cc/test/layer_tree_pixel_test.cc | 15 +++- cc/test/layer_tree_pixel_test.h | 5 ++ cc/test/pixel_test.cc | 13 ++- cc/test/pixel_test.h | 5 ++ cc/trees/layer_tree_host_pixeltest_readback.cc | 94 ++++++++++++++++++++ 12 files changed, 285 insertions(+), 84 deletions(-) create mode 100644 cc/trees/layer_tree_host_pixeltest_readback.cc diff --git a/cc/cc_tests.gyp b/cc/cc_tests.gyp index c7931db..4828854 100644 --- a/cc/cc_tests.gyp +++ b/cc/cc_tests.gyp @@ -71,6 +71,7 @@ 'trees/layer_tree_host_pixeltest_filters.cc', 'trees/layer_tree_host_pixeltest_masks.cc', 'trees/layer_tree_host_pixeltest_on_demand_raster.cc', + 'trees/layer_tree_host_pixeltest_readback.cc', 'trees/layer_tree_host_unittest_animation.cc', 'trees/layer_tree_host_unittest.cc', 'trees/layer_tree_host_unittest_context.cc', diff --git a/cc/output/direct_renderer.cc b/cc/output/direct_renderer.cc index e0cedb6..523c39a 100644 --- a/cc/output/direct_renderer.cc +++ b/cc/output/direct_renderer.cc @@ -198,8 +198,14 @@ void DirectRenderer::DrawFrame(RenderPassList* render_passes_in_draw_order) { DrawRenderPass(&frame, render_passes_in_draw_order->at(i)); const RenderPass* pass = frame.current_render_pass; - for (size_t i = 0; i < pass->copy_callbacks.size(); ++i) + for (size_t i = 0; i < pass->copy_callbacks.size(); ++i) { + if (i > 0) { + // Doing a readback is destructive of our state on Mac, so make sure + // we restore the state between readbacks. http://crbug.com/99393. + UseRenderPass(&frame, pass); + } CopyCurrentRenderPassToBitmap(&frame, pass->copy_callbacks[i]); + } } FinishDrawingFrame(&frame); diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc index 212a5dc..f492b10d 100644 --- a/cc/output/gl_renderer.cc +++ b/cc/output/gl_renderer.cc @@ -1807,7 +1807,9 @@ void GLRenderer::EnsureScissorTestDisabled() { void GLRenderer::CopyCurrentRenderPassToBitmap( DrawingFrame* frame, const CopyRenderPassCallback& callback) { - GetFramebufferPixelsAsync(frame->current_render_pass->output_rect, callback); + GetFramebufferPixelsAsync(frame->current_render_pass->output_rect, + frame->flipped_y, + callback); } void GLRenderer::ToGLMatrix(float* gl_matrix, const gfx::Transform& transform) { @@ -2011,6 +2013,10 @@ void GLRenderer::GetFramebufferPixels(void* pixels, gfx::Rect rect) { if (!pixels || rect.IsEmpty()) return; + // This function assumes that it is reading the root frame buffer. + DCHECK(!current_framebuffer_lock_); + bool flipped_y = FlippedFramebuffer(); + scoped_ptr pending_read(new PendingAsyncReadPixels); pending_async_read_pixels_.insert(pending_async_read_pixels_.begin(), pending_read.Pass()); @@ -2018,10 +2024,12 @@ void GLRenderer::GetFramebufferPixels(void* pixels, gfx::Rect rect) { // This is a syncronous call since the callback is null. DoGetFramebufferPixels(static_cast(pixels), rect, + flipped_y, AsyncGetFramebufferPixelsCleanupCallback()); } void GLRenderer::GetFramebufferPixelsAsync(gfx::Rect rect, + bool flipped_y, CopyRenderPassCallback callback) { if (callback.is_null()) return; @@ -2052,12 +2060,13 @@ void GLRenderer::GetFramebufferPixelsAsync(gfx::Rect rect, pending_read.Pass()); // This is an asyncronous call since the callback is not null. - DoGetFramebufferPixels(pixels, rect, cleanup_callback); + DoGetFramebufferPixels(pixels, rect, flipped_y, cleanup_callback); } void GLRenderer::DoGetFramebufferPixels( uint8* dest_pixels, gfx::Rect rect, + bool flipped_y, const AsyncGetFramebufferPixelsCleanupCallback& cleanup_callback) { DCHECK(rect.right() <= ViewportWidth()); DCHECK(rect.bottom() <= ViewportHeight()); @@ -2100,8 +2109,8 @@ void GLRenderer::DoGetFramebufferPixels( GL_RGBA, 0, 0, - ViewportSize().width(), - ViewportSize().height(), + current_framebuffer_size_.width(), + current_framebuffer_size_.height(), 0)); temporary_fbo = context_->createFramebuffer(); // Attach this texture to an FBO, and perform the readback from that FBO. @@ -2127,7 +2136,7 @@ void GLRenderer::DoGetFramebufferPixels( GLC(context_, context_->readPixels(rect.x(), - ViewportSize().height() - rect.bottom(), + current_framebuffer_size_.height() - rect.bottom(), rect.width(), rect.height(), GL_RGBA, @@ -2151,7 +2160,8 @@ void GLRenderer::DoGetFramebufferPixels( cleanup_callback, buffer, dest_pixels, - rect.size()); + rect.size(), + flipped_y); // Save the finished_callback so it can be cancelled. pending_async_read_pixels_.front()->finished_read_pixels_callback.Reset( finished_callback); @@ -2177,7 +2187,8 @@ void GLRenderer::FinishedReadback( const AsyncGetFramebufferPixelsCleanupCallback& cleanup_callback, unsigned source_buffer, uint8* dest_pixels, - gfx::Size size) { + gfx::Size size, + bool flipped_y) { DCHECK(!pending_async_read_pixels_.empty()); DCHECK_EQ(source_buffer, pending_async_read_pixels_.back()->buffer); @@ -2196,7 +2207,8 @@ void GLRenderer::FinishedReadback( size_t total_bytes = num_rows * row_bytes; for (size_t dest_y = 0; dest_y < total_bytes; dest_y += row_bytes) { // Flip Y axis. - size_t src_y = total_bytes - dest_y - row_bytes; + size_t src_y = flipped_y ? total_bytes - dest_y - row_bytes + : dest_y; // Swizzle OpenGL -> Skia byte order. for (size_t x = 0; x < row_bytes; x += 4) { dest_pixels[dest_y + x + SK_R32_SHIFT/8] = src_pixels[src_y + x + 0]; @@ -2280,6 +2292,8 @@ bool GLRenderer::BindFramebufferToTexture(DrawingFrame* frame, gfx::Rect framebuffer_rect) { DCHECK(texture->id()); + current_framebuffer_lock_.reset(); + GLC(context_, context_->bindFramebuffer(GL_FRAMEBUFFER, offscreen_framebuffer_id_)); current_framebuffer_lock_ = @@ -2317,6 +2331,7 @@ void GLRenderer::SetScissorTestRect(gfx::Rect scissor_rect) { } void GLRenderer::SetDrawViewportSize(gfx::Size viewport_size) { + current_framebuffer_size_ = viewport_size; GLC(context_, context_->viewport(0, 0, viewport_size.width(), viewport_size.height())); } diff --git a/cc/output/gl_renderer.h b/cc/output/gl_renderer.h index 24677d9..1c1ecb8 100644 --- a/cc/output/gl_renderer.h +++ b/cc/output/gl_renderer.h @@ -92,6 +92,7 @@ class CC_EXPORT GLRenderer } void GetFramebufferPixelsAsync(gfx::Rect rect, + bool flipped_y, CopyRenderPassCallback callback); bool GetFramebufferTexture(ScopedResource* resource, gfx::Rect device_rect); void ReleaseRenderPassTextures(); @@ -191,12 +192,14 @@ class CC_EXPORT GLRenderer void DoGetFramebufferPixels( uint8* pixels, gfx::Rect rect, + bool flipped_y, const AsyncGetFramebufferPixelsCleanupCallback& cleanup_callback); void FinishedReadback( const AsyncGetFramebufferPixelsCleanupCallback& cleanup_callback, unsigned source_buffer, uint8_t* dest_pixels, - gfx::Size size); + gfx::Size size, + bool flipped_y); void PassOnSkBitmap( scoped_ptr bitmap, scoped_ptr lock, @@ -407,6 +410,7 @@ class CC_EXPORT GLRenderer ScopedPtrVector pending_async_read_pixels_; scoped_ptr current_framebuffer_lock_; + gfx::Size current_framebuffer_size_; scoped_refptr last_swap_fence_; diff --git a/cc/output/gl_renderer_unittest.cc b/cc/output/gl_renderer_unittest.cc index cd334e3..5f6bb28 100644 --- a/cc/output/gl_renderer_unittest.cc +++ b/cc/output/gl_renderer_unittest.cc @@ -7,6 +7,7 @@ #include "cc/output/compositor_frame_metadata.h" #include "cc/resources/prioritized_resource_manager.h" #include "cc/resources/resource_provider.h" +#include "cc/resources/sync_point_helper.h" #include "cc/test/fake_impl_proxy.h" #include "cc/test/fake_layer_tree_host_impl.h" #include "cc/test/fake_output_surface.h" @@ -15,6 +16,7 @@ #include "cc/test/render_pass_test_common.h" #include "cc/test/render_pass_test_utils.h" #include "cc/test/test_web_graphics_context_3d.h" +#include "gpu/GLES2/gl2extchromium.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/khronos/GLES2/gl2.h" @@ -1426,5 +1428,75 @@ TEST_F(MockOutputSurfaceTestWithSendCompositorFrame, DrawFrame) { DrawFrame(); } +class GLRendererTestSyncPoint : public GLRendererPixelTest { + protected: + static void SyncPointCallback(int* callback_count) { + ++(*callback_count); + base::MessageLoop::current()->QuitWhenIdle(); + } + + static void OtherCallback(int* callback_count) { + ++(*callback_count); + base::MessageLoop::current()->QuitWhenIdle(); + } +}; + +#if !defined(OS_ANDROID) +TEST_F(GLRendererTestSyncPoint, SignalSyncPointOnLostContext) { + int sync_point_callback_count = 0; + int other_callback_count = 0; + unsigned sync_point = output_surface_->context3d()->insertSyncPoint(); + + output_surface_->context3d()->loseContextCHROMIUM( + GL_GUILTY_CONTEXT_RESET_ARB, GL_INNOCENT_CONTEXT_RESET_ARB); + + SyncPointHelper::SignalSyncPoint( + output_surface_->context3d(), + sync_point, + base::Bind(&SyncPointCallback, &sync_point_callback_count)); + EXPECT_EQ(0, sync_point_callback_count); + EXPECT_EQ(0, other_callback_count); + + // Make the sync point happen. + output_surface_->context3d()->finish(); + // Post a task after the sync point. + base::MessageLoop::current()->PostTask( + FROM_HERE, + base::Bind(&OtherCallback, &other_callback_count)); + + base::MessageLoop::current()->Run(); + + // The sync point shouldn't have happened since the context was lost. + EXPECT_EQ(0, sync_point_callback_count); + EXPECT_EQ(1, other_callback_count); +} + +TEST_F(GLRendererTestSyncPoint, SignalSyncPoint) { + int sync_point_callback_count = 0; + int other_callback_count = 0; + unsigned sync_point = output_surface_->context3d()->insertSyncPoint(); + + SyncPointHelper::SignalSyncPoint( + output_surface_->context3d(), + sync_point, + base::Bind(&SyncPointCallback, &sync_point_callback_count)); + EXPECT_EQ(0, sync_point_callback_count); + EXPECT_EQ(0, other_callback_count); + + // Make the sync point happen. + output_surface_->context3d()->finish(); + // Post a task after the sync point. + base::MessageLoop::current()->PostTask( + FROM_HERE, + base::Bind(&OtherCallback, &other_callback_count)); + + base::MessageLoop::current()->Run(); + + // The sync point should have happened. + EXPECT_EQ(1, sync_point_callback_count); + EXPECT_EQ(1, other_callback_count); +} +#endif // OS_ANDROID + } // namespace } // namespace cc diff --git a/cc/output/renderer_pixeltest.cc b/cc/output/renderer_pixeltest.cc index 4776dbb..dc5c808 100644 --- a/cc/output/renderer_pixeltest.cc +++ b/cc/output/renderer_pixeltest.cc @@ -139,9 +139,8 @@ TYPED_TEST(RendererPixelTest, SimpleGreenRect) { RenderPass::Id id(1, 1); scoped_ptr pass = CreateTestRootRenderPass(id, rect); - gfx::Transform content_to_target_transform; scoped_ptr shared_state = - CreateTestSharedQuadState(content_to_target_transform, rect); + CreateTestSharedQuadState(gfx::Transform(), rect); scoped_ptr color_quad = SolidColorDrawQuad::Create(); color_quad->SetNew(shared_state.get(), rect, SK_ColorGREEN, false); @@ -157,6 +156,47 @@ TYPED_TEST(RendererPixelTest, SimpleGreenRect) { ExactPixelComparator(true))); } +TYPED_TEST(RendererPixelTest, SimpleGreenRect_NonRootRenderPass) { + gfx::Rect rect(this->device_viewport_size_); + gfx::Rect small_rect(100, 100); + + RenderPass::Id child_id(2, 1); + scoped_ptr child_pass = + CreateTestRenderPass(child_id, small_rect, gfx::Transform()); + + scoped_ptr child_shared_state = + CreateTestSharedQuadState(gfx::Transform(), small_rect); + + scoped_ptr color_quad = SolidColorDrawQuad::Create(); + color_quad->SetNew(child_shared_state.get(), rect, SK_ColorGREEN, false); + child_pass->quad_list.push_back(color_quad.PassAs()); + + RenderPass::Id root_id(1, 1); + scoped_ptr root_pass = + CreateTestRenderPass(root_id, rect, gfx::Transform()); + + scoped_ptr root_shared_state = + CreateTestSharedQuadState(gfx::Transform(), rect); + + scoped_ptr render_pass_quad = + CreateTestRenderPassDrawQuad(root_shared_state.get(), + small_rect, + child_id); + root_pass->quad_list.push_back(render_pass_quad.PassAs()); + + RenderPass* child_pass_ptr = child_pass.get(); + + RenderPassList pass_list; + pass_list.push_back(child_pass.Pass()); + pass_list.push_back(root_pass.Pass()); + + EXPECT_TRUE(this->RunPixelTestWithReadbackTarget( + &pass_list, + child_pass_ptr, + base::FilePath(FILE_PATH_LITERAL("green_small.png")), + ExactPixelComparator(true))); +} + TYPED_TEST(RendererPixelTest, FastPassColorFilterAlpha) { gfx::Rect viewport_rect(this->device_viewport_size_); @@ -553,7 +593,7 @@ TEST_F(GLRendererPixelTestWithBackgroundFilter, InvertFilter) { // Software renderer does not support anti-aliased edges. TEST_F(GLRendererPixelTest, AntiAliasing) { - gfx::Rect rect(0, 0, 200, 200); + gfx::Rect rect(this->device_viewport_size_); RenderPass::Id id(1, 1); scoped_ptr pass = CreateTestRootRenderPass(id, rect); @@ -599,7 +639,7 @@ TEST_F(GLRendererPixelTest, AntiAliasing) { // This test tests that anti-aliasing works for axis aligned quads. // Anti-aliasing is only supported in the gl renderer. TEST_F(GLRendererPixelTest, AxisAligned) { - gfx::Rect rect(0, 0, 200, 200); + gfx::Rect rect(this->device_viewport_size_); RenderPass::Id id(1, 1); gfx::Transform transform_to_root; @@ -651,7 +691,7 @@ TEST_F(GLRendererPixelTest, AxisAligned) { // This test tests that forcing anti-aliasing off works as expected. // Anti-aliasing is only supported in the gl renderer. TEST_F(GLRendererPixelTest, ForceAntiAliasingOff) { - gfx::Rect rect(0, 0, 200, 200); + gfx::Rect rect(this->device_viewport_size_); RenderPass::Id id(1, 1); gfx::Transform transform_to_root; @@ -689,71 +729,6 @@ TEST_F(GLRendererPixelTest, ForceAntiAliasingOff) { ExactPixelComparator(false))); } -static void SyncPointCallback(int* callback_count) { - ++(*callback_count); - base::MessageLoop::current()->QuitWhenIdle(); -} - -static void OtherCallback(int* callback_count) { - ++(*callback_count); - base::MessageLoop::current()->QuitWhenIdle(); -} - -TEST_F(GLRendererPixelTest, SignalSyncPointOnLostContext) { - int sync_point_callback_count = 0; - int other_callback_count = 0; - unsigned sync_point = output_surface_->context3d()->insertSyncPoint(); - - output_surface_->context3d()->loseContextCHROMIUM( - GL_GUILTY_CONTEXT_RESET_ARB, GL_INNOCENT_CONTEXT_RESET_ARB); - - SyncPointHelper::SignalSyncPoint( - output_surface_->context3d(), - sync_point, - base::Bind(&SyncPointCallback, &sync_point_callback_count)); - EXPECT_EQ(0, sync_point_callback_count); - EXPECT_EQ(0, other_callback_count); - - // Make the sync point happen. - output_surface_->context3d()->finish(); - // Post a task after the sync point. - base::MessageLoop::current()->PostTask( - FROM_HERE, - base::Bind(&OtherCallback, &other_callback_count)); - - base::MessageLoop::current()->Run(); - - // The sync point shouldn't have happened since the context was lost. - EXPECT_EQ(0, sync_point_callback_count); - EXPECT_EQ(1, other_callback_count); -} - -TEST_F(GLRendererPixelTest, SignalSyncPoint) { - int sync_point_callback_count = 0; - int other_callback_count = 0; - unsigned sync_point = output_surface_->context3d()->insertSyncPoint(); - - SyncPointHelper::SignalSyncPoint( - output_surface_->context3d(), - sync_point, - base::Bind(&SyncPointCallback, &sync_point_callback_count)); - EXPECT_EQ(0, sync_point_callback_count); - EXPECT_EQ(0, other_callback_count); - - // Make the sync point happen. - output_surface_->context3d()->finish(); - // Post a task after the sync point. - base::MessageLoop::current()->PostTask( - FROM_HERE, - base::Bind(&OtherCallback, &other_callback_count)); - - base::MessageLoop::current()->Run(); - - // The sync point should have happened. - EXPECT_EQ(1, sync_point_callback_count); - EXPECT_EQ(1, other_callback_count); -} - TEST_F(GLRendererPixelTest, PictureDrawQuadIdentityScale) { gfx::Size pile_tile_size(1000, 1000); gfx::Rect viewport(this->device_viewport_size_); @@ -837,7 +812,7 @@ TEST_F(GLRendererPixelTest, PictureDrawQuadIdentityScale) { TEST_F(GLRendererPixelTest, PictureDrawQuadNonIdentityScale) { gfx::Size pile_tile_size(1000, 1000); - gfx::Rect viewport(gfx::Size(200, 200)); + gfx::Rect viewport(this->device_viewport_size_); // TODO(enne): the renderer should figure this out on its own. bool contents_swizzled = !PlatformColor::SameComponentOrder(GL_RGBA); @@ -978,7 +953,6 @@ TEST_F(GLRendererPixelTest, PictureDrawQuadNonIdentityScale) { base::FilePath(FILE_PATH_LITERAL("four_blue_green_checkers.png")), ExactPixelComparator(true))); } - #endif // !defined(OS_ANDROID) } // namespace diff --git a/cc/output/software_renderer.cc b/cc/output/software_renderer.cc index abb9bba..0e96c57 100644 --- a/cc/output/software_renderer.cc +++ b/cc/output/software_renderer.cc @@ -155,6 +155,7 @@ bool SoftwareRenderer::BindFramebufferToTexture( DrawingFrame* frame, const ScopedResource* texture, gfx::Rect framebuffer_rect) { + current_framebuffer_lock_.reset(); current_framebuffer_lock_ = make_scoped_ptr( new ResourceProvider::ScopedWriteLockSoftware( resource_provider_, texture->id())); diff --git a/cc/test/layer_tree_pixel_test.cc b/cc/test/layer_tree_pixel_test.cc index 1dfc551..1c9855f 100644 --- a/cc/test/layer_tree_pixel_test.cc +++ b/cc/test/layer_tree_pixel_test.cc @@ -63,7 +63,9 @@ void LayerTreePixelTest::ReadbackResult(scoped_ptr bitmap) { } void LayerTreePixelTest::BeginTest() { - layer_tree_host()->root_layer()->RequestCopyAsBitmap( + Layer* target = readback_target_ ? readback_target_ + : layer_tree_host()->root_layer(); + target->RequestCopyAsBitmap( base::Bind(&LayerTreePixelTest::ReadbackResult, base::Unretained(this))); PostSetNeedsCommitToMainThread(); @@ -114,6 +116,17 @@ void LayerTreePixelTest::RunPixelTest( scoped_refptr content_root, base::FilePath file_name) { content_root_ = content_root; + readback_target_ = NULL; + ref_file_ = file_name; + RunTest(true); +} + +void LayerTreePixelTest::RunPixelTestWithReadbackTarget( + scoped_refptr content_root, + Layer* target, + base::FilePath file_name) { + content_root_ = content_root; + readback_target_ = target; ref_file_ = file_name; RunTest(true); } diff --git a/cc/test/layer_tree_pixel_test.h b/cc/test/layer_tree_pixel_test.h index 4700ebd..1e5ddae 100644 --- a/cc/test/layer_tree_pixel_test.h +++ b/cc/test/layer_tree_pixel_test.h @@ -43,6 +43,10 @@ class LayerTreePixelTest : public LayerTreeTest { void RunPixelTest(scoped_refptr content_root, base::FilePath file_name); + void RunPixelTestWithReadbackTarget(scoped_refptr content_root, + Layer* target, + base::FilePath file_name); + // Common CSS colors defined for tests to use. enum Colors { kCSSOrange = 0xffffa500, @@ -54,6 +58,7 @@ class LayerTreePixelTest : public LayerTreeTest { private: scoped_refptr content_root_; + Layer* readback_target_; base::FilePath ref_file_; }; diff --git a/cc/test/pixel_test.cc b/cc/test/pixel_test.cc index 5d28d59..7d4c8f8 100644 --- a/cc/test/pixel_test.cc +++ b/cc/test/pixel_test.cc @@ -61,9 +61,20 @@ PixelTest::~PixelTest() {} bool PixelTest::RunPixelTest(RenderPassList* pass_list, const base::FilePath& ref_file, const PixelComparator& comparator) { + return RunPixelTestWithReadbackTarget(pass_list, + pass_list->back(), + ref_file, + comparator); +} + +bool PixelTest::RunPixelTestWithReadbackTarget( + RenderPassList* pass_list, + RenderPass* target, + const base::FilePath& ref_file, + const PixelComparator& comparator) { base::RunLoop run_loop; - pass_list->back()->copy_callbacks.push_back( + target->copy_callbacks.push_back( base::Bind(&PixelTest::ReadbackResult, base::Unretained(this), run_loop.QuitClosure())); diff --git a/cc/test/pixel_test.h b/cc/test/pixel_test.h index 6fb8135..148ecf9 100644 --- a/cc/test/pixel_test.h +++ b/cc/test/pixel_test.h @@ -27,6 +27,11 @@ class PixelTest : public testing::Test { const base::FilePath& ref_file, const PixelComparator& comparator); + bool RunPixelTestWithReadbackTarget(RenderPassList* pass_list, + RenderPass* target, + const base::FilePath& ref_file, + const PixelComparator& comparator); + gfx::Size device_viewport_size_; scoped_ptr output_surface_; scoped_ptr resource_provider_; diff --git a/cc/trees/layer_tree_host_pixeltest_readback.cc b/cc/trees/layer_tree_host_pixeltest_readback.cc new file mode 100644 index 0000000..f6a6ccb --- /dev/null +++ b/cc/trees/layer_tree_host_pixeltest_readback.cc @@ -0,0 +1,94 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "build/build_config.h" +#include "cc/test/layer_tree_pixel_test.h" + +#if !defined(OS_ANDROID) + +namespace cc { +namespace { + +class LayerTreeHostReadbackPixelTest : public LayerTreePixelTest {}; + +TEST_F(LayerTreeHostReadbackPixelTest, ReadbackRootLayer) { + scoped_refptr background = CreateSolidColorLayer( + gfx::Rect(200, 200), SK_ColorWHITE); + + scoped_refptr green = CreateSolidColorLayer( + gfx::Rect(200, 200), SK_ColorGREEN); + background->AddChild(green); + + RunPixelTest(background, + base::FilePath(FILE_PATH_LITERAL( + "green.png"))); +} + +TEST_F(LayerTreeHostReadbackPixelTest, ReadbackRootLayerWithChild) { + scoped_refptr background = CreateSolidColorLayer( + gfx::Rect(200, 200), SK_ColorWHITE); + + scoped_refptr green = CreateSolidColorLayer( + gfx::Rect(200, 200), SK_ColorGREEN); + background->AddChild(green); + + scoped_refptr blue = CreateSolidColorLayer( + gfx::Rect(150, 150, 50, 50), SK_ColorBLUE); + green->AddChild(blue); + + RunPixelTest(background, + base::FilePath(FILE_PATH_LITERAL( + "green_with_blue_corner.png"))); +} + +TEST_F(LayerTreeHostReadbackPixelTest, ReadbackNonRootLayer) { + scoped_refptr background = CreateSolidColorLayer( + gfx::Rect(200, 200), SK_ColorWHITE); + + scoped_refptr green = CreateSolidColorLayer( + gfx::Rect(200, 200), SK_ColorGREEN); + background->AddChild(green); + + RunPixelTestWithReadbackTarget(background, + green.get(), + base::FilePath(FILE_PATH_LITERAL( + "green.png"))); +} + +TEST_F(LayerTreeHostReadbackPixelTest, ReadbackSmallNonRootLayer) { + scoped_refptr background = CreateSolidColorLayer( + gfx::Rect(200, 200), SK_ColorWHITE); + + scoped_refptr green = CreateSolidColorLayer( + gfx::Rect(100, 100, 100, 100), SK_ColorGREEN); + background->AddChild(green); + + RunPixelTestWithReadbackTarget(background, + green.get(), + base::FilePath(FILE_PATH_LITERAL( + "green_small.png"))); +} + +TEST_F(LayerTreeHostReadbackPixelTest, ReadbackSmallNonRootLayerWithChild) { + scoped_refptr background = CreateSolidColorLayer( + gfx::Rect(200, 200), SK_ColorWHITE); + + scoped_refptr green = CreateSolidColorLayer( + gfx::Rect(100, 100, 100, 100), SK_ColorGREEN); + background->AddChild(green); + + scoped_refptr blue = CreateSolidColorLayer( + gfx::Rect(50, 50, 50, 50), SK_ColorBLUE); + green->AddChild(blue); + + RunPixelTestWithReadbackTarget(background, + green.get(), + base::FilePath(FILE_PATH_LITERAL( + "green_small_with_blue_corner.png"))); +} + +} // namespace +} // namespace cc + +#endif // OS_ANDROID -- cgit v1.1