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