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 "testing/gtest/include/gtest/gtest.h"
6 #include "third_party/skia/include/core/SkCanvas.h"
7 #include "third_party/skia/include/core/SkColor.h"
8 #include "third_party/skia/include/core/SkDevice.h"
9 #include "ui/gfx/ozone/dri/dri_skbitmap.h"
10 #include "ui/gfx/ozone/dri/dri_surface.h"
11 #include "ui/gfx/ozone/dri/hardware_display_controller.h"
12
13 namespace {
14
15 // Create a basic mode for a 6x4 screen.
16 const drmModeModeInfo kDefaultMode =
17 {0, 6, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, {'\0'}};
18
19 // Mock file descriptor ID.
20 const int kFd = 3;
21
22 // Mock connector ID.
23 const uint32_t kConnectorId = 1;
24
25 // Mock CRTC ID.
26 const uint32_t kCrtcId = 1;
27
28 // Mock DPMS property ID.
29 const uint32_t kDPMSPropertyId = 1;
30
31 class MockDriWrapper : public gfx::DriWrapper {
32 public:
MockDriWrapper()33 MockDriWrapper() : DriWrapper(""), id_(1) { fd_ = kFd; }
~MockDriWrapper()34 virtual ~MockDriWrapper() { fd_ = -1; }
35
GetCrtc(uint32_t crtc_id)36 virtual drmModeCrtc* GetCrtc(uint32_t crtc_id) OVERRIDE { return NULL; }
FreeCrtc(drmModeCrtc * crtc)37 virtual void FreeCrtc(drmModeCrtc* crtc) OVERRIDE {}
SetCrtc(uint32_t crtc_id,uint32_t framebuffer,uint32_t * connectors,drmModeModeInfo * mode)38 virtual bool SetCrtc(uint32_t crtc_id,
39 uint32_t framebuffer,
40 uint32_t* connectors,
41 drmModeModeInfo* mode) OVERRIDE { return true; }
SetCrtc(drmModeCrtc * crtc,uint32_t * connectors)42 virtual bool SetCrtc(drmModeCrtc* crtc, uint32_t* connectors) OVERRIDE {
43 return true;
44 }
AddFramebuffer(const drmModeModeInfo & mode,uint8_t depth,uint8_t bpp,uint32_t stride,uint32_t handle,uint32_t * framebuffer)45 virtual bool AddFramebuffer(const drmModeModeInfo& mode,
46 uint8_t depth,
47 uint8_t bpp,
48 uint32_t stride,
49 uint32_t handle,
50 uint32_t* framebuffer) OVERRIDE {
51 *framebuffer = id_++;
52 return true;
53 }
RemoveFramebuffer(uint32_t framebuffer)54 virtual bool RemoveFramebuffer(uint32_t framebuffer) OVERRIDE { return true; }
PageFlip(uint32_t crtc_id,uint32_t framebuffer,void * data)55 virtual bool PageFlip(uint32_t crtc_id,
56 uint32_t framebuffer,
57 void* data) OVERRIDE {
58 return true;
59 }
ConnectorSetProperty(uint32_t connector_id,uint32_t property_id,uint64_t value)60 virtual bool ConnectorSetProperty(uint32_t connector_id,
61 uint32_t property_id,
62 uint64_t value) OVERRIDE { return true; }
63
64 private:
65 int id_;
66 DISALLOW_COPY_AND_ASSIGN(MockDriWrapper);
67 };
68
69 class MockDriSkBitmap : public gfx::DriSkBitmap {
70 public:
MockDriSkBitmap(int fd,bool initialize_expectation)71 MockDriSkBitmap(int fd,
72 bool initialize_expectation)
73 : DriSkBitmap(fd),
74 initialize_expectation_(initialize_expectation) {}
~MockDriSkBitmap()75 virtual ~MockDriSkBitmap() {}
76
Initialize()77 virtual bool Initialize() OVERRIDE {
78 if (!initialize_expectation_)
79 return false;
80
81 allocPixels();
82 // Clear the bitmap to black.
83 eraseColor(SK_ColorBLACK);
84
85 return true;
86 }
87 private:
88 bool initialize_expectation_;
89
90 DISALLOW_COPY_AND_ASSIGN(MockDriSkBitmap);
91 };
92
93 class MockDriSurface : public gfx::DriSurface {
94 public:
MockDriSurface(gfx::HardwareDisplayController * controller)95 MockDriSurface(gfx::HardwareDisplayController* controller)
96 : DriSurface(controller),
97 initialize_expectation_(true) {}
~MockDriSurface()98 virtual ~MockDriSurface() {}
99
set_initialize_expectation(bool state)100 void set_initialize_expectation(bool state) {
101 initialize_expectation_ = state;
102 }
103
104 private:
CreateBuffer()105 virtual gfx::DriSkBitmap* CreateBuffer() OVERRIDE {
106 return new MockDriSkBitmap(kFd, initialize_expectation_);
107 }
108
109 bool initialize_expectation_;
110
111 DISALLOW_COPY_AND_ASSIGN(MockDriSurface);
112 };
113
114 } // namespace
115
116 class DriSurfaceTest : public testing::Test {
117 public:
DriSurfaceTest()118 DriSurfaceTest() {}
119
120 virtual void SetUp() OVERRIDE;
121 virtual void TearDown() OVERRIDE;
122
123 protected:
124 scoped_ptr<MockDriWrapper> drm_;
125 scoped_ptr<gfx::HardwareDisplayController> controller_;
126 scoped_ptr<MockDriSurface> surface_;
127
128 private:
129 DISALLOW_COPY_AND_ASSIGN(DriSurfaceTest);
130 };
131
SetUp()132 void DriSurfaceTest::SetUp() {
133 drm_.reset(new MockDriWrapper());
134 controller_.reset(new gfx::HardwareDisplayController());
135 controller_->SetControllerInfo(
136 drm_.get(), kConnectorId, kCrtcId, kDPMSPropertyId, kDefaultMode);
137
138 surface_.reset(new MockDriSurface(controller_.get()));
139 }
140
TearDown()141 void DriSurfaceTest::TearDown() {
142 surface_.reset();
143 controller_.reset();
144 drm_.reset();
145 }
146
TEST_F(DriSurfaceTest,FailInitialization)147 TEST_F(DriSurfaceTest, FailInitialization) {
148 surface_->set_initialize_expectation(false);
149 EXPECT_FALSE(surface_->Initialize());
150 }
151
TEST_F(DriSurfaceTest,SuccessfulInitialization)152 TEST_F(DriSurfaceTest, SuccessfulInitialization) {
153 EXPECT_TRUE(surface_->Initialize());
154 }
155
TEST_F(DriSurfaceTest,CheckFBIDOnSwap)156 TEST_F(DriSurfaceTest, CheckFBIDOnSwap) {
157 EXPECT_TRUE(surface_->Initialize());
158 controller_->BindSurfaceToController(
159 surface_.PassAs<gfx::DriSurface>());
160
161 // Check that the framebuffer ID is correct.
162 EXPECT_EQ(2u, controller_->get_surface()->GetFramebufferId());
163
164 controller_->get_surface()->SwapBuffers();
165
166 EXPECT_EQ(1u, controller_->get_surface()->GetFramebufferId());
167 }
168
TEST_F(DriSurfaceTest,CheckPixelPointerOnSwap)169 TEST_F(DriSurfaceTest, CheckPixelPointerOnSwap) {
170 EXPECT_TRUE(surface_->Initialize());
171
172 void* bitmap_pixels1 = surface_->GetDrawableForWidget()->getDevice()
173 ->accessBitmap(false).getPixels();
174
175 surface_->SwapBuffers();
176
177 void* bitmap_pixels2 = surface_->GetDrawableForWidget()->getDevice()
178 ->accessBitmap(false).getPixels();
179
180 // Check that once the buffers have been swapped the drawable's underlying
181 // pixels have been changed.
182 EXPECT_NE(bitmap_pixels1, bitmap_pixels2);
183 }
184
TEST_F(DriSurfaceTest,CheckCorrectBufferSync)185 TEST_F(DriSurfaceTest, CheckCorrectBufferSync) {
186 EXPECT_TRUE(surface_->Initialize());
187
188 SkCanvas* canvas = surface_->GetDrawableForWidget();
189 SkRect clip;
190 // Modify part of the canvas.
191 clip.set(0, 0,
192 canvas->getDeviceSize().width() / 2,
193 canvas->getDeviceSize().height() / 2);
194 canvas->clipRect(clip, SkRegion::kReplace_Op);
195
196 canvas->drawColor(SK_ColorWHITE);
197
198 surface_->SwapBuffers();
199
200 // Verify that the modified contents have been copied over on swap (make sure
201 // the 2 buffers have the same content).
202 for (int i = 0; i < canvas->getDeviceSize().height(); ++i) {
203 for (int j = 0; j < canvas->getDeviceSize().width(); ++j) {
204 if (i < clip.height() && j < clip.width())
205 EXPECT_EQ(SK_ColorWHITE,
206 canvas->getDevice()->accessBitmap(false).getColor(j, i));
207 else
208 EXPECT_EQ(SK_ColorBLACK,
209 canvas->getDevice()->accessBitmap(false).getColor(j, i));
210 }
211 }
212 }
213