diff options
author | danakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-08 23:52:14 +0000 |
---|---|---|
committer | danakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-08 23:52:14 +0000 |
commit | 6bec38a3e9548f6ba73d300a3722581121da818a (patch) | |
tree | 2cc537bdd2244329c751087b2de3f373378da689 | |
parent | 5b6c38455846eef96a706b5a20219e620a26491f (diff) | |
download | chromium_src-6bec38a3e9548f6ba73d300a3722581121da818a.zip chromium_src-6bec38a3e9548f6ba73d300a3722581121da818a.tar.gz chromium_src-6bec38a3e9548f6ba73d300a3722581121da818a.tar.bz2 |
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
-rw-r--r-- | cc/cc_tests.gyp | 1 | ||||
-rw-r--r-- | cc/output/direct_renderer.cc | 8 | ||||
-rw-r--r-- | cc/output/gl_renderer.cc | 31 | ||||
-rw-r--r-- | cc/output/gl_renderer.h | 6 | ||||
-rw-r--r-- | cc/output/gl_renderer_unittest.cc | 72 | ||||
-rw-r--r-- | cc/output/renderer_pixeltest.cc | 118 | ||||
-rw-r--r-- | cc/output/software_renderer.cc | 1 | ||||
-rw-r--r-- | cc/test/layer_tree_pixel_test.cc | 15 | ||||
-rw-r--r-- | cc/test/layer_tree_pixel_test.h | 5 | ||||
-rw-r--r-- | cc/test/pixel_test.cc | 13 | ||||
-rw-r--r-- | cc/test/pixel_test.h | 5 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_pixeltest_readback.cc | 94 |
12 files changed, 285 insertions, 84 deletions
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<PendingAsyncReadPixels> 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<uint8*>(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<SkBitmap> bitmap, scoped_ptr<SkAutoLockPixels> lock, @@ -407,6 +410,7 @@ class CC_EXPORT GLRenderer ScopedPtrVector<PendingAsyncReadPixels> pending_async_read_pixels_; scoped_ptr<ResourceProvider::ScopedWriteLockGL> current_framebuffer_lock_; + gfx::Size current_framebuffer_size_; scoped_refptr<ResourceProvider::Fence> 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<RenderPass> pass = CreateTestRootRenderPass(id, rect); - gfx::Transform content_to_target_transform; scoped_ptr<SharedQuadState> shared_state = - CreateTestSharedQuadState(content_to_target_transform, rect); + CreateTestSharedQuadState(gfx::Transform(), rect); scoped_ptr<SolidColorDrawQuad> 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<RenderPass> child_pass = + CreateTestRenderPass(child_id, small_rect, gfx::Transform()); + + scoped_ptr<SharedQuadState> child_shared_state = + CreateTestSharedQuadState(gfx::Transform(), small_rect); + + scoped_ptr<SolidColorDrawQuad> color_quad = SolidColorDrawQuad::Create(); + color_quad->SetNew(child_shared_state.get(), rect, SK_ColorGREEN, false); + child_pass->quad_list.push_back(color_quad.PassAs<DrawQuad>()); + + RenderPass::Id root_id(1, 1); + scoped_ptr<RenderPass> root_pass = + CreateTestRenderPass(root_id, rect, gfx::Transform()); + + scoped_ptr<SharedQuadState> root_shared_state = + CreateTestSharedQuadState(gfx::Transform(), rect); + + scoped_ptr<DrawQuad> render_pass_quad = + CreateTestRenderPassDrawQuad(root_shared_state.get(), + small_rect, + child_id); + root_pass->quad_list.push_back(render_pass_quad.PassAs<DrawQuad>()); + + 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<RenderPass> 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<SkBitmap> 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<Layer> content_root, base::FilePath file_name) { content_root_ = content_root; + readback_target_ = NULL; + ref_file_ = file_name; + RunTest(true); +} + +void LayerTreePixelTest::RunPixelTestWithReadbackTarget( + scoped_refptr<Layer> 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<Layer> content_root, base::FilePath file_name); + void RunPixelTestWithReadbackTarget(scoped_refptr<Layer> 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<Layer> 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<OutputSurface> output_surface_; scoped_ptr<ResourceProvider> 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<SolidColorLayer> background = CreateSolidColorLayer( + gfx::Rect(200, 200), SK_ColorWHITE); + + scoped_refptr<SolidColorLayer> 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<SolidColorLayer> background = CreateSolidColorLayer( + gfx::Rect(200, 200), SK_ColorWHITE); + + scoped_refptr<SolidColorLayer> green = CreateSolidColorLayer( + gfx::Rect(200, 200), SK_ColorGREEN); + background->AddChild(green); + + scoped_refptr<SolidColorLayer> 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<SolidColorLayer> background = CreateSolidColorLayer( + gfx::Rect(200, 200), SK_ColorWHITE); + + scoped_refptr<SolidColorLayer> 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<SolidColorLayer> background = CreateSolidColorLayer( + gfx::Rect(200, 200), SK_ColorWHITE); + + scoped_refptr<SolidColorLayer> 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<SolidColorLayer> background = CreateSolidColorLayer( + gfx::Rect(200, 200), SK_ColorWHITE); + + scoped_refptr<SolidColorLayer> green = CreateSolidColorLayer( + gfx::Rect(100, 100, 100, 100), SK_ColorGREEN); + background->AddChild(green); + + scoped_refptr<SolidColorLayer> 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 |