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 <drm/drm_fourcc.h>
24 #include <xf86drm.h>
25 #include <xf86drmMode.h>
26
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) : drm_(drm) {
51 }
52
~DrmGenericImporter()53 DrmGenericImporter::~DrmGenericImporter() {
54 }
55
Init()56 int DrmGenericImporter::Init() {
57 int ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
58 (const hw_module_t **)&gralloc_);
59 if (ret) {
60 ALOGE("Failed to open gralloc module");
61 return ret;
62 }
63 return 0;
64 }
65
ConvertHalFormatToDrm(uint32_t hal_format)66 uint32_t DrmGenericImporter::ConvertHalFormatToDrm(uint32_t hal_format) {
67 switch (hal_format) {
68 case HAL_PIXEL_FORMAT_RGB_888:
69 return DRM_FORMAT_BGR888;
70 case HAL_PIXEL_FORMAT_BGRA_8888:
71 return DRM_FORMAT_ARGB8888;
72 case HAL_PIXEL_FORMAT_RGBX_8888:
73 return DRM_FORMAT_XBGR8888;
74 case HAL_PIXEL_FORMAT_RGBA_8888:
75 return DRM_FORMAT_ABGR8888;
76 case HAL_PIXEL_FORMAT_RGB_565:
77 return DRM_FORMAT_BGR565;
78 case HAL_PIXEL_FORMAT_YV12:
79 return DRM_FORMAT_YVU420;
80 default:
81 ALOGE("Cannot convert hal format to drm format %u", hal_format);
82 return -EINVAL;
83 }
84 }
85
DrmFormatToBitsPerPixel(uint32_t drm_format)86 uint32_t DrmGenericImporter::DrmFormatToBitsPerPixel(uint32_t drm_format) {
87 switch (drm_format) {
88 case DRM_FORMAT_ARGB8888:
89 case DRM_FORMAT_XBGR8888:
90 case DRM_FORMAT_ABGR8888:
91 return 32;
92 case DRM_FORMAT_BGR888:
93 return 24;
94 case DRM_FORMAT_BGR565:
95 return 16;
96 case DRM_FORMAT_YVU420:
97 return 12;
98 default:
99 ALOGE("Cannot convert hal format %u to bpp (returning 32)", drm_format);
100 return 32;
101 }
102 }
103
ImportBuffer(buffer_handle_t handle,hwc_drm_bo_t * bo)104 int DrmGenericImporter::ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) {
105 gralloc_handle_t *gr_handle = gralloc_handle(handle);
106 if (!gr_handle)
107 return -EINVAL;
108
109 uint32_t gem_handle;
110 int ret = drmPrimeFDToHandle(drm_->fd(), gr_handle->prime_fd, &gem_handle);
111 if (ret) {
112 ALOGE("failed to import prime fd %d ret=%d", gr_handle->prime_fd, ret);
113 return ret;
114 }
115
116 memset(bo, 0, sizeof(hwc_drm_bo_t));
117 bo->width = gr_handle->width;
118 bo->height = gr_handle->height;
119 bo->hal_format = gr_handle->format;
120 bo->format = ConvertHalFormatToDrm(gr_handle->format);
121 bo->usage = gr_handle->usage;
122 bo->pixel_stride = (gr_handle->stride * 8) /
123 DrmFormatToBitsPerPixel(bo->format);
124 bo->pitches[0] = gr_handle->stride;
125 bo->gem_handles[0] = gem_handle;
126 bo->offsets[0] = 0;
127
128 ret = drmModeAddFB2(drm_->fd(), bo->width, bo->height, bo->format,
129 bo->gem_handles, bo->pitches, bo->offsets, &bo->fb_id, 0);
130 if (ret) {
131 ALOGE("could not create drm fb %d", ret);
132 return ret;
133 }
134
135 return ret;
136 }
137
ReleaseBuffer(hwc_drm_bo_t * bo)138 int DrmGenericImporter::ReleaseBuffer(hwc_drm_bo_t *bo) {
139 if (bo->fb_id)
140 if (drmModeRmFB(drm_->fd(), bo->fb_id))
141 ALOGE("Failed to rm fb");
142
143 struct drm_gem_close gem_close;
144 memset(&gem_close, 0, sizeof(gem_close));
145
146 for (int i = 0; i < HWC_DRM_BO_MAX_PLANES; i++) {
147 if (!bo->gem_handles[i])
148 continue;
149
150 gem_close.handle = bo->gem_handles[i];
151 int ret = drmIoctl(drm_->fd(), DRM_IOCTL_GEM_CLOSE, &gem_close);
152 if (ret) {
153 ALOGE("Failed to close gem handle %d %d", i, ret);
154 } else {
155 for (int j = i + 1; j < HWC_DRM_BO_MAX_PLANES; j++)
156 if (bo->gem_handles[j] == bo->gem_handles[i])
157 bo->gem_handles[j] = 0;
158 bo->gem_handles[i] = 0;
159 }
160 }
161 return 0;
162 }
163
CanImportBuffer(buffer_handle_t handle)164 bool DrmGenericImporter::CanImportBuffer(buffer_handle_t handle) {
165 if (handle == NULL)
166 return false;
167 return true;
168 }
169
170 #ifdef USE_DRM_GENERIC_IMPORTER
CreateInstance(DrmDevice *)171 std::unique_ptr<Planner> Planner::CreateInstance(DrmDevice *) {
172 std::unique_ptr<Planner> planner(new Planner);
173 planner->AddStage<PlanStageGreedy>();
174 return planner;
175 }
176 #endif
177 }
178