Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / ui / ozone / platform / dri / dri_wrapper.cc
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