2 // Copyright (c) 2016 Intel Corporation
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
8 // http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "gbmbufferhandler.h"
20 #include <drm_fourcc.h>
26 #include <platformdefines.h>
28 #include "commondrmutils.h"
31 namespace hwcomposer {
34 NativeBufferHandler *NativeBufferHandler::CreateInstance(uint32_t fd) {
35 GbmBufferHandler *handler = new GbmBufferHandler(fd);
39 if (!handler->Init()) {
40 ETRACE("Failed to initialize GbmBufferHandler.");
47 GbmBufferHandler::GbmBufferHandler(uint32_t fd)
50 preferred_cursor_width_(0),
51 preferred_cursor_height_(0) {
54 GbmBufferHandler::~GbmBufferHandler() {
56 gbm_device_destroy(device_);
59 bool GbmBufferHandler::Init() {
60 device_ = gbm_create_device(fd_);
62 ETRACE("failed to create gbm device \n");
66 uint64_t width = 0, height = 0;
68 if (drmGetCap(fd_, DRM_CAP_CURSOR_WIDTH, &width)) {
70 ETRACE("could not get cursor width.");
73 if (drmGetCap(fd_, DRM_CAP_CURSOR_HEIGHT, &height)) {
75 ETRACE("could not get cursor height.");
78 preferred_cursor_width_ = width;
79 preferred_cursor_height_ = height;
84 bool GbmBufferHandler::CreateBuffer(uint32_t w, uint32_t h, int format,
85 HWCNativeHandle *handle,
86 uint32_t layer_type, bool *modifier_used,
87 int64_t preferred_modifier,
88 bool raw_pixel_buffer) const {
89 uint32_t gbm_format = format;
91 gbm_format = GBM_FORMAT_XRGB8888;
95 if (layer_type == kLayerNormal || layer_type == kLayerCursor) {
96 flags |= (GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
99 if (raw_pixel_buffer) {
100 flags |= GBM_BO_USE_LINEAR;
103 if (layer_type == kLayerCursor) {
104 if (w < preferred_cursor_width_)
105 w = preferred_cursor_width_;
107 if (h < preferred_cursor_height_)
108 h = preferred_cursor_height_;
111 struct gbm_bo *bo = NULL;
113 bool rbc_enabled = false;
114 uint64_t modifier = DRM_FORMAT_MOD_NONE;
116 if (preferred_modifier != -1) {
117 modifier = preferred_modifier;
119 modifier = choose_drm_modifier(gbm_format);
123 *modifier_used = true;
127 *modifier_used = false;
131 if (modifier != DRM_FORMAT_MOD_NONE) {
132 bo = gbm_bo_create_with_modifiers(device_, w, h, gbm_format, &modifier, 1);
135 bo = gbm_bo_create(device_, w, h, gbm_format, flags);
139 flags &= ~GBM_BO_USE_SCANOUT;
140 bo = gbm_bo_create(device_, w, h, gbm_format, flags);
145 flags &= ~GBM_BO_USE_RENDERING;
146 bo = gbm_bo_create(device_, w, h, gbm_format, flags);
150 ETRACE("GbmBufferHandler: failed to create gbm_bo");
154 struct gbm_handle *temp = new struct gbm_handle();
158 temp->meta_data_.num_planes_ = gbm_bo_get_plane_count(bo);
159 temp->import_data.fd_modifier_data.width = gbm_bo_get_width(bo);
160 temp->import_data.fd_modifier_data.height = gbm_bo_get_height(bo);
161 temp->import_data.fd_modifier_data.format = gbm_bo_get_format(bo);
162 temp->import_data.fd_modifier_data.num_fds = 1;
163 temp->import_data.fd_modifier_data.fds[0] = gbm_bo_get_fd(bo);
165 temp->import_data.fd_modifier_data.modifier = gbm_bo_get_modifier(bo);
166 mod = temp->import_data.fd_modifier_data.modifier;
167 uint32_t modifier_low = static_cast<uint32_t>(mod >> 32);
168 uint32_t modifier_high = static_cast<uint32_t>(mod);
170 for (size_t i = 0; i < temp->meta_data_.num_planes_; i++) {
171 temp->import_data.fd_modifier_data.offsets[i] = gbm_bo_get_offset(bo, i);
172 temp->import_data.fd_modifier_data.strides[i] =
173 gbm_bo_get_stride_for_plane(bo, i);
174 temp->meta_data_.fb_modifiers_[2 * i] = modifier_low;
175 temp->meta_data_.fb_modifiers_[2 * i + 1] = modifier_high;
178 temp->import_data.fd_data.width = gbm_bo_get_width(bo);
179 temp->import_data.fd_data.height = gbm_bo_get_height(bo);
180 temp->import_data.fd_data.format = gbm_bo_get_format(bo);
181 temp->import_data.fd_data.fd = gbm_bo_get_fd(bo);
182 temp->import_data.fd_data.stride = gbm_bo_get_stride(bo);
186 temp->hwc_buffer_ = true;
187 temp->gbm_flags = flags;
188 temp->layer_type_ = layer_type;
194 bool GbmBufferHandler::ReleaseBuffer(HWCNativeHandle handle) const {
195 if (handle->bo || handle->imported_bo) {
196 if (handle->bo && handle->hwc_buffer_) {
197 gbm_bo_destroy(handle->bo);
200 if (handle->imported_bo) {
201 gbm_bo_destroy(handle->imported_bo);
204 if (!handle->meta_data_.fb_modifiers_[0]) {
205 close(handle->import_data.fd_data.fd);
207 for (size_t i = 0; i < handle->import_data.fd_modifier_data.num_fds; i++)
208 close(handle->import_data.fd_modifier_data.fds[i]);
215 void GbmBufferHandler::DestroyHandle(HWCNativeHandle handle) const {
220 void GbmBufferHandler::CopyHandle(HWCNativeHandle source,
221 HWCNativeHandle *target) const {
222 struct gbm_handle *temp = new struct gbm_handle();
224 if (!source->meta_data_.fb_modifiers_[0]) {
225 temp->import_data.fd_data.width = source->import_data.fd_data.width;
226 temp->import_data.fd_data.height = source->import_data.fd_data.height;
227 temp->import_data.fd_data.format = source->import_data.fd_data.format;
228 temp->import_data.fd_data.fd = dup(source->import_data.fd_data.fd);
229 temp->import_data.fd_data.stride = source->import_data.fd_data.stride;
231 temp->import_data.fd_modifier_data.width =
232 source->import_data.fd_modifier_data.width;
233 temp->import_data.fd_modifier_data.height =
234 source->import_data.fd_modifier_data.height;
235 temp->import_data.fd_modifier_data.format =
236 source->import_data.fd_modifier_data.format;
237 temp->import_data.fd_modifier_data.num_fds =
238 source->import_data.fd_modifier_data.num_fds;
240 for (size_t i = 0; i < temp->import_data.fd_modifier_data.num_fds; i++) {
241 temp->import_data.fd_modifier_data.fds[i] =
242 dup(source->import_data.fd_modifier_data.fds[i]);
245 size_t total_planes = source->meta_data_.num_planes_;
247 for (size_t i = 0; i < total_planes; i++) {
248 temp->import_data.fd_modifier_data.offsets[i] =
249 source->import_data.fd_modifier_data.offsets[i];
250 temp->import_data.fd_modifier_data.strides[i] =
251 source->import_data.fd_modifier_data.strides[i];
252 temp->meta_data_.fb_modifiers_[2 * i] =
253 source->meta_data_.fb_modifiers_[2 * i];
254 temp->meta_data_.fb_modifiers_[2 * i + 1] =
255 source->meta_data_.fb_modifiers_[2 * i + 1];
258 temp->import_data.fd_modifier_data.modifier =
259 source->import_data.fd_modifier_data.modifier;
262 temp->bo = source->bo;
263 temp->meta_data_.num_planes_ = source->meta_data_.num_planes_;
264 temp->gbm_flags = source->gbm_flags;
265 temp->layer_type_ = source->layer_type_;
269 bool GbmBufferHandler::ImportBuffer(HWCNativeHandle handle) const {
270 uint32_t gem_handle = 0;
271 HwcMeta *meta = &(handle->meta_data_);
272 bool use_modifier = true;
275 if (!handle->imported_bo) {
276 if (!handle->meta_data_.fb_modifiers_[0]) {
277 use_modifier = false;
278 meta->format_ = handle->import_data.fd_data.format;
279 meta->native_format_ = handle->import_data.fd_data.format;
281 handle->imported_bo =
282 gbm_bo_import(device_, GBM_BO_IMPORT_FD, &handle->import_data.fd_data,
285 meta->format_ = handle->import_data.fd_modifier_data.format;
286 meta->native_format_ = handle->import_data.fd_modifier_data.format;
287 handle->imported_bo = gbm_bo_import(device_, GBM_BO_IMPORT_FD_MODIFIER,
288 &handle->import_data.fd_modifier_data,
292 if (!handle->imported_bo) {
293 ETRACE("can't import bo");
297 gem_handle = gbm_bo_get_handle(handle->imported_bo).u32;
300 ETRACE("Invalid GEM handle. \n");
305 handle->meta_data_.width_ = handle->import_data.fd_data.width;
306 handle->meta_data_.height_ = handle->import_data.fd_data.height;
308 handle->meta_data_.width_ = handle->import_data.fd_modifier_data.width;
309 handle->meta_data_.height_ = handle->import_data.fd_modifier_data.height;
312 if (handle->layer_type_ == hwcomposer::kLayerCursor) {
313 handle->meta_data_.usage_ = hwcomposer::kLayerCursor;
314 // We support DRM_FORMAT_ARGB8888 for cursor.
315 handle->meta_data_.format_ = DRM_FORMAT_ARGB8888;
316 } else if (hwcomposer::IsSupportedMediaFormat(handle->meta_data_.format_)) {
317 handle->meta_data_.usage_ = hwcomposer::kLayerVideo;
319 handle->meta_data_.usage_ = hwcomposer::kLayerNormal;
322 size_t total_planes = gbm_bo_get_plane_count(handle->imported_bo);
323 handle->meta_data_.num_planes_ = total_planes;
326 meta->prime_fds_[0] = handle->import_data.fd_data.fd;
327 for (size_t i = 0; i < total_planes; i++) {
328 handle->meta_data_.gem_handles_[i] = gem_handle;
329 handle->meta_data_.offsets_[i] =
330 gbm_bo_get_offset(handle->imported_bo, i);
331 handle->meta_data_.pitches_[i] =
332 gbm_bo_get_stride_for_plane(handle->imported_bo, i);
333 handle->meta_data_.prime_fds_[i] = handle->import_data.fd_data.fd;
336 meta->prime_fds_[0] = handle->import_data.fd_modifier_data.fds[0];
338 mod = gbm_bo_get_modifier(handle->imported_bo);
339 uint32_t modifier_low = static_cast<uint32_t>(mod >> 32);
340 uint32_t modifier_high = static_cast<uint32_t>(mod);
342 for (size_t i = 0; i < total_planes; i++) {
343 handle->meta_data_.gem_handles_[i] = gem_handle;
344 handle->meta_data_.offsets_[i] =
345 gbm_bo_get_offset(handle->imported_bo, i);
346 handle->meta_data_.pitches_[i] =
347 gbm_bo_get_stride_for_plane(handle->imported_bo, i);
348 handle->meta_data_.prime_fds_[i] =
349 handle->import_data.fd_modifier_data.fds[0];
350 meta->fb_modifiers_[2 * i] = modifier_low;
351 meta->fb_modifiers_[2 * i + 1] = modifier_high;
358 uint32_t GbmBufferHandler::GetTotalPlanes(HWCNativeHandle handle) const {
359 return handle->meta_data_.num_planes_;
362 void *GbmBufferHandler::Map(HWCNativeHandle handle, uint32_t x, uint32_t y,
363 uint32_t width, uint32_t height, uint32_t *stride,
364 void **map_data, size_t plane) const {
368 return gbm_bo_map(handle->bo, x, y, width, height, GBM_BO_TRANSFER_WRITE,
372 int32_t GbmBufferHandler::UnMap(HWCNativeHandle handle, void *map_data) const {
376 gbm_bo_unmap(handle->bo, map_data);
380 } // namespace hwcomposer