1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/test/pixel_test.h"
7 #include "base/command_line.h"
8 #include "base/path_service.h"
9 #include "base/run_loop.h"
10 #include "cc/base/switches.h"
11 #include "cc/output/compositor_frame_metadata.h"
12 #include "cc/output/copy_output_request.h"
13 #include "cc/output/copy_output_result.h"
14 #include "cc/output/gl_renderer.h"
15 #include "cc/output/output_surface_client.h"
16 #include "cc/output/software_renderer.h"
17 #include "cc/resources/resource_provider.h"
18 #include "cc/resources/texture_mailbox_deleter.h"
19 #include "cc/test/paths.h"
20 #include "cc/test/pixel_test_output_surface.h"
21 #include "cc/test/pixel_test_software_output_device.h"
22 #include "cc/test/pixel_test_utils.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24 #include "ui/gl/gl_implementation.h"
25 #include "webkit/common/gpu/context_provider_in_process.h"
26 #include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h"
30 class PixelTest::PixelTestRendererClient
31 : public RendererClient, public OutputSurfaceClient {
33 explicit PixelTestRendererClient(gfx::Rect device_viewport)
34 : device_viewport_(device_viewport), device_clip_(device_viewport) {}
36 // RendererClient implementation.
37 virtual gfx::Rect DeviceViewport() const OVERRIDE {
38 return device_viewport_;
40 virtual gfx::Rect DeviceClip() const OVERRIDE { return device_clip_; }
41 virtual void SetFullRootLayerDamage() OVERRIDE {}
42 virtual CompositorFrameMetadata MakeCompositorFrameMetadata() const
44 return CompositorFrameMetadata();
47 // OutputSurfaceClient implementation.
48 virtual bool DeferredInitialize(
49 scoped_refptr<ContextProvider> offscreen_context_provider) OVERRIDE {
52 virtual void ReleaseGL() OVERRIDE {}
53 virtual void SetNeedsRedrawRect(gfx::Rect damage_rect) OVERRIDE {}
54 virtual void BeginImplFrame(const BeginFrameArgs& args) OVERRIDE {}
55 virtual void OnSwapBuffersComplete() OVERRIDE {}
56 virtual void ReclaimResources(const CompositorFrameAck* ack) OVERRIDE {}
57 virtual void DidLoseOutputSurface() OVERRIDE {}
58 virtual void SetExternalDrawConstraints(
59 const gfx::Transform& transform,
62 bool valid_for_tile_management) OVERRIDE {
63 device_viewport_ = viewport;
66 virtual void SetMemoryPolicy(const ManagedMemoryPolicy& policy) OVERRIDE {}
67 virtual void SetTreeActivationCallback(const base::Closure&) OVERRIDE {}
70 gfx::Rect device_viewport_;
71 gfx::Rect device_clip_;
74 PixelTest::PixelTest()
75 : device_viewport_size_(gfx::Size(200, 200)),
76 disable_picture_quad_image_filtering_(false),
78 new PixelTestRendererClient(gfx::Rect(device_viewport_size_))) {}
80 PixelTest::~PixelTest() {}
82 bool PixelTest::RunPixelTest(RenderPassList* pass_list,
83 OffscreenContextOption provide_offscreen_context,
84 const base::FilePath& ref_file,
85 const PixelComparator& comparator) {
86 return RunPixelTestWithReadbackTarget(pass_list,
88 provide_offscreen_context,
93 bool PixelTest::RunPixelTestWithReadbackTarget(
94 RenderPassList* pass_list,
96 OffscreenContextOption provide_offscreen_context,
97 const base::FilePath& ref_file,
98 const PixelComparator& comparator) {
99 base::RunLoop run_loop;
101 target->copy_requests.push_back(CopyOutputRequest::CreateBitmapRequest(
102 base::Bind(&PixelTest::ReadbackResult,
103 base::Unretained(this),
104 run_loop.QuitClosure())));
106 scoped_refptr<webkit::gpu::ContextProviderInProcess> offscreen_contexts;
107 switch (provide_offscreen_context) {
108 case NoOffscreenContext:
110 case WithOffscreenContext:
112 webkit::gpu::ContextProviderInProcess::CreateOffscreen();
113 CHECK(offscreen_contexts->BindToCurrentThread());
117 float device_scale_factor = 1.f;
118 bool allow_partial_swap = true;
120 renderer_->DecideRenderPassAllocationsForFrame(*pass_list);
121 renderer_->DrawFrame(pass_list,
122 offscreen_contexts.get(),
125 disable_picture_quad_image_filtering_);
127 // Wait for the readback to complete.
128 resource_provider_->Finish();
131 return PixelsMatchReference(ref_file, comparator);
134 void PixelTest::ReadbackResult(base::Closure quit_run_loop,
135 scoped_ptr<CopyOutputResult> result) {
136 ASSERT_TRUE(result->HasBitmap());
137 result_bitmap_ = result->TakeBitmap().Pass();
141 bool PixelTest::PixelsMatchReference(const base::FilePath& ref_file,
142 const PixelComparator& comparator) {
143 base::FilePath test_data_dir;
144 if (!PathService::Get(cc::DIR_TEST_DATA, &test_data_dir))
147 // If this is false, we didn't set up a readback on a render pass.
151 CommandLine* cmd = CommandLine::ForCurrentProcess();
152 if (cmd->HasSwitch(switches::kCCRebaselinePixeltests))
153 return WritePNGFile(*result_bitmap_, test_data_dir.Append(ref_file), true);
155 return MatchesPNGFile(*result_bitmap_,
156 test_data_dir.Append(ref_file),
160 void PixelTest::SetUpGLRenderer(bool use_skia_gpu_backend) {
162 CHECK(gfx::InitializeGLBindings(gfx::kGLImplementationOSMesaGL));
164 using webkit::gpu::ContextProviderInProcess;
165 output_surface_.reset(new PixelTestOutputSurface(
166 ContextProviderInProcess::CreateOffscreen()));
167 output_surface_->BindToClient(fake_client_.get());
170 ResourceProvider::Create(output_surface_.get(), NULL, 0, false, 1);
172 texture_mailbox_deleter_ = make_scoped_ptr(new TextureMailboxDeleter);
174 renderer_ = GLRenderer::Create(fake_client_.get(),
176 output_surface_.get(),
177 resource_provider_.get(),
178 texture_mailbox_deleter_.get(),
180 use_skia_gpu_backend).PassAs<DirectRenderer>();
183 void PixelTest::ForceExpandedViewport(gfx::Size surface_expansion,
184 gfx::Vector2d viewport_offset) {
185 static_cast<PixelTestOutputSurface*>(output_surface_.get())
186 ->set_surface_expansion_size(surface_expansion);
187 static_cast<PixelTestOutputSurface*>(output_surface_.get())
188 ->set_viewport_offset(viewport_offset);
189 SoftwareOutputDevice* device = output_surface_->software_device();
191 static_cast<PixelTestSoftwareOutputDevice*>(device)
192 ->set_surface_expansion_size(surface_expansion);
196 void PixelTest::ForceDeviceClip(gfx::Rect clip) {
197 static_cast<PixelTestOutputSurface*>(output_surface_.get())
198 ->set_device_clip(clip);
201 void PixelTest::EnableExternalStencilTest() {
202 static_cast<PixelTestOutputSurface*>(output_surface_.get())
203 ->set_has_external_stencil_test(true);
206 void PixelTest::SetUpSoftwareRenderer() {
209 scoped_ptr<SoftwareOutputDevice> device(new PixelTestSoftwareOutputDevice());
210 output_surface_.reset(new PixelTestOutputSurface(device.Pass()));
211 output_surface_->BindToClient(fake_client_.get());
213 ResourceProvider::Create(output_surface_.get(), NULL, 0, false, 1);
214 renderer_ = SoftwareRenderer::Create(fake_client_.get(),
216 output_surface_.get(),
217 resource_provider_.get())
218 .PassAs<DirectRenderer>();