• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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