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.
5 #include "ui/ozone/platform/dri/dri_wrapper.h"
11 #include <xf86drmMode.h>
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"
23 uint32_t ToFixedPoint(double v
) {
24 // This returns a number in a 16-bit.16-bit fixed point.
28 bool DrmCreateDumbBuffer(int fd
,
29 const SkImageInfo
& info
,
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;
39 if (drmIoctl(fd
, DRM_IOCTL_MODE_CREATE_DUMB
, &request
) < 0) {
40 VLOG(2) << "Cannot create dumb buffer (" << errno
<< ") "
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
);
50 *handle
= request
.handle
;
51 *stride
= request
.pitch
;
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
);
64 DriWrapper::DriWrapper(const char* device_path
)
65 : fd_(-1), device_path_(device_path
) {
68 DriWrapper::~DriWrapper() {
73 void DriWrapper::Initialize() {
74 fd_
= open(device_path_
, O_RDWR
| O_CLOEXEC
);
76 PLOG(FATAL
) << "open: " << device_path_
;
79 ScopedDrmCrtcPtr
DriWrapper::GetCrtc(uint32_t crtc_id
) {
81 return ScopedDrmCrtcPtr(drmModeGetCrtc(fd_
, crtc_id
));
84 bool DriWrapper::SetCrtc(uint32_t crtc_id
,
86 std::vector
<uint32_t> connectors
,
87 drmModeModeInfo
* mode
) {
89 DCHECK(!connectors
.empty());
92 TRACE_EVENT2("dri", "DriWrapper::SetCrtc", "crtc", crtc_id
, "size",
93 gfx::Size(mode
->hdisplay
, mode
->vdisplay
).ToString());
94 return !drmModeSetCrtc(fd_
,
99 vector_as_array(&connectors
),
100 connectors
.size(), mode
);
103 bool DriWrapper::SetCrtc(drmModeCrtc
* crtc
, std::vector
<uint32_t> connectors
) {
105 // If there's no buffer then the CRTC was disabled.
106 if (!crtc
->buffer_id
)
107 return DisableCrtc(crtc
->crtc_id
);
109 DCHECK(!connectors
.empty());
111 TRACE_EVENT1("dri", "DriWrapper::RestoreCrtc",
112 "crtc", crtc
->crtc_id
);
113 return !drmModeSetCrtc(fd_
,
118 vector_as_array(&connectors
),
123 bool DriWrapper::DisableCrtc(uint32_t crtc_id
) {
125 TRACE_EVENT1("dri", "DriWrapper::DisableCrtc",
127 return !drmModeSetCrtc(fd_
, crtc_id
, 0, 0, 0, NULL
, 0, NULL
);
130 ScopedDrmConnectorPtr
DriWrapper::GetConnector(uint32_t connector_id
) {
132 TRACE_EVENT1("dri", "DriWrapper::GetConnector", "connector", connector_id
);
133 return ScopedDrmConnectorPtr(drmModeGetConnector(fd_
, connector_id
));
136 bool DriWrapper::AddFramebuffer(uint32_t width
,
142 uint32_t* framebuffer
) {
144 TRACE_EVENT1("dri", "DriWrapper::AddFramebuffer",
146 return !drmModeAddFB(fd_
,
156 bool DriWrapper::RemoveFramebuffer(uint32_t framebuffer
) {
158 TRACE_EVENT1("dri", "DriWrapper::RemoveFramebuffer",
159 "framebuffer", framebuffer
);
160 return !drmModeRmFB(fd_
, framebuffer
);
163 bool DriWrapper::PageFlip(uint32_t crtc_id
,
164 uint32_t framebuffer
,
167 TRACE_EVENT2("dri", "DriWrapper::PageFlip",
169 "framebuffer", framebuffer
);
170 return !drmModePageFlip(fd_
,
173 DRM_MODE_PAGE_FLIP_EVENT
,
177 bool DriWrapper::PageFlipOverlay(uint32_t crtc_id
,
178 uint32_t framebuffer
,
179 const gfx::Rect
& location
,
180 const gfx::RectF
& source
,
183 TRACE_EVENT2("dri", "DriWrapper::PageFlipOverlay",
185 "framebuffer", framebuffer
);
186 return !drmModeSetPlane(fd_
,
195 ToFixedPoint(source
.x()),
196 ToFixedPoint(source
.y()),
197 ToFixedPoint(source
.width()),
198 ToFixedPoint(source
.height()));
201 ScopedDrmFramebufferPtr
DriWrapper::GetFramebuffer(uint32_t framebuffer
) {
203 TRACE_EVENT1("dri", "DriWrapper::GetFramebuffer",
204 "framebuffer", framebuffer
);
205 return ScopedDrmFramebufferPtr(drmModeGetFB(fd_
, framebuffer
));
208 ScopedDrmPropertyPtr
DriWrapper::GetProperty(drmModeConnector
* connector
,
210 TRACE_EVENT2("dri", "DriWrapper::GetProperty",
211 "connector", connector
->connector_id
,
213 for (int i
= 0; i
< connector
->count_props
; ++i
) {
214 ScopedDrmPropertyPtr
property(drmModeGetProperty(fd_
, connector
->props
[i
]));
218 if (strcmp(property
->name
, name
) == 0)
219 return property
.Pass();
222 return ScopedDrmPropertyPtr();
225 bool DriWrapper::SetProperty(uint32_t connector_id
,
226 uint32_t property_id
,
229 return !drmModeConnectorSetProperty(fd_
, connector_id
, property_id
, value
);
232 bool DriWrapper::GetCapability(uint64_t capability
, uint64_t* value
) {
234 return !drmGetCap(fd_
, capability
, value
);
237 ScopedDrmPropertyBlobPtr
DriWrapper::GetPropertyBlob(
238 drmModeConnector
* connector
, const char* name
) {
240 TRACE_EVENT2("dri", "DriWrapper::GetPropertyBlob",
241 "connector", connector
->connector_id
,
243 for (int i
= 0; i
< connector
->count_props
; ++i
) {
244 ScopedDrmPropertyPtr
property(drmModeGetProperty(fd_
, connector
->props
[i
]));
248 if (strcmp(property
->name
, name
) == 0 &&
249 property
->flags
& DRM_MODE_PROP_BLOB
)
250 return ScopedDrmPropertyBlobPtr(
251 drmModeGetPropertyBlob(fd_
, connector
->prop_values
[i
]));
254 return ScopedDrmPropertyBlobPtr();
257 bool DriWrapper::SetCursor(uint32_t crtc_id
,
259 const gfx::Size
& size
) {
261 TRACE_EVENT1("dri", "DriWrapper::SetCursor", "handle", handle
);
262 return !drmModeSetCursor(fd_
, crtc_id
, handle
, size
.width(), size
.height());
265 bool DriWrapper::MoveCursor(uint32_t crtc_id
, const gfx::Point
& point
) {
267 return !drmModeMoveCursor(fd_
, crtc_id
, point
.x(), point
.y());
270 void DriWrapper::HandleEvent(drmEventContext
& event
) {
272 TRACE_EVENT0("dri", "DriWrapper::HandleEvent");
273 drmHandleEvent(fd_
, &event
);
276 bool DriWrapper::CreateDumbBuffer(const SkImageInfo
& info
,
282 TRACE_EVENT0("dri", "DriWrapper::CreateDumbBuffer");
283 if (!DrmCreateDumbBuffer(fd_
, info
, handle
, stride
))
286 if (!MapDumbBuffer(fd_
, *handle
, info
.getSafeSize(*stride
), pixels
)) {
287 DrmDestroyDumbBuffer(fd_
, *handle
);
294 void DriWrapper::DestroyDumbBuffer(const SkImageInfo
& info
,
299 TRACE_EVENT1("dri", "DriWrapper::DestroyDumbBuffer", "handle", handle
);
300 munmap(pixels
, info
.getSafeSize(stride
));
301 DrmDestroyDumbBuffer(fd_
, handle
);
304 bool DriWrapper::SetMaster() {
306 return (drmSetMaster(fd_
) == 0);
309 bool DriWrapper::DropMaster() {
311 return (drmDropMaster(fd_
) == 0);