Upstream version 7.35.144.0
[platform/framework/web/crosswalk.git] / src / ui / gfx / ozone / dri / dri_surface_factory_unittest.cc
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 <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/SkColor.h"
11 #include "ui/gfx/ozone/dri/dri_skbitmap.h"
12 #include "ui/gfx/ozone/dri/dri_surface.h"
13 #include "ui/gfx/ozone/dri/dri_surface_factory.h"
14 #include "ui/gfx/ozone/dri/dri_wrapper.h"
15 #include "ui/gfx/ozone/dri/hardware_display_controller.h"
16 #include "ui/gfx/ozone/surface_factory_ozone.h"
17
18 namespace {
19
20 const drmModeModeInfo kDefaultMode =
21     {0, 6, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, {'\0'}};
22
23 // Mock file descriptor ID.
24 const int kFd = 3;
25
26 // Mock connector ID.
27 const uint32_t kConnectorId = 1;
28
29 // Mock CRTC ID.
30 const uint32_t kCrtcId = 1;
31
32 const uint32_t kDPMSPropertyId = 1;
33
34 const gfx::AcceleratedWidget kDefaultWidgetHandle = 1;
35
36 // The real DriWrapper makes actual DRM calls which we can't use in unit tests.
37 class MockDriWrapper : public gfx::DriWrapper {
38  public:
39   MockDriWrapper(int fd) : DriWrapper(""),
40                                 add_framebuffer_expectation_(true),
41                                 page_flip_expectation_(true) {
42     fd_ = fd;
43   }
44
45   virtual ~MockDriWrapper() { fd_ = -1; }
46
47   virtual drmModeCrtc* GetCrtc(uint32_t crtc_id) OVERRIDE {
48     return new drmModeCrtc;
49   }
50
51   virtual void FreeCrtc(drmModeCrtc* crtc) OVERRIDE {
52     delete crtc;
53   }
54
55   virtual bool SetCrtc(uint32_t crtc_id,
56                        uint32_t framebuffer,
57                        uint32_t* connectors,
58                        drmModeModeInfo* mode) OVERRIDE {
59     return true;
60   }
61
62   virtual bool SetCrtc(drmModeCrtc* crtc, uint32_t* connectors) OVERRIDE {
63     return true;
64   }
65
66   virtual bool AddFramebuffer(const drmModeModeInfo& mode,
67                               uint8_t depth,
68                               uint8_t bpp,
69                               uint32_t stride,
70                               uint32_t handle,
71                               uint32_t* framebuffer) OVERRIDE {
72     return add_framebuffer_expectation_;
73   }
74
75   virtual bool RemoveFramebuffer(uint32_t framebuffer) OVERRIDE { return true; }
76
77   virtual bool PageFlip(uint32_t crtc_id,
78                         uint32_t framebuffer,
79                         void* data) OVERRIDE {
80     static_cast<gfx::HardwareDisplayController*>(data)->get_surface()
81         ->SwapBuffers();
82     return page_flip_expectation_;
83   }
84
85   virtual bool ConnectorSetProperty(uint32_t connector_id,
86                                     uint32_t property_id,
87                                     uint64_t value) OVERRIDE { return true; }
88
89   virtual bool SetCursor(uint32_t crtc_id,
90                          uint32_t handle,
91                          uint32_t width,
92                          uint32_t height) OVERRIDE { return true; }
93
94   virtual bool MoveCursor(uint32_t crtc_id, int x, int y) OVERRIDE {
95     return true;
96   }
97
98   void set_add_framebuffer_expectation(bool state) {
99     add_framebuffer_expectation_ = state;
100   }
101
102   void set_page_flip_expectation(bool state) {
103     page_flip_expectation_ = state;
104   }
105
106  private:
107   bool add_framebuffer_expectation_;
108   bool page_flip_expectation_;
109
110   DISALLOW_COPY_AND_ASSIGN(MockDriWrapper);
111 };
112
113 class MockDriSkBitmap : public gfx::DriSkBitmap {
114  public:
115   MockDriSkBitmap() : DriSkBitmap(kFd) {}
116   virtual ~MockDriSkBitmap() {}
117
118   virtual bool Initialize(const SkImageInfo& info) OVERRIDE {
119     allocPixels(info);
120     eraseColor(SK_ColorBLACK);
121     return true;
122   }
123
124  private:
125   DISALLOW_COPY_AND_ASSIGN(MockDriSkBitmap);
126 };
127
128 class MockDriSurface : public gfx::DriSurface {
129  public:
130   MockDriSurface(gfx::DriWrapper* dri, const gfx::Size& size)
131       : DriSurface(dri, size) {}
132   virtual ~MockDriSurface() {}
133
134   const std::vector<MockDriSkBitmap*>& bitmaps() const { return bitmaps_; }
135
136  private:
137   virtual gfx::DriSkBitmap* CreateBuffer() OVERRIDE {
138      MockDriSkBitmap* bitmap = new MockDriSkBitmap();
139      bitmaps_.push_back(bitmap);
140
141      return bitmap;
142   }
143
144   std::vector<MockDriSkBitmap*> bitmaps_;  // Not owned.
145
146   DISALLOW_COPY_AND_ASSIGN(MockDriSurface);
147 };
148
149 // SSFO would normally allocate DRM resources. We can't rely on having a DRM
150 // backend to allocate and display our buffers. Thus, we replace these
151 // resources with stubs. For DRM calls, we simply use stubs that do nothing and
152 // for buffers we use the default SkBitmap allocator.
153 class MockDriSurfaceFactory
154     : public gfx::DriSurfaceFactory {
155  public:
156   MockDriSurfaceFactory()
157       : DriSurfaceFactory(),
158         mock_drm_(NULL),
159         drm_wrapper_expectation_(true),
160         initialize_controller_expectation_(true) {}
161   virtual ~MockDriSurfaceFactory() {};
162
163   void set_drm_wrapper_expectation(bool state) {
164     drm_wrapper_expectation_ = state;
165   }
166
167   void set_initialize_controller_expectation(bool state) {
168     initialize_controller_expectation_ = state;
169   }
170
171   MockDriWrapper* get_drm() const {
172     return mock_drm_;
173   }
174
175   const std::vector<MockDriSurface*>& get_surfaces() const { return surfaces_; }
176
177  private:
178   virtual gfx::DriSurface* CreateSurface(const gfx::Size& size) OVERRIDE {
179     MockDriSurface* surface = new MockDriSurface(mock_drm_, size);
180     surfaces_.push_back(surface);
181     return surface;
182   }
183
184   virtual gfx::DriWrapper* CreateWrapper() OVERRIDE {
185     if (drm_wrapper_expectation_)
186       mock_drm_ = new MockDriWrapper(kFd);
187     else
188       mock_drm_ = new MockDriWrapper(-1);
189
190     return mock_drm_;
191   }
192
193   // Normally we'd use DRM to figure out the controller configuration. But we
194   // can't use DRM in unit tests, so we just create a fake configuration.
195   virtual bool InitializeControllerForPrimaryDisplay(
196       gfx::DriWrapper* drm,
197       gfx::HardwareDisplayController* controller) OVERRIDE {
198     if (initialize_controller_expectation_) {
199       controller->SetControllerInfo(drm,
200                                     kConnectorId,
201                                     kCrtcId,
202                                     kDPMSPropertyId,
203                                     kDefaultMode);
204       return true;
205     } else {
206       return false;
207     }
208   }
209
210   virtual void WaitForPageFlipEvent(int fd) OVERRIDE {}
211
212   MockDriWrapper* mock_drm_;
213   bool drm_wrapper_expectation_;
214   bool initialize_controller_expectation_;
215   std::vector<MockDriSurface*> surfaces_;  // Not owned.
216
217   DISALLOW_COPY_AND_ASSIGN(MockDriSurfaceFactory);
218 };
219
220 }  // namespace
221
222 class DriSurfaceFactoryTest : public testing::Test {
223  public:
224   DriSurfaceFactoryTest() {}
225
226   virtual void SetUp() OVERRIDE;
227   virtual void TearDown() OVERRIDE;
228  protected:
229   scoped_ptr<base::MessageLoop> message_loop_;
230   scoped_ptr<MockDriSurfaceFactory> factory_;
231
232  private:
233   DISALLOW_COPY_AND_ASSIGN(DriSurfaceFactoryTest);
234 };
235
236 void DriSurfaceFactoryTest::SetUp() {
237   message_loop_.reset(new base::MessageLoopForUI);
238   factory_.reset(new MockDriSurfaceFactory());
239 }
240
241 void DriSurfaceFactoryTest::TearDown() {
242   factory_.reset();
243   message_loop_.reset();
244 }
245
246 TEST_F(DriSurfaceFactoryTest, FailInitialization) {
247   factory_->set_drm_wrapper_expectation(false);
248
249   EXPECT_EQ(gfx::SurfaceFactoryOzone::FAILED, factory_->InitializeHardware());
250 }
251
252 TEST_F(DriSurfaceFactoryTest, SuccessfulInitialization) {
253   EXPECT_EQ(gfx::SurfaceFactoryOzone::INITIALIZED,
254             factory_->InitializeHardware());
255 }
256
257 TEST_F(DriSurfaceFactoryTest, FailSurfaceInitialization) {
258   factory_->set_initialize_controller_expectation(false);
259
260   EXPECT_EQ(gfx::SurfaceFactoryOzone::INITIALIZED,
261             factory_->InitializeHardware());
262
263   gfx::AcceleratedWidget w = factory_->GetAcceleratedWidget();
264   EXPECT_EQ(kDefaultWidgetHandle, w);
265
266   EXPECT_EQ(gfx::kNullAcceleratedWidget, factory_->RealizeAcceleratedWidget(w));
267 }
268
269 TEST_F(DriSurfaceFactoryTest, FailBindingSurfaceToController) {
270   EXPECT_EQ(gfx::SurfaceFactoryOzone::INITIALIZED,
271             factory_->InitializeHardware());
272
273   factory_->get_drm()->set_add_framebuffer_expectation(false);
274
275   gfx::AcceleratedWidget w = factory_->GetAcceleratedWidget();
276   EXPECT_EQ(kDefaultWidgetHandle, w);
277
278   EXPECT_EQ(gfx::kNullAcceleratedWidget, factory_->RealizeAcceleratedWidget(w));
279 }
280
281 TEST_F(DriSurfaceFactoryTest, SuccessfulWidgetRealization) {
282   EXPECT_EQ(gfx::SurfaceFactoryOzone::INITIALIZED,
283             factory_->InitializeHardware());
284
285   gfx::AcceleratedWidget w = factory_->GetAcceleratedWidget();
286   EXPECT_EQ(kDefaultWidgetHandle, w);
287
288   EXPECT_NE(gfx::kNullAcceleratedWidget, factory_->RealizeAcceleratedWidget(w));
289 }
290
291 TEST_F(DriSurfaceFactoryTest, FailSchedulePageFlip) {
292   EXPECT_EQ(gfx::SurfaceFactoryOzone::INITIALIZED,
293             factory_->InitializeHardware());
294
295   factory_->get_drm()->set_page_flip_expectation(false);
296
297   gfx::AcceleratedWidget w = factory_->GetAcceleratedWidget();
298   EXPECT_EQ(kDefaultWidgetHandle, w);
299
300   EXPECT_NE(gfx::kNullAcceleratedWidget, factory_->RealizeAcceleratedWidget(w));
301
302   EXPECT_FALSE(factory_->SchedulePageFlip(w));
303 }
304
305 TEST_F(DriSurfaceFactoryTest, SuccessfulSchedulePageFlip) {
306   EXPECT_EQ(gfx::SurfaceFactoryOzone::INITIALIZED,
307             factory_->InitializeHardware());
308
309   gfx::AcceleratedWidget w = factory_->GetAcceleratedWidget();
310   EXPECT_EQ(kDefaultWidgetHandle, w);
311
312   EXPECT_NE(gfx::kNullAcceleratedWidget, factory_->RealizeAcceleratedWidget(w));
313
314   EXPECT_TRUE(factory_->SchedulePageFlip(w));
315 }
316
317 TEST_F(DriSurfaceFactoryTest, SetCursorImage) {
318   EXPECT_EQ(gfx::SurfaceFactoryOzone::INITIALIZED,
319             factory_->InitializeHardware());
320
321   gfx::AcceleratedWidget w = factory_->GetAcceleratedWidget();
322   EXPECT_EQ(kDefaultWidgetHandle, w);
323   EXPECT_NE(gfx::kNullAcceleratedWidget, factory_->RealizeAcceleratedWidget(w));
324
325   SkBitmap image;
326   SkImageInfo info = SkImageInfo::Make(
327       6, 4, kPMColor_SkColorType, kPremul_SkAlphaType);
328   image.allocPixels(info);
329   image.eraseColor(SK_ColorWHITE);
330
331   factory_->SetHardwareCursor(w, image, gfx::Point(4, 2));
332   const std::vector<MockDriSurface*>& surfaces = factory_->get_surfaces();
333
334   // The first surface is the cursor surface since it is allocated early in the
335   // initialization process.
336   const std::vector<MockDriSkBitmap*>& bitmaps = surfaces[0]->bitmaps();
337
338   // The surface should have been initialized to a double-buffered surface.
339   EXPECT_EQ(2u, bitmaps.size());
340   // Check that the frontbuffer is displaying the right image as set above.
341   for (int i = 0; i < bitmaps[1]->height(); ++i) {
342     for (int j = 0; j < bitmaps[1]->width(); ++j) {
343       if (j < info.width() && i < info.height())
344         EXPECT_EQ(SK_ColorWHITE, bitmaps[1]->getColor(j, i));
345       else
346         EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT),
347                   bitmaps[1]->getColor(j, i));
348     }
349   }
350 }