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: 33 MockDriWrapper() : DriWrapper(""), id_(1) { fd_ = kFd; } 34 virtual ~MockDriWrapper() { fd_ = -1; } 35 36 virtual drmModeCrtc* GetCrtc(uint32_t crtc_id) OVERRIDE { return NULL; } 37 virtual void FreeCrtc(drmModeCrtc* crtc) OVERRIDE {} 38 virtual bool SetCrtc(uint32_t crtc_id, 39 uint32_t framebuffer, 40 uint32_t* connectors, 41 drmModeModeInfo* mode) OVERRIDE { return true; } 42 virtual bool SetCrtc(drmModeCrtc* crtc, uint32_t* connectors) OVERRIDE { 43 return true; 44 } 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 } 54 virtual bool RemoveFramebuffer(uint32_t framebuffer) OVERRIDE { return true; } 55 virtual bool PageFlip(uint32_t crtc_id, 56 uint32_t framebuffer, 57 void* data) OVERRIDE { 58 return true; 59 } 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: 71 MockDriSkBitmap(int fd, 72 bool initialize_expectation) 73 : DriSkBitmap(fd), 74 initialize_expectation_(initialize_expectation) {} 75 virtual ~MockDriSkBitmap() {} 76 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: 95 MockDriSurface(gfx::HardwareDisplayController* controller) 96 : DriSurface(controller), 97 initialize_expectation_(true) {} 98 virtual ~MockDriSurface() {} 99 100 void set_initialize_expectation(bool state) { 101 initialize_expectation_ = state; 102 } 103 104 private: 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: 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 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 141 void DriSurfaceTest::TearDown() { 142 surface_.reset(); 143 controller_.reset(); 144 drm_.reset(); 145 } 146 147 TEST_F(DriSurfaceTest, FailInitialization) { 148 surface_->set_initialize_expectation(false); 149 EXPECT_FALSE(surface_->Initialize()); 150 } 151 152 TEST_F(DriSurfaceTest, SuccessfulInitialization) { 153 EXPECT_TRUE(surface_->Initialize()); 154 } 155 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 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 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