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 <unistd.h>
9#include <xf86drm.h>
10#include <xf86drmMode.h>
11
12#include "base/logging.h"
13
14namespace ui {
15
16DriWrapper::DriWrapper(const char* device_path) {
17  fd_ = open(device_path, O_RDWR | O_CLOEXEC);
18}
19
20DriWrapper::~DriWrapper() {
21  if (fd_ >= 0)
22    close(fd_);
23}
24
25drmModeCrtc* DriWrapper::GetCrtc(uint32_t crtc_id) {
26  CHECK(fd_ >= 0);
27  return drmModeGetCrtc(fd_, crtc_id);
28}
29
30void DriWrapper::FreeCrtc(drmModeCrtc* crtc) {
31  drmModeFreeCrtc(crtc);
32}
33
34bool DriWrapper::SetCrtc(uint32_t crtc_id,
35                         uint32_t framebuffer,
36                         uint32_t* connectors,
37                         drmModeModeInfo* mode) {
38  CHECK(fd_ >= 0);
39  return !drmModeSetCrtc(fd_, crtc_id, framebuffer, 0, 0, connectors, 1, mode);
40}
41
42bool DriWrapper::SetCrtc(drmModeCrtc* crtc, uint32_t* connectors) {
43  CHECK(fd_ >= 0);
44  return !drmModeSetCrtc(fd_,
45                         crtc->crtc_id,
46                         crtc->buffer_id,
47                         crtc->x,
48                         crtc->y,
49                         connectors,
50                         1,
51                         &crtc->mode);
52}
53
54bool DriWrapper::DisableCrtc(uint32_t crtc_id) {
55  CHECK(fd_ >= 0);
56  return !drmModeSetCrtc(fd_, crtc_id, 0, 0, 0, NULL, 0, NULL);
57}
58
59bool DriWrapper::AddFramebuffer(uint32_t width,
60                                uint32_t height,
61                                uint8_t depth,
62                                uint8_t bpp,
63                                uint32_t stride,
64                                uint32_t handle,
65                                uint32_t* framebuffer) {
66  CHECK(fd_ >= 0);
67  return !drmModeAddFB(fd_,
68                       width,
69                       height,
70                       depth,
71                       bpp,
72                       stride,
73                       handle,
74                       framebuffer);
75}
76
77bool DriWrapper::RemoveFramebuffer(uint32_t framebuffer) {
78  CHECK(fd_ >= 0);
79  return !drmModeRmFB(fd_, framebuffer);
80}
81
82bool DriWrapper::PageFlip(uint32_t crtc_id,
83                          uint32_t framebuffer,
84                          void* data) {
85  CHECK(fd_ >= 0);
86  return !drmModePageFlip(fd_,
87                          crtc_id,
88                          framebuffer,
89                          DRM_MODE_PAGE_FLIP_EVENT,
90                          data);
91}
92
93drmModePropertyRes* DriWrapper::GetProperty(drmModeConnector* connector,
94                                            const char* name) {
95  for (int i = 0; i < connector->count_props; ++i) {
96    drmModePropertyRes* property = drmModeGetProperty(fd_, connector->props[i]);
97    if (!property)
98      continue;
99
100    if (strcmp(property->name, name) == 0)
101      return property;
102
103    drmModeFreeProperty(property);
104  }
105
106  return NULL;
107}
108
109bool DriWrapper::SetProperty(uint32_t connector_id,
110                             uint32_t property_id,
111                             uint64_t value) {
112  CHECK(fd_ >= 0);
113  return !drmModeConnectorSetProperty(fd_, connector_id, property_id, value);
114}
115
116void DriWrapper::FreeProperty(drmModePropertyRes* prop) {
117  drmModeFreeProperty(prop);
118}
119
120drmModePropertyBlobRes* DriWrapper::GetPropertyBlob(drmModeConnector* connector,
121                                                    const char* name) {
122  CHECK(fd_ >= 0);
123  for (int i = 0; i < connector->count_props; ++i) {
124    drmModePropertyRes* property = drmModeGetProperty(fd_, connector->props[i]);
125    if (!property)
126      continue;
127
128    if (strcmp(property->name, name) == 0 &&
129        property->flags & DRM_MODE_PROP_BLOB) {
130      drmModePropertyBlobRes* blob =
131          drmModeGetPropertyBlob(fd_, connector->prop_values[i]);
132      drmModeFreeProperty(property);
133      return blob;
134    }
135
136    drmModeFreeProperty(property);
137  }
138
139  return NULL;
140}
141
142void DriWrapper::FreePropertyBlob(drmModePropertyBlobRes* blob) {
143  drmModeFreePropertyBlob(blob);
144}
145
146bool DriWrapper::SetCursor(uint32_t crtc_id,
147                           uint32_t handle,
148                           uint32_t width,
149                           uint32_t height) {
150  CHECK(fd_ >= 0);
151  return !drmModeSetCursor(fd_, crtc_id, handle, width, height);
152}
153
154bool DriWrapper::MoveCursor(uint32_t crtc_id, int x, int y) {
155  CHECK(fd_ >= 0);
156  return !drmModeMoveCursor(fd_, crtc_id, x, y);
157}
158
159void DriWrapper::HandleEvent(drmEventContext& event) {
160  CHECK(fd_ >= 0);
161  drmHandleEvent(fd_, &event);
162}
163
164}  // namespace ui
165