OSDN Git Service

PixelBuffer: Align width and height of pixelbuffer
[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 <unistd.h>
20 #include <drm.h>
21 #include <xf86drm.h>
22 #include <drm_fourcc.h>
23
24 #include <hwcdefs.h>
25 #include <hwctrace.h>
26 #include <platformdefines.h>
27
28 #include "commondrmutils.h"
29
30 namespace hwcomposer {
31
32 // static
33 NativeBufferHandler *NativeBufferHandler::CreateInstance(uint32_t fd) {
34   GbmBufferHandler *handler = new GbmBufferHandler(fd);
35   if (!handler)
36     return NULL;
37
38   if (!handler->Init()) {
39     ETRACE("Failed to initialize GbmBufferHandler.");
40     delete handler;
41     return NULL;
42   }
43   return handler;
44 }
45
46 GbmBufferHandler::GbmBufferHandler(uint32_t fd) : fd_(fd), device_(0) {
47 }
48
49 GbmBufferHandler::~GbmBufferHandler() {
50   if (device_)
51     gbm_device_destroy(device_);
52 }
53
54 bool GbmBufferHandler::Init() {
55   device_ = gbm_create_device(fd_);
56   if (!device_) {
57     ETRACE("failed to create gbm device \n");
58     return false;
59   }
60
61   uint64_t width = 0, height = 0;
62
63   if (drmGetCap(fd_, DRM_CAP_CURSOR_WIDTH, &width)) {
64     width = 64;
65     ETRACE("could not get cursor width.");
66   }
67
68   if (drmGetCap(fd_, DRM_CAP_CURSOR_HEIGHT, &height)) {
69     height = 64;
70     ETRACE("could not get cursor height.");
71   }
72
73   preferred_cursor_width_ = width;
74   preferred_cursor_height_ = height;
75
76   return true;
77 }
78
79 bool GbmBufferHandler::CreateBuffer(uint32_t w, uint32_t h, int format,
80                                     HWCNativeHandle *handle,
81                                     uint32_t layer_type) const {
82   uint32_t gbm_format = format;
83   if (gbm_format == 0)
84     gbm_format = GBM_FORMAT_XRGB8888;
85
86   uint32_t flags = 0;
87
88   if (layer_type == kLayerNormal) {
89     flags |= (GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
90 #ifdef USE_MINIGBM
91   } else if (layer_type == kLayerVideo) {
92     flags |= (GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING |
93               GBM_BO_USE_CAMERA_WRITE | GBM_BO_USE_CAMERA_READ);
94 #endif
95   }
96
97   if (layer_type == kLayerCursor) {
98     if (w < preferred_cursor_width_)
99       w = preferred_cursor_width_;
100
101     if (h < preferred_cursor_height_)
102       h = preferred_cursor_height_;
103   }
104
105   struct gbm_bo *bo = gbm_bo_create(device_, w, h, gbm_format, flags);
106
107   if (!bo) {
108     flags &= ~GBM_BO_USE_SCANOUT;
109     bo = gbm_bo_create(device_, w, h, gbm_format, flags);
110   }
111
112   if (!bo) {
113     flags &= ~GBM_BO_USE_RENDERING;
114     bo = gbm_bo_create(device_, w, h, gbm_format, flags);
115   }
116
117   if (!bo) {
118     ETRACE("GbmBufferHandler: failed to create gbm_bo");
119     return false;
120   }
121
122   struct gbm_handle *temp = new struct gbm_handle();
123   temp->import_data.width = gbm_bo_get_width(bo);
124   temp->import_data.height = gbm_bo_get_height(bo);
125   temp->import_data.format = gbm_bo_get_format(bo);
126 #if USE_MINIGBM
127   size_t total_planes = gbm_bo_get_num_planes(bo);
128   for (size_t i = 0; i < total_planes; i++) {
129     temp->import_data.fds[i] = gbm_bo_get_plane_fd(bo, i);
130     temp->import_data.offsets[i] = gbm_bo_get_plane_offset(bo, i);
131     temp->import_data.strides[i] = gbm_bo_get_plane_stride(bo, i);
132   }
133   temp->total_planes = total_planes;
134 #else
135   temp->import_data.fd = gbm_bo_get_fd(bo);
136   temp->import_data.stride = gbm_bo_get_stride(bo);
137   temp->total_planes = drm_bo_get_num_planes(temp->import_data.format);
138 #endif
139
140   temp->bo = bo;
141   temp->hwc_buffer_ = true;
142   temp->gbm_flags = flags;
143   *handle = temp;
144
145   return true;
146 }
147
148 bool GbmBufferHandler::ReleaseBuffer(HWCNativeHandle handle) const {
149   if (handle->bo || handle->imported_bo) {
150     if (handle->bo && handle->hwc_buffer_) {
151       gbm_bo_destroy(handle->bo);
152     }
153
154     if (handle->imported_bo) {
155       gbm_bo_destroy(handle->imported_bo);
156     }
157 #ifdef USE_MINIGBM
158     for (size_t i = 0; i < handle->total_planes; i++)
159       close(handle->import_data.fds[i]);
160 #else
161     close(handle->import_data.fd);
162 #endif
163   }
164
165   return true;
166 }
167
168 void GbmBufferHandler::DestroyHandle(HWCNativeHandle handle) const {
169   delete handle;
170   handle = NULL;
171 }
172
173 void GbmBufferHandler::CopyHandle(HWCNativeHandle source,
174                                   HWCNativeHandle *target) const {
175   struct gbm_handle *temp = new struct gbm_handle();
176   temp->import_data.width = source->import_data.width;
177   temp->import_data.height = source->import_data.height;
178   temp->import_data.format = source->import_data.format;
179 #if USE_MINIGBM
180   size_t total_planes = source->total_planes;
181   for (size_t i = 0; i < total_planes; i++) {
182     temp->import_data.fds[i] = dup(source->import_data.fds[i]);
183     temp->import_data.offsets[i] = source->import_data.offsets[i];
184     temp->import_data.strides[i] = source->import_data.strides[i];
185   }
186 #else
187   temp->import_data.fd = dup(source->import_data.fd);
188   temp->import_data.stride = source->import_data.stride;
189 #endif
190   temp->bo = source->bo;
191   temp->total_planes = source->total_planes;
192   temp->gbm_flags  = source->gbm_flags;
193   *target = temp;
194 }
195
196 bool GbmBufferHandler::ImportBuffer(HWCNativeHandle handle) const {
197   memset(&(handle->meta_data_), 0, sizeof(struct HwcBuffer));
198   uint32_t gem_handle = 0;
199   handle->meta_data_.format_ = handle->import_data.format;
200   handle->meta_data_.native_format_ = handle->import_data.format;
201   if (!handle->imported_bo) {
202 #if USE_MINIGBM
203     handle->imported_bo =
204         gbm_bo_import(device_, GBM_BO_IMPORT_FD_PLANAR, &handle->import_data,
205                       handle->gbm_flags);
206      if (!handle->imported_bo) {
207         ETRACE("can't import bo");
208       }
209 #else
210     handle->imported_bo = gbm_bo_import(
211         device_, GBM_BO_IMPORT_FD, &handle->import_data, handle->gbm_flags);
212     if (!handle->imported_bo) {
213         ETRACE("can't import bo");
214     }
215 #endif
216   }
217
218   gem_handle = gbm_bo_get_handle(handle->imported_bo).u32;
219
220   if (!gem_handle) {
221     ETRACE("Invalid GEM handle. \n");
222     return false;
223   }
224
225   handle->meta_data_.width_ = handle->import_data.width;
226   handle->meta_data_.height_ = handle->import_data.height;
227   // FIXME: Set right flag here.
228   handle->meta_data_.usage_ = hwcomposer::kLayerNormal;
229
230 #if USE_MINIGBM
231   handle->meta_data_.prime_fd_ = handle->import_data.fds[0];
232   size_t total_planes = gbm_bo_get_num_planes(handle->bo);
233   for (size_t i = 0; i < total_planes; i++) {
234     handle->meta_data_.gem_handles_[i] = gem_handle;
235     handle->meta_data_.offsets_[i] = gbm_bo_get_plane_offset(handle->bo, i);
236     handle->meta_data_.pitches_[i] = gbm_bo_get_plane_stride(handle->bo, i);
237   }
238 #else
239   handle->meta_data_.prime_fd_ = handle->import_data.fd;
240   handle->meta_data_.gem_handles_[0] = gem_handle;
241   handle->meta_data_.offsets_[0] = 0;
242   handle->meta_data_.pitches_[0] = gbm_bo_get_stride(handle->bo);
243 #endif
244
245   return true;
246 }
247
248 uint32_t GbmBufferHandler::GetTotalPlanes(HWCNativeHandle handle) const {
249   return handle->total_planes;
250 }
251
252 void *GbmBufferHandler::Map(HWCNativeHandle handle, uint32_t x, uint32_t y,
253                             uint32_t width, uint32_t height, uint32_t *stride,
254                             void **map_data, size_t plane) const {
255   if (!handle->bo)
256     return NULL;
257
258 #if USE_MINIGBM
259   return gbm_bo_map(handle->bo, x, y, width, height, GBM_BO_TRANSFER_WRITE,
260                     stride, map_data, plane);
261 #else
262   return gbm_bo_map(handle->bo, x, y, width, height, GBM_BO_TRANSFER_WRITE,
263                     stride, map_data);
264 #endif
265 }
266
267 int32_t GbmBufferHandler::UnMap(HWCNativeHandle handle, void *map_data) const {
268   if (!handle->bo)
269     return -1;
270
271   gbm_bo_unmap(handle->bo, map_data);
272   return 0;
273 }
274
275 }  // namespace hwcomposer