1 /*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define LOG_TAG "hwc-platform-drm-generic"
18
19 #include "platformdrmgeneric.h"
20 #include "drmdevice.h"
21 #include "platform.h"
22
23 #include <xf86drm.h>
24 #include <xf86drmMode.h>
25
26 #include <cutils/properties.h>
27 #include <gralloc_handle.h>
28 #include <hardware/gralloc.h>
29 #include <log/log.h>
30
31 namespace android {
32
33 #ifdef USE_DRM_GENERIC_IMPORTER
34 // static
CreateInstance(DrmDevice * drm)35 Importer *Importer::CreateInstance(DrmDevice *drm) {
36 DrmGenericImporter *importer = new DrmGenericImporter(drm);
37 if (!importer)
38 return NULL;
39
40 int ret = importer->Init();
41 if (ret) {
42 ALOGE("Failed to initialize the nv importer %d", ret);
43 delete importer;
44 return NULL;
45 }
46 return importer;
47 }
48 #endif
49
DrmGenericImporter(DrmDevice * drm)50 DrmGenericImporter::DrmGenericImporter(DrmDevice *drm)
51 : drm_(drm), exclude_non_hwfb_(false) {
52 }
53
~DrmGenericImporter()54 DrmGenericImporter::~DrmGenericImporter() {
55 }
56
Init()57 int DrmGenericImporter::Init() {
58 int ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
59 (const hw_module_t **)&gralloc_);
60 if (ret) {
61 ALOGE("Failed to open gralloc module");
62 return ret;
63 }
64
65 ALOGI("Using %s gralloc module: %s\n", gralloc_->common.name,
66 gralloc_->common.author);
67
68 char exclude_non_hwfb_prop[PROPERTY_VALUE_MAX];
69 property_get("hwc.drm.exclude_non_hwfb_imports", exclude_non_hwfb_prop, "0");
70 exclude_non_hwfb_ = static_cast<bool>(strncmp(exclude_non_hwfb_prop, "0", 1));
71
72 return 0;
73 }
74
ConvertHalFormatToDrm(uint32_t hal_format)75 uint32_t DrmGenericImporter::ConvertHalFormatToDrm(uint32_t hal_format) {
76 switch (hal_format) {
77 case HAL_PIXEL_FORMAT_RGB_888:
78 return DRM_FORMAT_BGR888;
79 case HAL_PIXEL_FORMAT_BGRA_8888:
80 return DRM_FORMAT_ARGB8888;
81 case HAL_PIXEL_FORMAT_RGBX_8888:
82 return DRM_FORMAT_XBGR8888;
83 case HAL_PIXEL_FORMAT_RGBA_8888:
84 return DRM_FORMAT_ABGR8888;
85 case HAL_PIXEL_FORMAT_RGB_565:
86 return DRM_FORMAT_BGR565;
87 case HAL_PIXEL_FORMAT_YV12:
88 return DRM_FORMAT_YVU420;
89 default:
90 ALOGE("Cannot convert hal format to drm format %u", hal_format);
91 return DRM_FORMAT_INVALID;
92 }
93 }
94
DrmFormatToBitsPerPixel(uint32_t drm_format)95 uint32_t DrmGenericImporter::DrmFormatToBitsPerPixel(uint32_t drm_format) {
96 switch (drm_format) {
97 case DRM_FORMAT_ARGB8888:
98 case DRM_FORMAT_XBGR8888:
99 case DRM_FORMAT_ABGR8888:
100 return 32;
101 case DRM_FORMAT_BGR888:
102 return 24;
103 case DRM_FORMAT_BGR565:
104 return 16;
105 case DRM_FORMAT_YVU420:
106 return 12;
107 default:
108 ALOGE("Cannot convert hal format %u to bpp (returning 32)", drm_format);
109 return 32;
110 }
111 }
112
ConvertBoInfo(buffer_handle_t handle,hwc_drm_bo_t * bo)113 int DrmGenericImporter::ConvertBoInfo(buffer_handle_t handle,
114 hwc_drm_bo_t *bo) {
115 gralloc_handle_t *gr_handle = gralloc_handle(handle);
116 if (!gr_handle)
117 return -EINVAL;
118
119 bo->width = gr_handle->width;
120 bo->height = gr_handle->height;
121 bo->hal_format = gr_handle->format;
122 bo->format = ConvertHalFormatToDrm(gr_handle->format);
123 if (bo->format == DRM_FORMAT_INVALID)
124 return -EINVAL;
125 bo->usage = gr_handle->usage;
126 bo->pixel_stride = (gr_handle->stride * 8) /
127 DrmFormatToBitsPerPixel(bo->format);
128 bo->prime_fds[0] = gr_handle->prime_fd;
129 bo->pitches[0] = gr_handle->stride;
130 bo->offsets[0] = 0;
131
132 return 0;
133 }
134
ImportBuffer(buffer_handle_t handle,hwc_drm_bo_t * bo)135 int DrmGenericImporter::ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) {
136 memset(bo, 0, sizeof(hwc_drm_bo_t));
137
138 int ret = ConvertBoInfo(handle, bo);
139 if (ret)
140 return ret;
141
142 ret = drmPrimeFDToHandle(drm_->fd(), bo->prime_fds[0], &bo->gem_handles[0]);
143 if (ret) {
144 ALOGE("failed to import prime fd %d ret=%d", bo->prime_fds[0], ret);
145 return ret;
146 }
147
148 for (int i = 1; i < HWC_DRM_BO_MAX_PLANES; i++) {
149 int fd = bo->prime_fds[i];
150 if (fd != 0) {
151 if (fd != bo->prime_fds[0]) {
152 ALOGE("Multiplanar FBs are not supported by this version of composer");
153 return -ENOTSUP;
154 }
155 bo->gem_handles[i] = bo->gem_handles[0];
156 }
157 }
158
159 if (!bo->with_modifiers)
160 ret = drmModeAddFB2(drm_->fd(), bo->width, bo->height, bo->format,
161 bo->gem_handles, bo->pitches, bo->offsets, &bo->fb_id,
162 0);
163 else
164 ret = drmModeAddFB2WithModifiers(drm_->fd(), bo->width, bo->height,
165 bo->format, bo->gem_handles, bo->pitches,
166 bo->offsets, bo->modifiers, &bo->fb_id,
167 bo->modifiers[0] ? DRM_MODE_FB_MODIFIERS
168 : 0);
169
170 if (ret) {
171 ALOGE("could not create drm fb %d", ret);
172 return ret;
173 }
174
175 ImportHandle(bo->gem_handles[0]);
176
177 return ret;
178 }
179
ReleaseBuffer(hwc_drm_bo_t * bo)180 int DrmGenericImporter::ReleaseBuffer(hwc_drm_bo_t *bo) {
181 if (bo->fb_id)
182 if (drmModeRmFB(drm_->fd(), bo->fb_id))
183 ALOGE("Failed to rm fb");
184
185 for (int i = 0; i < HWC_DRM_BO_MAX_PLANES; i++) {
186 if (!bo->gem_handles[i])
187 continue;
188
189 if (ReleaseHandle(bo->gem_handles[i])) {
190 ALOGE("Failed to release gem handle %d", bo->gem_handles[i]);
191 } else {
192 for (int j = i + 1; j < HWC_DRM_BO_MAX_PLANES; j++)
193 if (bo->gem_handles[j] == bo->gem_handles[i])
194 bo->gem_handles[j] = 0;
195 bo->gem_handles[i] = 0;
196 }
197 }
198 return 0;
199 }
200
CanImportBuffer(buffer_handle_t handle)201 bool DrmGenericImporter::CanImportBuffer(buffer_handle_t handle) {
202 hwc_drm_bo_t bo;
203
204 int ret = ConvertBoInfo(handle, &bo);
205 if (ret)
206 return false;
207
208 if (bo.prime_fds[0] == 0)
209 return false;
210
211 if (exclude_non_hwfb_ && !(bo.usage & GRALLOC_USAGE_HW_FB))
212 return false;
213
214 return true;
215 }
216
217 #ifdef USE_DRM_GENERIC_IMPORTER
CreateInstance(DrmDevice *)218 std::unique_ptr<Planner> Planner::CreateInstance(DrmDevice *) {
219 std::unique_ptr<Planner> planner(new Planner);
220 planner->AddStage<PlanStageGreedy>();
221 return planner;
222 }
223 #endif
224
ImportHandle(uint32_t gem_handle)225 int DrmGenericImporter::ImportHandle(uint32_t gem_handle) {
226 gem_refcount_[gem_handle]++;
227
228 return 0;
229 }
230
ReleaseHandle(uint32_t gem_handle)231 int DrmGenericImporter::ReleaseHandle(uint32_t gem_handle) {
232 if (--gem_refcount_[gem_handle])
233 return 0;
234
235 gem_refcount_.erase(gem_handle);
236
237 return CloseHandle(gem_handle);
238 }
239
CloseHandle(uint32_t gem_handle)240 int DrmGenericImporter::CloseHandle(uint32_t gem_handle) {
241 struct drm_gem_close gem_close;
242
243 memset(&gem_close, 0, sizeof(gem_close));
244
245 gem_close.handle = gem_handle;
246 int ret = drmIoctl(drm_->fd(), DRM_IOCTL_GEM_CLOSE, &gem_close);
247 if (ret)
248 ALOGE("Failed to close gem handle %d %d", gem_handle, ret);
249
250 return ret;
251 }
252 }
253