Home | History | Annotate | Download | only in output
      1 // Copyright 2012 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/output/software_renderer.h"
      6 
      7 #include "cc/layers/quad_sink.h"
      8 #include "cc/output/compositor_frame_metadata.h"
      9 #include "cc/output/software_output_device.h"
     10 #include "cc/quads/render_pass.h"
     11 #include "cc/quads/render_pass_draw_quad.h"
     12 #include "cc/quads/solid_color_draw_quad.h"
     13 #include "cc/quads/tile_draw_quad.h"
     14 #include "cc/test/animation_test_common.h"
     15 #include "cc/test/fake_output_surface.h"
     16 #include "cc/test/geometry_test_utils.h"
     17 #include "cc/test/render_pass_test_common.h"
     18 #include "cc/test/render_pass_test_utils.h"
     19 #include "testing/gmock/include/gmock/gmock.h"
     20 #include "testing/gtest/include/gtest/gtest.h"
     21 #include "third_party/skia/include/core/SkCanvas.h"
     22 #include "third_party/skia/include/core/SkDevice.h"
     23 
     24 namespace cc {
     25 namespace {
     26 
     27 class SoftwareRendererTest : public testing::Test, public RendererClient {
     28  public:
     29   SoftwareRendererTest() : should_clear_root_render_pass_(true) {}
     30 
     31   void InitializeRenderer(
     32       scoped_ptr<SoftwareOutputDevice> software_output_device) {
     33     output_surface_ = FakeOutputSurface::CreateSoftware(
     34         software_output_device.Pass());
     35     resource_provider_ = ResourceProvider::Create(output_surface_.get(), 0);
     36     renderer_ = SoftwareRenderer::Create(
     37         this, output_surface_.get(), resource_provider());
     38   }
     39 
     40   ResourceProvider* resource_provider() const {
     41     return resource_provider_.get();
     42   }
     43 
     44   SoftwareRenderer* renderer() const { return renderer_.get(); }
     45 
     46   void set_viewport(gfx::Rect viewport) {
     47     viewport_ = viewport;
     48   }
     49 
     50   void set_should_clear_root_render_pass(bool clear_root_render_pass) {
     51     should_clear_root_render_pass_ = clear_root_render_pass;
     52   }
     53 
     54   // RendererClient implementation.
     55   virtual gfx::Rect DeviceViewport() const OVERRIDE {
     56     return viewport_;
     57   }
     58   virtual float DeviceScaleFactor() const OVERRIDE {
     59     return 1.f;
     60   }
     61   virtual const LayerTreeSettings& Settings() const OVERRIDE {
     62     return settings_;
     63   }
     64   virtual void SetFullRootLayerDamage() OVERRIDE {}
     65   virtual bool HasImplThread() const OVERRIDE { return false; }
     66   virtual bool ShouldClearRootRenderPass() const OVERRIDE {
     67     return should_clear_root_render_pass_;
     68   }
     69   virtual CompositorFrameMetadata MakeCompositorFrameMetadata() const OVERRIDE {
     70     return CompositorFrameMetadata();
     71   }
     72   virtual bool AllowPartialSwap() const OVERRIDE {
     73     return true;
     74   }
     75   virtual bool ExternalStencilTestEnabled() const OVERRIDE { return false; }
     76 
     77  protected:
     78   scoped_ptr<FakeOutputSurface> output_surface_;
     79   scoped_ptr<ResourceProvider> resource_provider_;
     80   scoped_ptr<SoftwareRenderer> renderer_;
     81   gfx::Rect viewport_;
     82   LayerTreeSettings settings_;
     83   bool should_clear_root_render_pass_;
     84 };
     85 
     86 TEST_F(SoftwareRendererTest, SolidColorQuad) {
     87   gfx::Size outer_size(100, 100);
     88   gfx::Size inner_size(98, 98);
     89   gfx::Rect outer_rect(outer_size);
     90   gfx::Rect inner_rect(gfx::Point(1, 1), inner_size);
     91   set_viewport(gfx::Rect(outer_size));
     92 
     93   InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
     94 
     95   scoped_ptr<SharedQuadState> shared_quad_state = SharedQuadState::Create();
     96   shared_quad_state->SetAll(
     97       gfx::Transform(), outer_size, outer_rect, outer_rect, false, 1.0);
     98   RenderPass::Id root_render_pass_id = RenderPass::Id(1, 1);
     99   scoped_ptr<TestRenderPass> root_render_pass = TestRenderPass::Create();
    100   root_render_pass->SetNew(
    101       root_render_pass_id, outer_rect, outer_rect, gfx::Transform());
    102   scoped_ptr<SolidColorDrawQuad> outer_quad = SolidColorDrawQuad::Create();
    103   outer_quad->SetNew(
    104       shared_quad_state.get(), outer_rect, SK_ColorYELLOW, false);
    105   scoped_ptr<SolidColorDrawQuad> inner_quad = SolidColorDrawQuad::Create();
    106   inner_quad->SetNew(shared_quad_state.get(), inner_rect, SK_ColorCYAN, false);
    107   root_render_pass->AppendQuad(inner_quad.PassAs<DrawQuad>());
    108   root_render_pass->AppendQuad(outer_quad.PassAs<DrawQuad>());
    109 
    110   RenderPassList list;
    111   list.push_back(root_render_pass.PassAs<RenderPass>());
    112   renderer()->DrawFrame(&list);
    113 
    114   SkBitmap output;
    115   output.setConfig(SkBitmap::kARGB_8888_Config,
    116                    DeviceViewport().width(),
    117                    DeviceViewport().height());
    118   output.allocPixels();
    119   renderer()->GetFramebufferPixels(output.getPixels(), outer_rect);
    120 
    121   EXPECT_EQ(SK_ColorYELLOW, output.getColor(0, 0));
    122   EXPECT_EQ(SK_ColorYELLOW,
    123             output.getColor(outer_size.width() - 1, outer_size.height() - 1));
    124   EXPECT_EQ(SK_ColorCYAN, output.getColor(1, 1));
    125   EXPECT_EQ(SK_ColorCYAN,
    126             output.getColor(inner_size.width() - 1, inner_size.height() - 1));
    127 }
    128 
    129 TEST_F(SoftwareRendererTest, TileQuad) {
    130   gfx::Size outer_size(100, 100);
    131   gfx::Size inner_size(98, 98);
    132   gfx::Rect outer_rect(outer_size);
    133   gfx::Rect inner_rect(gfx::Point(1, 1), inner_size);
    134   set_viewport(gfx::Rect(outer_size));
    135   InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
    136 
    137   ResourceProvider::ResourceId resource_yellow =
    138       resource_provider()->CreateResource(
    139           outer_size, GL_RGBA, ResourceProvider::TextureUsageAny);
    140   ResourceProvider::ResourceId resource_cyan =
    141       resource_provider()->CreateResource(
    142           inner_size, GL_RGBA, ResourceProvider::TextureUsageAny);
    143 
    144   SkBitmap yellow_tile;
    145   yellow_tile.setConfig(
    146       SkBitmap::kARGB_8888_Config, outer_size.width(), outer_size.height());
    147   yellow_tile.allocPixels();
    148   yellow_tile.eraseColor(SK_ColorYELLOW);
    149 
    150   SkBitmap cyan_tile;
    151   cyan_tile.setConfig(
    152       SkBitmap::kARGB_8888_Config, inner_size.width(), inner_size.height());
    153   cyan_tile.allocPixels();
    154   cyan_tile.eraseColor(SK_ColorCYAN);
    155 
    156   resource_provider()->SetPixels(
    157       resource_yellow,
    158       static_cast<uint8_t*>(yellow_tile.getPixels()),
    159       gfx::Rect(outer_size),
    160       gfx::Rect(outer_size),
    161       gfx::Vector2d());
    162   resource_provider()->SetPixels(resource_cyan,
    163                                  static_cast<uint8_t*>(cyan_tile.getPixels()),
    164                                  gfx::Rect(inner_size),
    165                                  gfx::Rect(inner_size),
    166                                  gfx::Vector2d());
    167 
    168   gfx::Rect root_rect = DeviceViewport();
    169 
    170   scoped_ptr<SharedQuadState> shared_quad_state = SharedQuadState::Create();
    171   shared_quad_state->SetAll(
    172       gfx::Transform(), outer_size, outer_rect, outer_rect, false, 1.0);
    173   RenderPass::Id root_render_pass_id = RenderPass::Id(1, 1);
    174   scoped_ptr<TestRenderPass> root_render_pass = TestRenderPass::Create();
    175   root_render_pass->SetNew(
    176       root_render_pass_id, root_rect, root_rect, gfx::Transform());
    177   scoped_ptr<TileDrawQuad> outer_quad = TileDrawQuad::Create();
    178   outer_quad->SetNew(shared_quad_state.get(),
    179                      outer_rect,
    180                      outer_rect,
    181                      resource_yellow,
    182                      gfx::RectF(outer_size),
    183                      outer_size,
    184                      false);
    185   scoped_ptr<TileDrawQuad> inner_quad = TileDrawQuad::Create();
    186   inner_quad->SetNew(shared_quad_state.get(),
    187                      inner_rect,
    188                      inner_rect,
    189                      resource_cyan,
    190                      gfx::RectF(inner_size),
    191                      inner_size,
    192                      false);
    193   root_render_pass->AppendQuad(inner_quad.PassAs<DrawQuad>());
    194   root_render_pass->AppendQuad(outer_quad.PassAs<DrawQuad>());
    195 
    196   RenderPassList list;
    197   list.push_back(root_render_pass.PassAs<RenderPass>());
    198   renderer()->DrawFrame(&list);
    199 
    200   SkBitmap output;
    201   output.setConfig(SkBitmap::kARGB_8888_Config,
    202                    DeviceViewport().width(),
    203                    DeviceViewport().height());
    204   output.allocPixels();
    205   renderer()->GetFramebufferPixels(output.getPixels(), outer_rect);
    206 
    207   EXPECT_EQ(SK_ColorYELLOW, output.getColor(0, 0));
    208   EXPECT_EQ(SK_ColorYELLOW,
    209             output.getColor(outer_size.width() - 1, outer_size.height() - 1));
    210   EXPECT_EQ(SK_ColorCYAN, output.getColor(1, 1));
    211   EXPECT_EQ(SK_ColorCYAN,
    212             output.getColor(inner_size.width() - 1, inner_size.height() - 1));
    213 }
    214 
    215 TEST_F(SoftwareRendererTest, ShouldClearRootRenderPass) {
    216   gfx::Rect viewport_rect(0, 0, 100, 100);
    217   set_viewport(viewport_rect);
    218   set_should_clear_root_render_pass(false);
    219   InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
    220 
    221   RenderPassList list;
    222 
    223   SkBitmap output;
    224   output.setConfig(SkBitmap::kARGB_8888_Config,
    225                    viewport_rect.width(),
    226                    viewport_rect.height());
    227   output.allocPixels();
    228 
    229   // Draw a fullscreen green quad in a first frame.
    230   RenderPass::Id root_clear_pass_id(1, 0);
    231   TestRenderPass* root_clear_pass = AddRenderPass(
    232       &list, root_clear_pass_id, viewport_rect, gfx::Transform());
    233   AddQuad(root_clear_pass, viewport_rect, SK_ColorGREEN);
    234 
    235   renderer()->DecideRenderPassAllocationsForFrame(list);
    236   renderer()->DrawFrame(&list);
    237   renderer()->GetFramebufferPixels(output.getPixels(), viewport_rect);
    238 
    239   EXPECT_EQ(SK_ColorGREEN, output.getColor(0, 0));
    240   EXPECT_EQ(SK_ColorGREEN,
    241       output.getColor(viewport_rect.width() - 1, viewport_rect.height() - 1));
    242 
    243   list.clear();
    244 
    245   // Draw a smaller magenta rect without filling the viewport in a separate
    246   // frame.
    247   gfx::Rect smaller_rect(20, 20, 60, 60);
    248 
    249   RenderPass::Id root_smaller_pass_id(2, 0);
    250   TestRenderPass* root_smaller_pass = AddRenderPass(
    251       &list, root_smaller_pass_id, viewport_rect, gfx::Transform());
    252   AddQuad(root_smaller_pass, smaller_rect, SK_ColorMAGENTA);
    253 
    254   renderer()->DecideRenderPassAllocationsForFrame(list);
    255   renderer()->DrawFrame(&list);
    256   renderer()->GetFramebufferPixels(output.getPixels(), viewport_rect);
    257 
    258   // If we didn't clear, the borders should still be green.
    259   EXPECT_EQ(SK_ColorGREEN, output.getColor(0, 0));
    260   EXPECT_EQ(SK_ColorGREEN,
    261       output.getColor(viewport_rect.width() - 1, viewport_rect.height() - 1));
    262 
    263   EXPECT_EQ(SK_ColorMAGENTA,
    264             output.getColor(smaller_rect.x(), smaller_rect.y()));
    265   EXPECT_EQ(SK_ColorMAGENTA,
    266       output.getColor(smaller_rect.right() - 1, smaller_rect.bottom() - 1));
    267 }
    268 
    269 }  // namespace
    270 }  // namespace cc
    271