OSDN Git Service

b0881280128def4d866dd11ecd7a903ee171116c
[android-x86/external-IA-Hardware-Composer.git] / os / linux / gbmbufferhandler.cpp
1 /*
2 // Copyright (c) 2016 Intel Corporation
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 #include "gbmbufferhandler.h"
18
19 #include <drm.h>
20 #include <drm_fourcc.h>
21 #include <unistd.h>
22 #include <xf86drm.h>
23
24 #include <hwcdefs.h>
25 #include <hwctrace.h>
26 #include <platformdefines.h>
27
28 #include "commondrmutils.h"
29 #include "hwcutils.h"
30
31 namespace hwcomposer {
32
33 // static
34 NativeBufferHandler *NativeBufferHandler::CreateInstance(uint32_t fd) {
35   GbmBufferHandler *handler = new GbmBufferHandler(fd);
36   if (!handler)
37     return NULL;
38
39   if (!handler->Init()) {
40     ETRACE("Failed to initialize GbmBufferHandler.");
41     delete handler;
42     return NULL;
43   }
44   return handler;
45 }
46
47 GbmBufferHandler::GbmBufferHandler(uint32_t fd)
48     : fd_(fd),
49       device_(0),
50       preferred_cursor_width_(0),
51       preferred_cursor_height_(0) {
52 }
53
54 GbmBufferHandler::~GbmBufferHandler() {
55   if (device_)
56     gbm_device_destroy(device_);
57 }
58
59 bool GbmBufferHandler::Init() {
60   device_ = gbm_create_device(fd_);
61   if (!device_) {
62     ETRACE("failed to create gbm device \n");
63     return false;
64   }
65
66   uint64_t width = 0, height = 0;
67
68   if (drmGetCap(fd_, DRM_CAP_CURSOR_WIDTH, &width)) {
69     width = 64;
70     ETRACE("could not get cursor width.");
71   }
72
73   if (drmGetCap(fd_, DRM_CAP_CURSOR_HEIGHT, &height)) {
74     height = 64;
75     ETRACE("could not get cursor height.");
76   }
77
78   preferred_cursor_width_ = width;
79   preferred_cursor_height_ = height;
80
81   return true;
82 }
83
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;
90   if (gbm_format == 0)
91     gbm_format = GBM_FORMAT_XRGB8888;
92
93   uint32_t flags = 0;
94
95   if (layer_type == kLayerNormal || layer_type == kLayerCursor) {
96     flags |= (GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
97   }
98
99   if (raw_pixel_buffer) {
100     flags |= GBM_BO_USE_LINEAR;
101   }
102
103   if (layer_type == kLayerCursor) {
104     if (w < preferred_cursor_width_)
105       w = preferred_cursor_width_;
106
107     if (h < preferred_cursor_height_)
108       h = preferred_cursor_height_;
109   }
110
111   struct gbm_bo *bo = NULL;
112
113   bool rbc_enabled = false;
114   uint64_t modifier = DRM_FORMAT_MOD_NONE;
115 #ifdef ENABLE_RBC
116   if (preferred_modifier != -1) {
117     modifier = preferred_modifier;
118   } else {
119     modifier = choose_drm_modifier(gbm_format);
120   }
121
122   if (modifier_used) {
123     *modifier_used = true;
124   }
125 #else
126   if (modifier_used) {
127     *modifier_used = false;
128   }
129 #endif
130
131   if (modifier != DRM_FORMAT_MOD_NONE) {
132     bo = gbm_bo_create_with_modifiers(device_, w, h, gbm_format, &modifier, 1);
133     rbc_enabled = true;
134   } else {
135     bo = gbm_bo_create(device_, w, h, gbm_format, flags);
136   }
137
138   if (!bo) {
139     flags &= ~GBM_BO_USE_SCANOUT;
140     bo = gbm_bo_create(device_, w, h, gbm_format, flags);
141     rbc_enabled = false;
142   }
143
144   if (!bo) {
145     flags &= ~GBM_BO_USE_RENDERING;
146     bo = gbm_bo_create(device_, w, h, gbm_format, flags);
147   }
148
149   if (!bo) {
150     ETRACE("GbmBufferHandler: failed to create gbm_bo");
151     return false;
152   }
153
154   struct gbm_handle *temp = new struct gbm_handle();
155   uint64_t mod = 0;
156
157   if (rbc_enabled) {
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);
164
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);
169
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;
176     }
177   } else {
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);
183   }
184
185   temp->bo = bo;
186   temp->hwc_buffer_ = true;
187   temp->gbm_flags = flags;
188   temp->layer_type_ = layer_type;
189   *handle = temp;
190
191   return true;
192 }
193
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);
198     }
199
200     if (handle->imported_bo) {
201       gbm_bo_destroy(handle->imported_bo);
202     }
203
204     if (!handle->meta_data_.fb_modifiers_[0]) {
205       close(handle->import_data.fd_data.fd);
206     } else {
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]);
209     }
210   }
211
212   return true;
213 }
214
215 void GbmBufferHandler::DestroyHandle(HWCNativeHandle handle) const {
216   delete handle;
217   handle = NULL;
218 }
219
220 void GbmBufferHandler::CopyHandle(HWCNativeHandle source,
221                                   HWCNativeHandle *target) const {
222   struct gbm_handle *temp = new struct gbm_handle();
223
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;
230   } else {
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;
239
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]);
243     }
244
245     size_t total_planes = source->meta_data_.num_planes_;
246
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];
256     }
257
258     temp->import_data.fd_modifier_data.modifier =
259         source->import_data.fd_modifier_data.modifier;
260   }
261
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_;
266   *target = temp;
267 }
268
269 bool GbmBufferHandler::ImportBuffer(HWCNativeHandle handle) const {
270   uint32_t gem_handle = 0;
271   HwcMeta *meta = &(handle->meta_data_);
272   bool use_modifier = true;
273   uint64_t mod = 0;
274
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;
280
281       handle->imported_bo =
282           gbm_bo_import(device_, GBM_BO_IMPORT_FD, &handle->import_data.fd_data,
283                         handle->gbm_flags);
284     } else {
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,
289                                           handle->gbm_flags);
290     }
291
292     if (!handle->imported_bo) {
293       ETRACE("can't import bo");
294     }
295   }
296
297   gem_handle = gbm_bo_get_handle(handle->imported_bo).u32;
298
299   if (!gem_handle) {
300     ETRACE("Invalid GEM handle. \n");
301     return false;
302   }
303
304   if (!use_modifier) {
305     handle->meta_data_.width_ = handle->import_data.fd_data.width;
306     handle->meta_data_.height_ = handle->import_data.fd_data.height;
307   } else {
308     handle->meta_data_.width_ = handle->import_data.fd_modifier_data.width;
309     handle->meta_data_.height_ = handle->import_data.fd_modifier_data.height;
310   }
311
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;
318   } else {
319     handle->meta_data_.usage_ = hwcomposer::kLayerNormal;
320   }
321
322   size_t total_planes = gbm_bo_get_plane_count(handle->imported_bo);
323   handle->meta_data_.num_planes_ = total_planes;
324
325   if (!use_modifier) {
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;
334     }
335   } else {
336     meta->prime_fds_[0] = handle->import_data.fd_modifier_data.fds[0];
337
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);
341
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;
352     }
353   }
354
355   return true;
356 }
357
358 uint32_t GbmBufferHandler::GetTotalPlanes(HWCNativeHandle handle) const {
359   return handle->meta_data_.num_planes_;
360 }
361
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 {
365   if (!handle->bo)
366     return NULL;
367
368   return gbm_bo_map(handle->bo, x, y, width, height, GBM_BO_TRANSFER_WRITE,
369                     stride, map_data);
370 }
371
372 int32_t GbmBufferHandler::UnMap(HWCNativeHandle handle, void *map_data) const {
373   if (!handle->bo)
374     return -1;
375
376   gbm_bo_unmap(handle->bo, map_data);
377   return 0;
378 }
379
380 }  // namespace hwcomposer