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.
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"
20 const drmModeModeInfo kDefaultMode =
21 {0, 6, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, {'\0'}};
23 // Mock file descriptor ID.
27 const uint32_t kConnectorId = 1;
30 const uint32_t kCrtcId = 1;
32 const uint32_t kDPMSPropertyId = 1;
34 const gfx::AcceleratedWidget kDefaultWidgetHandle = 1;
36 // The real DriWrapper makes actual DRM calls which we can't use in unit tests.
37 class MockDriWrapper : public gfx::DriWrapper {
39 MockDriWrapper(int fd) : DriWrapper(""),
40 add_framebuffer_expectation_(true),
41 page_flip_expectation_(true) {
45 virtual ~MockDriWrapper() { fd_ = -1; }
47 virtual drmModeCrtc* GetCrtc(uint32_t crtc_id) OVERRIDE {
48 return new drmModeCrtc;
51 virtual void FreeCrtc(drmModeCrtc* crtc) OVERRIDE {
55 virtual bool SetCrtc(uint32_t crtc_id,
58 drmModeModeInfo* mode) OVERRIDE {
62 virtual bool SetCrtc(drmModeCrtc* crtc, uint32_t* connectors) OVERRIDE {
66 virtual bool AddFramebuffer(const drmModeModeInfo& mode,
71 uint32_t* framebuffer) OVERRIDE {
72 return add_framebuffer_expectation_;
75 virtual bool RemoveFramebuffer(uint32_t framebuffer) OVERRIDE { return true; }
77 virtual bool PageFlip(uint32_t crtc_id,
79 void* data) OVERRIDE {
80 static_cast<gfx::HardwareDisplayController*>(data)->get_surface()
82 return page_flip_expectation_;
85 virtual bool ConnectorSetProperty(uint32_t connector_id,
87 uint64_t value) OVERRIDE { return true; }
89 virtual bool SetCursor(uint32_t crtc_id,
92 uint32_t height) OVERRIDE { return true; }
94 virtual bool MoveCursor(uint32_t crtc_id, int x, int y) OVERRIDE {
98 void set_add_framebuffer_expectation(bool state) {
99 add_framebuffer_expectation_ = state;
102 void set_page_flip_expectation(bool state) {
103 page_flip_expectation_ = state;
107 bool add_framebuffer_expectation_;
108 bool page_flip_expectation_;
110 DISALLOW_COPY_AND_ASSIGN(MockDriWrapper);
113 class MockDriSkBitmap : public gfx::DriSkBitmap {
115 MockDriSkBitmap() : DriSkBitmap(kFd) {}
116 virtual ~MockDriSkBitmap() {}
118 virtual bool Initialize(const SkImageInfo& info) OVERRIDE {
120 eraseColor(SK_ColorBLACK);
125 DISALLOW_COPY_AND_ASSIGN(MockDriSkBitmap);
128 class MockDriSurface : public gfx::DriSurface {
130 MockDriSurface(gfx::DriWrapper* dri, const gfx::Size& size)
131 : DriSurface(dri, size) {}
132 virtual ~MockDriSurface() {}
134 const std::vector<MockDriSkBitmap*>& bitmaps() const { return bitmaps_; }
137 virtual gfx::DriSkBitmap* CreateBuffer() OVERRIDE {
138 MockDriSkBitmap* bitmap = new MockDriSkBitmap();
139 bitmaps_.push_back(bitmap);
144 std::vector<MockDriSkBitmap*> bitmaps_; // Not owned.
146 DISALLOW_COPY_AND_ASSIGN(MockDriSurface);
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 {
156 MockDriSurfaceFactory()
157 : DriSurfaceFactory(),
159 drm_wrapper_expectation_(true),
160 initialize_controller_expectation_(true) {}
161 virtual ~MockDriSurfaceFactory() {};
163 void set_drm_wrapper_expectation(bool state) {
164 drm_wrapper_expectation_ = state;
167 void set_initialize_controller_expectation(bool state) {
168 initialize_controller_expectation_ = state;
171 MockDriWrapper* get_drm() const {
175 const std::vector<MockDriSurface*>& get_surfaces() const { return surfaces_; }
178 virtual gfx::DriSurface* CreateSurface(const gfx::Size& size) OVERRIDE {
179 MockDriSurface* surface = new MockDriSurface(mock_drm_, size);
180 surfaces_.push_back(surface);
184 virtual gfx::DriWrapper* CreateWrapper() OVERRIDE {
185 if (drm_wrapper_expectation_)
186 mock_drm_ = new MockDriWrapper(kFd);
188 mock_drm_ = new MockDriWrapper(-1);
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,
210 virtual void WaitForPageFlipEvent(int fd) OVERRIDE {}
212 MockDriWrapper* mock_drm_;
213 bool drm_wrapper_expectation_;
214 bool initialize_controller_expectation_;
215 std::vector<MockDriSurface*> surfaces_; // Not owned.
217 DISALLOW_COPY_AND_ASSIGN(MockDriSurfaceFactory);
222 class DriSurfaceFactoryTest : public testing::Test {
224 DriSurfaceFactoryTest() {}
226 virtual void SetUp() OVERRIDE;
227 virtual void TearDown() OVERRIDE;
229 scoped_ptr<base::MessageLoop> message_loop_;
230 scoped_ptr<MockDriSurfaceFactory> factory_;
233 DISALLOW_COPY_AND_ASSIGN(DriSurfaceFactoryTest);
236 void DriSurfaceFactoryTest::SetUp() {
237 message_loop_.reset(new base::MessageLoopForUI);
238 factory_.reset(new MockDriSurfaceFactory());
241 void DriSurfaceFactoryTest::TearDown() {
243 message_loop_.reset();
246 TEST_F(DriSurfaceFactoryTest, FailInitialization) {
247 factory_->set_drm_wrapper_expectation(false);
249 EXPECT_EQ(gfx::SurfaceFactoryOzone::FAILED, factory_->InitializeHardware());
252 TEST_F(DriSurfaceFactoryTest, SuccessfulInitialization) {
253 EXPECT_EQ(gfx::SurfaceFactoryOzone::INITIALIZED,
254 factory_->InitializeHardware());
257 TEST_F(DriSurfaceFactoryTest, FailSurfaceInitialization) {
258 factory_->set_initialize_controller_expectation(false);
260 EXPECT_EQ(gfx::SurfaceFactoryOzone::INITIALIZED,
261 factory_->InitializeHardware());
263 gfx::AcceleratedWidget w = factory_->GetAcceleratedWidget();
264 EXPECT_EQ(kDefaultWidgetHandle, w);
266 EXPECT_EQ(gfx::kNullAcceleratedWidget, factory_->RealizeAcceleratedWidget(w));
269 TEST_F(DriSurfaceFactoryTest, FailBindingSurfaceToController) {
270 EXPECT_EQ(gfx::SurfaceFactoryOzone::INITIALIZED,
271 factory_->InitializeHardware());
273 factory_->get_drm()->set_add_framebuffer_expectation(false);
275 gfx::AcceleratedWidget w = factory_->GetAcceleratedWidget();
276 EXPECT_EQ(kDefaultWidgetHandle, w);
278 EXPECT_EQ(gfx::kNullAcceleratedWidget, factory_->RealizeAcceleratedWidget(w));
281 TEST_F(DriSurfaceFactoryTest, SuccessfulWidgetRealization) {
282 EXPECT_EQ(gfx::SurfaceFactoryOzone::INITIALIZED,
283 factory_->InitializeHardware());
285 gfx::AcceleratedWidget w = factory_->GetAcceleratedWidget();
286 EXPECT_EQ(kDefaultWidgetHandle, w);
288 EXPECT_NE(gfx::kNullAcceleratedWidget, factory_->RealizeAcceleratedWidget(w));
291 TEST_F(DriSurfaceFactoryTest, FailSchedulePageFlip) {
292 EXPECT_EQ(gfx::SurfaceFactoryOzone::INITIALIZED,
293 factory_->InitializeHardware());
295 factory_->get_drm()->set_page_flip_expectation(false);
297 gfx::AcceleratedWidget w = factory_->GetAcceleratedWidget();
298 EXPECT_EQ(kDefaultWidgetHandle, w);
300 EXPECT_NE(gfx::kNullAcceleratedWidget, factory_->RealizeAcceleratedWidget(w));
302 EXPECT_FALSE(factory_->SchedulePageFlip(w));
305 TEST_F(DriSurfaceFactoryTest, SuccessfulSchedulePageFlip) {
306 EXPECT_EQ(gfx::SurfaceFactoryOzone::INITIALIZED,
307 factory_->InitializeHardware());
309 gfx::AcceleratedWidget w = factory_->GetAcceleratedWidget();
310 EXPECT_EQ(kDefaultWidgetHandle, w);
312 EXPECT_NE(gfx::kNullAcceleratedWidget, factory_->RealizeAcceleratedWidget(w));
314 EXPECT_TRUE(factory_->SchedulePageFlip(w));
317 TEST_F(DriSurfaceFactoryTest, SetCursorImage) {
318 EXPECT_EQ(gfx::SurfaceFactoryOzone::INITIALIZED,
319 factory_->InitializeHardware());
321 gfx::AcceleratedWidget w = factory_->GetAcceleratedWidget();
322 EXPECT_EQ(kDefaultWidgetHandle, w);
323 EXPECT_NE(gfx::kNullAcceleratedWidget, factory_->RealizeAcceleratedWidget(w));
326 SkImageInfo info = SkImageInfo::Make(
327 6, 4, kPMColor_SkColorType, kPremul_SkAlphaType);
328 image.allocPixels(info);
329 image.eraseColor(SK_ColorWHITE);
331 factory_->SetHardwareCursor(w, image, gfx::Point(4, 2));
332 const std::vector<MockDriSurface*>& surfaces = factory_->get_surfaces();
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();
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));
346 EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT),
347 bitmaps[1]->getColor(j, i));