Home | History | Annotate | Download | only in dri
      1 // Copyright 2014 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 <vector>
      6 
      7 #include "base/memory/scoped_ptr.h"
      8 #include "base/message_loop/message_loop.h"
      9 #include "testing/gtest/include/gtest/gtest.h"
     10 #include "third_party/skia/include/core/SkCanvas.h"
     11 #include "third_party/skia/include/core/SkColor.h"
     12 #include "third_party/skia/include/core/SkImageInfo.h"
     13 #include "ui/ozone/platform/dri/dri_buffer.h"
     14 #include "ui/ozone/platform/dri/dri_surface.h"
     15 #include "ui/ozone/platform/dri/dri_surface_factory.h"
     16 #include "ui/ozone/platform/dri/hardware_display_controller.h"
     17 #include "ui/ozone/platform/dri/screen_manager.h"
     18 #include "ui/ozone/platform/dri/test/mock_dri_surface.h"
     19 #include "ui/ozone/platform/dri/test/mock_dri_wrapper.h"
     20 #include "ui/ozone/platform/dri/test/mock_surface_generator.h"
     21 #include "ui/ozone/public/surface_factory_ozone.h"
     22 #include "ui/ozone/public/surface_ozone_canvas.h"
     23 
     24 namespace {
     25 
     26 const drmModeModeInfo kDefaultMode =
     27     {0, 6, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, {'\0'}};
     28 
     29 // SSFO would normally allocate DRM resources. We can't rely on having a DRM
     30 // backend to allocate and display our buffers. Thus, we replace these
     31 // resources with stubs. For DRM calls, we simply use stubs that do nothing and
     32 // for buffers we use the default SkBitmap allocator.
     33 class MockDriSurfaceFactory : public ui::DriSurfaceFactory {
     34  public:
     35   MockDriSurfaceFactory(ui::DriWrapper* dri, ui::ScreenManager* screen_manager)
     36       : DriSurfaceFactory(dri, screen_manager), dri_(dri) {}
     37   virtual ~MockDriSurfaceFactory() {};
     38 
     39   const std::vector<ui::MockDriSurface*>& get_surfaces() const {
     40     return surfaces_;
     41   }
     42 
     43  private:
     44   virtual ui::DriSurface* CreateSurface(const gfx::Size& size) OVERRIDE {
     45     ui::MockDriSurface* surface = new ui::MockDriSurface(dri_, size);
     46     surfaces_.push_back(surface);
     47     return surface;
     48   }
     49 
     50   ui::DriWrapper* dri_;
     51   std::vector<ui::MockDriSurface*> surfaces_;  // Not owned.
     52 
     53   DISALLOW_COPY_AND_ASSIGN(MockDriSurfaceFactory);
     54 };
     55 
     56 class MockScreenManager : public ui::ScreenManager {
     57  public:
     58   MockScreenManager(ui::DriWrapper* dri,
     59                     ui::ScanoutSurfaceGenerator* surface_generator)
     60       : ScreenManager(dri, surface_generator),
     61         dri_(dri) {}
     62   virtual ~MockScreenManager() {}
     63 
     64   // Normally we'd use DRM to figure out the controller configuration. But we
     65   // can't use DRM in unit tests, so we just create a fake configuration.
     66   virtual void ForceInitializationOfPrimaryDisplay() OVERRIDE {
     67     ConfigureDisplayController(1, 2, kDefaultMode);
     68   }
     69 
     70  private:
     71   ui::DriWrapper* dri_;  // Not owned.
     72   std::vector<ui::MockDriSurface*> surfaces_;  // Not owned.
     73 
     74   DISALLOW_COPY_AND_ASSIGN(MockScreenManager);
     75 };
     76 
     77 }  // namespace
     78 
     79 class DriSurfaceFactoryTest : public testing::Test {
     80  public:
     81   DriSurfaceFactoryTest() {}
     82 
     83   virtual void SetUp() OVERRIDE;
     84   virtual void TearDown() OVERRIDE;
     85  protected:
     86   scoped_ptr<base::MessageLoop> message_loop_;
     87   scoped_ptr<ui::MockDriWrapper> dri_;
     88   scoped_ptr<ui::MockSurfaceGenerator> surface_generator_;
     89   scoped_ptr<MockScreenManager> screen_manager_;
     90   scoped_ptr<MockDriSurfaceFactory> factory_;
     91 
     92  private:
     93   DISALLOW_COPY_AND_ASSIGN(DriSurfaceFactoryTest);
     94 };
     95 
     96 void DriSurfaceFactoryTest::SetUp() {
     97   message_loop_.reset(new base::MessageLoopForUI);
     98   dri_.reset(new ui::MockDriWrapper(3));
     99   surface_generator_.reset(new ui::MockSurfaceGenerator(dri_.get()));
    100   screen_manager_.reset(new MockScreenManager(dri_.get(),
    101                                               surface_generator_.get()));
    102   factory_.reset(new MockDriSurfaceFactory(dri_.get(), screen_manager_.get()));
    103 }
    104 
    105 void DriSurfaceFactoryTest::TearDown() {
    106   factory_.reset();
    107   message_loop_.reset();
    108 }
    109 
    110 TEST_F(DriSurfaceFactoryTest, FailInitialization) {
    111   dri_->fail_init();
    112   EXPECT_EQ(ui::SurfaceFactoryOzone::FAILED, factory_->InitializeHardware());
    113 }
    114 
    115 TEST_F(DriSurfaceFactoryTest, SuccessfulInitialization) {
    116   EXPECT_EQ(ui::SurfaceFactoryOzone::INITIALIZED,
    117             factory_->InitializeHardware());
    118 }
    119 
    120 TEST_F(DriSurfaceFactoryTest, SuccessfulWidgetRealization) {
    121   EXPECT_EQ(ui::SurfaceFactoryOzone::INITIALIZED,
    122             factory_->InitializeHardware());
    123 
    124   gfx::AcceleratedWidget w = factory_->GetAcceleratedWidget();
    125   EXPECT_EQ(ui::DriSurfaceFactory::kDefaultWidgetHandle, w);
    126 
    127   EXPECT_TRUE(factory_->CreateCanvasForWidget(w));
    128 }
    129 
    130 TEST_F(DriSurfaceFactoryTest, CheckNativeSurfaceContents) {
    131   EXPECT_EQ(ui::SurfaceFactoryOzone::INITIALIZED,
    132             factory_->InitializeHardware());
    133 
    134   gfx::AcceleratedWidget w = factory_->GetAcceleratedWidget();
    135   EXPECT_EQ(ui::DriSurfaceFactory::kDefaultWidgetHandle, w);
    136 
    137   scoped_ptr<ui::SurfaceOzoneCanvas> surface =
    138       factory_->CreateCanvasForWidget(w);
    139 
    140   surface->ResizeCanvas(
    141       gfx::Size(kDefaultMode.hdisplay, kDefaultMode.vdisplay));
    142   surface->GetCanvas()->drawColor(SK_ColorWHITE);
    143   surface->PresentCanvas(
    144       gfx::Rect(0, 0, kDefaultMode.hdisplay / 2, kDefaultMode.vdisplay / 2));
    145 
    146   const std::vector<ui::DriBuffer*>& bitmaps =
    147       surface_generator_->surfaces()[0]->bitmaps();
    148 
    149   SkBitmap image;
    150   bitmaps[1]->canvas()->readPixels(&image, 0, 0);
    151 
    152   // Make sure the updates are correctly propagated to the native surface.
    153   for (int i = 0; i < image.height(); ++i) {
    154     for (int j = 0; j < image.width(); ++j) {
    155       if (j < kDefaultMode.hdisplay / 2 && i < kDefaultMode.vdisplay / 2)
    156         EXPECT_EQ(SK_ColorWHITE, image.getColor(j, i));
    157       else
    158         EXPECT_EQ(SK_ColorBLACK, image.getColor(j, i));
    159     }
    160   }
    161 }
    162 
    163 TEST_F(DriSurfaceFactoryTest, SetCursorImage) {
    164   EXPECT_EQ(ui::SurfaceFactoryOzone::INITIALIZED,
    165             factory_->InitializeHardware());
    166 
    167   gfx::AcceleratedWidget w = factory_->GetAcceleratedWidget();
    168   EXPECT_EQ(ui::DriSurfaceFactory::kDefaultWidgetHandle, w);
    169 
    170   scoped_ptr<ui::SurfaceOzoneCanvas> surf = factory_->CreateCanvasForWidget(w);
    171   EXPECT_TRUE(surf);
    172 
    173   SkBitmap image;
    174   SkImageInfo info = SkImageInfo::Make(
    175       6, 4, kN32_SkColorType, kPremul_SkAlphaType);
    176   image.allocPixels(info);
    177   image.eraseColor(SK_ColorWHITE);
    178 
    179   factory_->SetHardwareCursor(w, image, gfx::Point(4, 2));
    180   const std::vector<ui::MockDriSurface*>& surfaces = factory_->get_surfaces();
    181 
    182   // The first surface is the cursor surface since it is allocated early in the
    183   // initialization process.
    184   const std::vector<ui::DriBuffer*>& bitmaps = surfaces[0]->bitmaps();
    185 
    186   // The surface should have been initialized to a double-buffered surface.
    187   EXPECT_EQ(2u, bitmaps.size());
    188 
    189   SkBitmap cursor;
    190   bitmaps[1]->canvas()->readPixels(&cursor, 0, 0);
    191 
    192   // Check that the frontbuffer is displaying the right image as set above.
    193   for (int i = 0; i < cursor.height(); ++i) {
    194     for (int j = 0; j < cursor.width(); ++j) {
    195       if (j < info.width() && i < info.height())
    196         EXPECT_EQ(SK_ColorWHITE, cursor.getColor(j, i));
    197       else
    198         EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT),
    199                   cursor.getColor(j, i));
    200     }
    201   }
    202 }
    203