Home | History | Annotate | Download | only in test
      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