| OLD | NEW |
| (Empty) |
| 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 "ui/ozone/platform/dri/dri_wrapper.h" | |
| 6 | |
| 7 #include <fcntl.h> | |
| 8 #include <sys/mman.h> | |
| 9 #include <unistd.h> | |
| 10 #include <xf86drm.h> | |
| 11 #include <xf86drmMode.h> | |
| 12 | |
| 13 #include "base/debug/trace_event.h" | |
| 14 #include "base/logging.h" | |
| 15 #include "base/stl_util.h" | |
| 16 #include "third_party/skia/include/core/SkImageInfo.h" | |
| 17 #include "ui/ozone/platform/dri/dri_util.h" | |
| 18 | |
| 19 namespace ui { | |
| 20 | |
| 21 namespace { | |
| 22 | |
| 23 uint32_t ToFixedPoint(double v) { | |
| 24 // This returns a number in a 16-bit.16-bit fixed point. | |
| 25 return v * 65536.0; | |
| 26 } | |
| 27 | |
| 28 bool DrmCreateDumbBuffer(int fd, | |
| 29 const SkImageInfo& info, | |
| 30 uint32_t* handle, | |
| 31 uint32_t* stride) { | |
| 32 struct drm_mode_create_dumb request; | |
| 33 memset(&request, 0, sizeof(request)); | |
| 34 request.width = info.width(); | |
| 35 request.height = info.height(); | |
| 36 request.bpp = info.bytesPerPixel() << 3; | |
| 37 request.flags = 0; | |
| 38 | |
| 39 if (drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &request) < 0) { | |
| 40 VLOG(2) << "Cannot create dumb buffer (" << errno << ") " | |
| 41 << strerror(errno); | |
| 42 return false; | |
| 43 } | |
| 44 | |
| 45 // The driver may choose to align the last row as well. We don't care about | |
| 46 // the last alignment bits since they aren't used for display purposes, so | |
| 47 // just check that the expected size is <= to what the driver allocated. | |
| 48 DCHECK_LE(info.getSafeSize(request.pitch), request.size); | |
| 49 | |
| 50 *handle = request.handle; | |
| 51 *stride = request.pitch; | |
| 52 return true; | |
| 53 } | |
| 54 | |
| 55 void DrmDestroyDumbBuffer(int fd, uint32_t handle) { | |
| 56 struct drm_mode_destroy_dumb destroy_request; | |
| 57 memset(&destroy_request, 0, sizeof(destroy_request)); | |
| 58 destroy_request.handle = handle; | |
| 59 drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_request); | |
| 60 } | |
| 61 | |
| 62 } // namespace | |
| 63 | |
| 64 DriWrapper::DriWrapper(const char* device_path) | |
| 65 : fd_(-1), device_path_(device_path) { | |
| 66 } | |
| 67 | |
| 68 DriWrapper::~DriWrapper() { | |
| 69 if (fd_ >= 0) | |
| 70 close(fd_); | |
| 71 } | |
| 72 | |
| 73 void DriWrapper::Initialize() { | |
| 74 fd_ = open(device_path_, O_RDWR | O_CLOEXEC); | |
| 75 if (fd_ < 0) | |
| 76 PLOG(FATAL) << "open: " << device_path_; | |
| 77 } | |
| 78 | |
| 79 ScopedDrmCrtcPtr DriWrapper::GetCrtc(uint32_t crtc_id) { | |
| 80 DCHECK(fd_ >= 0); | |
| 81 return ScopedDrmCrtcPtr(drmModeGetCrtc(fd_, crtc_id)); | |
| 82 } | |
| 83 | |
| 84 bool DriWrapper::SetCrtc(uint32_t crtc_id, | |
| 85 uint32_t framebuffer, | |
| 86 std::vector<uint32_t> connectors, | |
| 87 drmModeModeInfo* mode) { | |
| 88 DCHECK(fd_ >= 0); | |
| 89 DCHECK(!connectors.empty()); | |
| 90 DCHECK(mode); | |
| 91 | |
| 92 TRACE_EVENT2("dri", | |
| 93 "DriWrapper::SetCrtc", | |
| 94 "crtc", | |
| 95 crtc_id, | |
| 96 "size", | |
| 97 gfx::Size(mode->hdisplay, mode->vdisplay).ToString()); | |
| 98 return !drmModeSetCrtc(fd_, | |
| 99 crtc_id, | |
| 100 framebuffer, | |
| 101 0, | |
| 102 0, | |
| 103 vector_as_array(&connectors), | |
| 104 connectors.size(), mode); | |
| 105 } | |
| 106 | |
| 107 bool DriWrapper::SetCrtc(drmModeCrtc* crtc, std::vector<uint32_t> connectors) { | |
| 108 DCHECK(fd_ >= 0); | |
| 109 // If there's no buffer then the CRTC was disabled. | |
| 110 if (!crtc->buffer_id) | |
| 111 return DisableCrtc(crtc->crtc_id); | |
| 112 | |
| 113 DCHECK(!connectors.empty()); | |
| 114 | |
| 115 TRACE_EVENT1("dri", "DriWrapper::RestoreCrtc", | |
| 116 "crtc", crtc->crtc_id); | |
| 117 return !drmModeSetCrtc(fd_, | |
| 118 crtc->crtc_id, | |
| 119 crtc->buffer_id, | |
| 120 crtc->x, | |
| 121 crtc->y, | |
| 122 vector_as_array(&connectors), | |
| 123 connectors.size(), | |
| 124 &crtc->mode); | |
| 125 } | |
| 126 | |
| 127 bool DriWrapper::DisableCrtc(uint32_t crtc_id) { | |
| 128 DCHECK(fd_ >= 0); | |
| 129 TRACE_EVENT1("dri", "DriWrapper::DisableCrtc", | |
| 130 "crtc", crtc_id); | |
| 131 return !drmModeSetCrtc(fd_, crtc_id, 0, 0, 0, NULL, 0, NULL); | |
| 132 } | |
| 133 | |
| 134 ScopedDrmConnectorPtr DriWrapper::GetConnector(uint32_t connector_id) { | |
| 135 DCHECK(fd_ >= 0); | |
| 136 TRACE_EVENT1("dri", "DriWrapper::GetConnector", "connector", connector_id); | |
| 137 return ScopedDrmConnectorPtr(drmModeGetConnector(fd_, connector_id)); | |
| 138 } | |
| 139 | |
| 140 bool DriWrapper::AddFramebuffer(uint32_t width, | |
| 141 uint32_t height, | |
| 142 uint8_t depth, | |
| 143 uint8_t bpp, | |
| 144 uint32_t stride, | |
| 145 uint32_t handle, | |
| 146 uint32_t* framebuffer) { | |
| 147 DCHECK(fd_ >= 0); | |
| 148 TRACE_EVENT1("dri", "DriWrapper::AddFramebuffer", | |
| 149 "handle", handle); | |
| 150 return !drmModeAddFB(fd_, | |
| 151 width, | |
| 152 height, | |
| 153 depth, | |
| 154 bpp, | |
| 155 stride, | |
| 156 handle, | |
| 157 framebuffer); | |
| 158 } | |
| 159 | |
| 160 bool DriWrapper::RemoveFramebuffer(uint32_t framebuffer) { | |
| 161 DCHECK(fd_ >= 0); | |
| 162 TRACE_EVENT1("dri", "DriWrapper::RemoveFramebuffer", | |
| 163 "framebuffer", framebuffer); | |
| 164 return !drmModeRmFB(fd_, framebuffer); | |
| 165 } | |
| 166 | |
| 167 bool DriWrapper::PageFlip(uint32_t crtc_id, | |
| 168 uint32_t framebuffer, | |
| 169 void* data) { | |
| 170 DCHECK(fd_ >= 0); | |
| 171 TRACE_EVENT2("dri", "DriWrapper::PageFlip", | |
| 172 "crtc", crtc_id, | |
| 173 "framebuffer", framebuffer); | |
| 174 return !drmModePageFlip(fd_, | |
| 175 crtc_id, | |
| 176 framebuffer, | |
| 177 DRM_MODE_PAGE_FLIP_EVENT, | |
| 178 data); | |
| 179 } | |
| 180 | |
| 181 bool DriWrapper::PageFlipOverlay(uint32_t crtc_id, | |
| 182 uint32_t framebuffer, | |
| 183 const gfx::Rect& location, | |
| 184 const gfx::RectF& source, | |
| 185 int overlay_plane) { | |
| 186 DCHECK(fd_ >= 0); | |
| 187 TRACE_EVENT2("dri", "DriWrapper::PageFlipOverlay", | |
| 188 "crtc", crtc_id, | |
| 189 "framebuffer", framebuffer); | |
| 190 return !drmModeSetPlane(fd_, | |
| 191 overlay_plane, | |
| 192 crtc_id, | |
| 193 framebuffer, | |
| 194 0, | |
| 195 location.x(), | |
| 196 location.y(), | |
| 197 location.width(), | |
| 198 location.height(), | |
| 199 ToFixedPoint(source.x()), | |
| 200 ToFixedPoint(source.y()), | |
| 201 ToFixedPoint(source.width()), | |
| 202 ToFixedPoint(source.height())); | |
| 203 } | |
| 204 | |
| 205 ScopedDrmFramebufferPtr DriWrapper::GetFramebuffer(uint32_t framebuffer) { | |
| 206 DCHECK(fd_ >= 0); | |
| 207 TRACE_EVENT1("dri", "DriWrapper::GetFramebuffer", | |
| 208 "framebuffer", framebuffer); | |
| 209 return ScopedDrmFramebufferPtr(drmModeGetFB(fd_, framebuffer)); | |
| 210 } | |
| 211 | |
| 212 ScopedDrmPropertyPtr DriWrapper::GetProperty(drmModeConnector* connector, | |
| 213 const char* name) { | |
| 214 TRACE_EVENT2("dri", "DriWrapper::GetProperty", | |
| 215 "connector", connector->connector_id, | |
| 216 "name", name); | |
| 217 for (int i = 0; i < connector->count_props; ++i) { | |
| 218 ScopedDrmPropertyPtr property(drmModeGetProperty(fd_, connector->props[i])); | |
| 219 if (!property) | |
| 220 continue; | |
| 221 | |
| 222 if (strcmp(property->name, name) == 0) | |
| 223 return property.Pass(); | |
| 224 } | |
| 225 | |
| 226 return ScopedDrmPropertyPtr(); | |
| 227 } | |
| 228 | |
| 229 bool DriWrapper::SetProperty(uint32_t connector_id, | |
| 230 uint32_t property_id, | |
| 231 uint64_t value) { | |
| 232 DCHECK(fd_ >= 0); | |
| 233 return !drmModeConnectorSetProperty(fd_, connector_id, property_id, value); | |
| 234 } | |
| 235 | |
| 236 ScopedDrmPropertyBlobPtr DriWrapper::GetPropertyBlob( | |
| 237 drmModeConnector* connector, const char* name) { | |
| 238 DCHECK(fd_ >= 0); | |
| 239 TRACE_EVENT2("dri", "DriWrapper::GetPropertyBlob", | |
| 240 "connector", connector->connector_id, | |
| 241 "name", name); | |
| 242 for (int i = 0; i < connector->count_props; ++i) { | |
| 243 ScopedDrmPropertyPtr property(drmModeGetProperty(fd_, connector->props[i])); | |
| 244 if (!property) | |
| 245 continue; | |
| 246 | |
| 247 if (strcmp(property->name, name) == 0 && | |
| 248 property->flags & DRM_MODE_PROP_BLOB) | |
| 249 return ScopedDrmPropertyBlobPtr( | |
| 250 drmModeGetPropertyBlob(fd_, connector->prop_values[i])); | |
| 251 } | |
| 252 | |
| 253 return ScopedDrmPropertyBlobPtr(); | |
| 254 } | |
| 255 | |
| 256 bool DriWrapper::SetCursor(uint32_t crtc_id, | |
| 257 uint32_t handle, | |
| 258 const gfx::Size& size) { | |
| 259 DCHECK(fd_ >= 0); | |
| 260 TRACE_EVENT1("dri", "DriWrapper::SetCursor", "handle", handle); | |
| 261 return !drmModeSetCursor(fd_, crtc_id, handle, size.width(), size.height()); | |
| 262 } | |
| 263 | |
| 264 bool DriWrapper::MoveCursor(uint32_t crtc_id, const gfx::Point& point) { | |
| 265 DCHECK(fd_ >= 0); | |
| 266 return !drmModeMoveCursor(fd_, crtc_id, point.x(), point.y()); | |
| 267 } | |
| 268 | |
| 269 void DriWrapper::HandleEvent(drmEventContext& event) { | |
| 270 DCHECK(fd_ >= 0); | |
| 271 TRACE_EVENT0("dri", "DriWrapper::HandleEvent"); | |
| 272 drmHandleEvent(fd_, &event); | |
| 273 } | |
| 274 | |
| 275 bool DriWrapper::CreateDumbBuffer(const SkImageInfo& info, | |
| 276 uint32_t* handle, | |
| 277 uint32_t* stride, | |
| 278 void** pixels) { | |
| 279 DCHECK(fd_ >= 0); | |
| 280 | |
| 281 TRACE_EVENT0("dri", "DriWrapper::CreateDumbBuffer"); | |
| 282 if (!DrmCreateDumbBuffer(fd_, info, handle, stride)) | |
| 283 return false; | |
| 284 | |
| 285 if (!MapDumbBuffer(fd_, *handle, info.getSafeSize(*stride), pixels)) { | |
| 286 DrmDestroyDumbBuffer(fd_, *handle); | |
| 287 return false; | |
| 288 } | |
| 289 | |
| 290 return true; | |
| 291 } | |
| 292 | |
| 293 void DriWrapper::DestroyDumbBuffer(const SkImageInfo& info, | |
| 294 uint32_t handle, | |
| 295 uint32_t stride, | |
| 296 void* pixels) { | |
| 297 DCHECK(fd_ >= 0); | |
| 298 TRACE_EVENT1("dri", "DriWrapper::DestroyDumbBuffer", "handle", handle); | |
| 299 munmap(pixels, info.getSafeSize(stride)); | |
| 300 DrmDestroyDumbBuffer(fd_, handle); | |
| 301 } | |
| 302 | |
| 303 | |
| 304 } // namespace ui | |
| OLD | NEW |