summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordanakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-08 23:52:14 +0000
committerdanakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-08 23:52:14 +0000
commit6bec38a3e9548f6ba73d300a3722581121da818a (patch)
tree2cc537bdd2244329c751087b2de3f373378da689
parent5b6c38455846eef96a706b5a20219e620a26491f (diff)
downloadchromium_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.gyp1
-rw-r--r--cc/output/direct_renderer.cc8
-rw-r--r--cc/output/gl_renderer.cc31
-rw-r--r--cc/output/gl_renderer.h6
-rw-r--r--cc/output/gl_renderer_unittest.cc72
-rw-r--r--cc/output/renderer_pixeltest.cc118
-rw-r--r--cc/output/software_renderer.cc1
-rw-r--r--cc/test/layer_tree_pixel_test.cc15
-rw-r--r--cc/test/layer_tree_pixel_test.h5
-rw-r--r--cc/test/pixel_test.cc13
-rw-r--r--cc/test/pixel_test.h5
-rw-r--r--cc/trees/layer_tree_host_pixeltest_readback.cc94
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