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. 4 5 #include "cc/test/pixel_test.h" 6 7 #include "base/path_service.h" 8 #include "base/run_loop.h" 9 #include "cc/output/compositor_frame_metadata.h" 10 #include "cc/output/copy_output_request.h" 11 #include "cc/output/copy_output_result.h" 12 #include "cc/output/gl_renderer.h" 13 #include "cc/output/output_surface_client.h" 14 #include "cc/output/software_renderer.h" 15 #include "cc/resources/resource_provider.h" 16 #include "cc/test/paths.h" 17 #include "cc/test/pixel_test_output_surface.h" 18 #include "cc/test/pixel_test_software_output_device.h" 19 #include "cc/test/pixel_test_utils.h" 20 #include "testing/gtest/include/gtest/gtest.h" 21 #include "ui/gl/gl_implementation.h" 22 #include "webkit/common/gpu/context_provider_in_process.h" 23 #include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h" 24 25 namespace cc { 26 27 class PixelTest::PixelTestRendererClient 28 : public RendererClient, public OutputSurfaceClient { 29 public: 30 explicit PixelTestRendererClient(gfx::Rect device_viewport) 31 : device_viewport_(device_viewport), stencil_enabled_(false) {} 32 33 // RendererClient implementation. 34 virtual gfx::Rect DeviceViewport() const OVERRIDE { 35 return device_viewport_; 36 } 37 virtual float DeviceScaleFactor() const OVERRIDE { 38 return 1.f; 39 } 40 virtual const LayerTreeSettings& Settings() const OVERRIDE { 41 return settings_; 42 } 43 virtual void SetFullRootLayerDamage() OVERRIDE {} 44 virtual bool HasImplThread() const OVERRIDE { return false; } 45 virtual bool ShouldClearRootRenderPass() const OVERRIDE { return true; } 46 virtual CompositorFrameMetadata MakeCompositorFrameMetadata() const 47 OVERRIDE { 48 return CompositorFrameMetadata(); 49 } 50 virtual bool AllowPartialSwap() const OVERRIDE { 51 return true; 52 } 53 virtual bool ExternalStencilTestEnabled() const OVERRIDE { 54 return stencil_enabled_; 55 } 56 57 // OutputSurfaceClient implementation. 58 virtual bool DeferredInitialize( 59 scoped_refptr<ContextProvider> offscreen_context_provider) OVERRIDE { 60 return false; 61 } 62 virtual void ReleaseGL() OVERRIDE {} 63 virtual void SetNeedsRedrawRect(gfx::Rect damage_rect) OVERRIDE {} 64 virtual void BeginFrame(const BeginFrameArgs& args) OVERRIDE {} 65 virtual void OnSwapBuffersComplete(const CompositorFrameAck* ack) OVERRIDE {} 66 virtual void DidLoseOutputSurface() OVERRIDE {} 67 virtual void SetExternalDrawConstraints(const gfx::Transform& transform, 68 gfx::Rect viewport) OVERRIDE { 69 device_viewport_ = viewport; 70 } 71 virtual void SetExternalStencilTest(bool enable) OVERRIDE { 72 stencil_enabled_ = enable; 73 } 74 virtual void SetMemoryPolicy(const ManagedMemoryPolicy& policy) OVERRIDE {} 75 virtual void SetDiscardBackBufferWhenNotVisible(bool discard) OVERRIDE {} 76 virtual void SetTreeActivationCallback(const base::Closure&) OVERRIDE {} 77 78 private: 79 gfx::Rect device_viewport_; 80 bool stencil_enabled_; 81 LayerTreeSettings settings_; 82 }; 83 84 PixelTest::PixelTest() 85 : device_viewport_size_(gfx::Size(200, 200)), 86 fake_client_( 87 new PixelTestRendererClient(gfx::Rect(device_viewport_size_))) {} 88 89 PixelTest::~PixelTest() {} 90 91 bool PixelTest::RunPixelTest(RenderPassList* pass_list, 92 const base::FilePath& ref_file, 93 const PixelComparator& comparator) { 94 return RunPixelTestWithReadbackTarget(pass_list, 95 pass_list->back(), 96 ref_file, 97 comparator); 98 } 99 100 bool PixelTest::RunPixelTestWithReadbackTarget( 101 RenderPassList* pass_list, 102 RenderPass* target, 103 const base::FilePath& ref_file, 104 const PixelComparator& comparator) { 105 base::RunLoop run_loop; 106 107 target->copy_requests.push_back(CopyOutputRequest::CreateBitmapRequest( 108 base::Bind(&PixelTest::ReadbackResult, 109 base::Unretained(this), 110 run_loop.QuitClosure()))); 111 112 renderer_->DecideRenderPassAllocationsForFrame(*pass_list); 113 renderer_->DrawFrame(pass_list); 114 115 // Wait for the readback to complete. 116 resource_provider_->Finish(); 117 run_loop.Run(); 118 119 return PixelsMatchReference(ref_file, comparator); 120 } 121 122 void PixelTest::ReadbackResult(base::Closure quit_run_loop, 123 scoped_ptr<CopyOutputResult> result) { 124 ASSERT_TRUE(result->HasBitmap()); 125 result_bitmap_ = result->TakeBitmap().Pass(); 126 quit_run_loop.Run(); 127 } 128 129 bool PixelTest::PixelsMatchReference(const base::FilePath& ref_file, 130 const PixelComparator& comparator) { 131 base::FilePath test_data_dir; 132 if (!PathService::Get(cc::DIR_TEST_DATA, &test_data_dir)) 133 return false; 134 135 // If this is false, we didn't set up a readback on a render pass. 136 if (!result_bitmap_) 137 return false; 138 139 // To rebaseline: 140 // return WritePNGFile(*result_bitmap_, test_data_dir.Append(ref_file), true); 141 142 return MatchesPNGFile(*result_bitmap_, 143 test_data_dir.Append(ref_file), 144 comparator); 145 } 146 147 void PixelTest::SetUpGLRenderer(bool use_skia_gpu_backend) { 148 CHECK(fake_client_); 149 CHECK(gfx::InitializeGLBindings(gfx::kGLImplementationOSMesaGL)); 150 151 using webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl; 152 scoped_ptr<WebKit::WebGraphicsContext3D> context3d( 153 WebGraphicsContext3DInProcessCommandBufferImpl::CreateOffscreenContext( 154 WebKit::WebGraphicsContext3D::Attributes())); 155 output_surface_.reset(new PixelTestOutputSurface( 156 context3d.PassAs<WebKit::WebGraphicsContext3D>())); 157 output_surface_->BindToClient(fake_client_.get()); 158 159 resource_provider_ = ResourceProvider::Create(output_surface_.get(), 0); 160 renderer_ = GLRenderer::Create(fake_client_.get(), 161 output_surface_.get(), 162 resource_provider_.get(), 163 0, 164 use_skia_gpu_backend).PassAs<DirectRenderer>(); 165 166 scoped_refptr<webkit::gpu::ContextProviderInProcess> offscreen_contexts = 167 webkit::gpu::ContextProviderInProcess::CreateOffscreen(); 168 ASSERT_TRUE(offscreen_contexts->BindToCurrentThread()); 169 resource_provider_->set_offscreen_context_provider(offscreen_contexts); 170 } 171 172 void PixelTest::ForceExpandedViewport(gfx::Size surface_expansion, 173 gfx::Vector2d viewport_offset) { 174 static_cast<PixelTestOutputSurface*>(output_surface_.get()) 175 ->set_surface_expansion_size(surface_expansion); 176 static_cast<PixelTestOutputSurface*>(output_surface_.get()) 177 ->set_viewport_offset(viewport_offset); 178 SoftwareOutputDevice* device = output_surface_->software_device(); 179 if (device) { 180 static_cast<PixelTestSoftwareOutputDevice*>(device) 181 ->set_surface_expansion_size(surface_expansion); 182 } 183 } 184 185 void PixelTest::EnableExternalStencilTest() { 186 fake_client_->SetExternalStencilTest(true); 187 } 188 189 void PixelTest::SetUpSoftwareRenderer() { 190 CHECK(fake_client_); 191 192 scoped_ptr<SoftwareOutputDevice> device(new PixelTestSoftwareOutputDevice()); 193 output_surface_.reset(new PixelTestOutputSurface(device.Pass())); 194 output_surface_->BindToClient(fake_client_.get()); 195 resource_provider_ = ResourceProvider::Create(output_surface_.get(), 0); 196 renderer_ = SoftwareRenderer::Create( 197 fake_client_.get(), 198 output_surface_.get(), 199 resource_provider_.get()).PassAs<DirectRenderer>(); 200 } 201 202 } // namespace cc 203