Merge "exynos_omx: multi_thread: Fix the bug of video recording I-frame interval...
[GitHub/LineageOS/android_hardware_samsung_slsi_exynos5.git] / gralloc / gralloc.cpp
1 /*
2 * Copyright (C) 2008 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 #ifdef HAVE_ANDROID_OS // just want PAGE_SIZE define
18 # include <asm/page.h>
19 #else
20 # include <sys/user.h>
21 #endif
22 #include <limits.h>
23 #include <unistd.h>
24 #include <fcntl.h>
25 #include <errno.h>
26 #include <pthread.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include <sys/mman.h>
31 #include <sys/stat.h>
32 #include <sys/types.h>
33 #include <sys/ioctl.h>
34
35 #include <ion/ion.h>
36 #include <linux/ion.h>
37 #include <cutils/log.h>
38 #include <cutils/atomic.h>
39
40 #include <hardware/hardware.h>
41 #include <hardware/gralloc.h>
42
43 #include "gralloc_priv.h"
44 #include "exynos_format.h"
45 #include "gr.h"
46
47 #define ION_HEAP_EXYNOS_CONTIG_MASK (1 << 4)
48 #define ION_EXYNOS_VIDEO_MASK (1 << 29)
49
50 /*****************************************************************************/
51
52 struct gralloc_context_t {
53 alloc_device_t device;
54 /* our private data here */
55 };
56
57 static int gralloc_alloc_buffer(alloc_device_t* dev,
58 size_t size, int usage, buffer_handle_t* pHandle);
59
60 /*****************************************************************************/
61
62 int fb_device_open(const hw_module_t* module, const char* name,
63 hw_device_t** device);
64
65 static int gralloc_device_open(const hw_module_t* module, const char* name,
66 hw_device_t** device);
67
68 extern int gralloc_lock(gralloc_module_t const* module,
69 buffer_handle_t handle, int usage,
70 int l, int t, int w, int h,
71 void** vaddr);
72
73 extern int gralloc_unlock(gralloc_module_t const* module,
74 buffer_handle_t handle);
75
76 extern int gralloc_register_buffer(gralloc_module_t const* module,
77 buffer_handle_t handle);
78
79 extern int gralloc_unregister_buffer(gralloc_module_t const* module,
80 buffer_handle_t handle);
81
82 /*****************************************************************************/
83
84 static struct hw_module_methods_t gralloc_module_methods = {
85 open: gralloc_device_open
86 };
87
88 struct private_module_t HAL_MODULE_INFO_SYM = {
89 base: {
90 common: {
91 tag: HARDWARE_MODULE_TAG,
92 version_major: 1,
93 version_minor: 0,
94 id: GRALLOC_HARDWARE_MODULE_ID,
95 name: "Graphics Memory Allocator Module",
96 author: "The Android Open Source Project",
97 methods: &gralloc_module_methods
98 },
99 registerBuffer: gralloc_register_buffer,
100 unregisterBuffer: gralloc_unregister_buffer,
101 lock: gralloc_lock,
102 unlock: gralloc_unlock,
103 },
104 framebuffer: 0,
105 flags: 0,
106 numBuffers: 0,
107 bufferMask: 0,
108 lock: PTHREAD_MUTEX_INITIALIZER,
109 currentBuffer: 0,
110 ionfd: -1,
111 };
112
113 /*****************************************************************************/
114
115 #define ALIGN(x, a) (((x) + (a - 1)) & ~(a - 1))
116
117 static unsigned int _select_heap(int usage)
118 {
119 unsigned int heap_mask;
120
121 if (usage & GRALLOC_USAGE_PROTECTED)
122 heap_mask = ION_HEAP_EXYNOS_CONTIG_MASK;
123 else
124 heap_mask = ION_HEAP_SYSTEM_MASK;
125
126 return heap_mask;
127 }
128
129 static int gralloc_alloc_rgb(int ionfd, int w, int h, int format, int usage,
130 unsigned int ion_flags, private_handle_t **hnd, int *stride)
131 {
132 size_t size, bpr;
133 int bpp = 0, vstride, fd, err;
134 unsigned int heap_mask = _select_heap(usage);
135
136 switch (format) {
137 case HAL_PIXEL_FORMAT_RGBA_8888:
138 case HAL_PIXEL_FORMAT_RGBX_8888:
139 case HAL_PIXEL_FORMAT_BGRA_8888:
140 bpp = 4;
141 break;
142 case HAL_PIXEL_FORMAT_RGB_888:
143 bpp = 3;
144 break;
145 case HAL_PIXEL_FORMAT_RGB_565:
146 case HAL_PIXEL_FORMAT_RGBA_5551:
147 case HAL_PIXEL_FORMAT_RGBA_4444:
148 case HAL_PIXEL_FORMAT_RAW_SENSOR:
149 bpp = 2;
150 break;
151 case HAL_PIXEL_FORMAT_BLOB:
152 bpp = 1;
153 break;
154 default:
155 return -EINVAL;
156 }
157 bpr = ALIGN(w*bpp, 16);
158 vstride = ALIGN(h, 16);
159 size = bpr * vstride;
160 *stride = bpr / bpp;
161 size = ALIGN(size, PAGE_SIZE);
162
163 err = ion_alloc_fd(ionfd, size, 0, heap_mask, ion_flags,
164 &fd);
165 *hnd = new private_handle_t(fd, size, usage, w, h, format, *stride,
166 vstride);
167
168 return err;
169 }
170
171 static int gralloc_alloc_framework_yuv(int ionfd, int w, int h, int format,
172 int usage, unsigned int ion_flags,
173 private_handle_t **hnd, int *stride)
174 {
175 size_t size;
176 int err, fd;
177
178 switch (format) {
179 case HAL_PIXEL_FORMAT_YV12:
180 *stride = ALIGN(w, 16);
181 break;
182 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
183 *stride = w;
184 break;
185 default:
186 ALOGE("invalid yuv format %d\n", format);
187 return -EINVAL;
188 }
189
190 size = *stride * h * 3 / 2;
191 err = ion_alloc_fd(ionfd, size, 0, 1 << ION_HEAP_TYPE_SYSTEM,
192 ion_flags, &fd);
193 if (err)
194 return err;
195
196 *hnd = new private_handle_t(fd, size, usage, w, h, format, *stride, h);
197 return err;
198 }
199
200 static int gralloc_alloc_yuv(int ionfd, int w, int h, int format,
201 int usage, unsigned int ion_flags,
202 private_handle_t **hnd, int *stride)
203 {
204 size_t luma_size, chroma_size;
205 int err, planes, fd, fd1, fd2 = 0;
206 size_t luma_vstride;
207 unsigned int heap_mask = _select_heap(usage);
208
209 *stride = ALIGN(w, 16);
210
211 switch (format) {
212 case HAL_PIXEL_FORMAT_EXYNOS_YV12:
213 {
214 luma_vstride = ALIGN(h, 16);
215 luma_size = luma_vstride * *stride;
216 chroma_size = (luma_vstride / 2) * ALIGN(*stride / 2, 16);
217 planes = 3;
218 break;
219 }
220 case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP:
221 case HAL_PIXEL_FORMAT_YCbCr_420_SP:
222 case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
223 {
224 size_t chroma_vstride = ALIGN(h / 2, 32);
225 luma_vstride = ALIGN(h, 32);
226 luma_size = luma_vstride * *stride;
227 chroma_size = chroma_vstride * *stride;
228 planes = 2;
229 break;
230 }
231 case HAL_PIXEL_FORMAT_YV12:
232 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
233 return gralloc_alloc_framework_yuv(ionfd, w, h, format, usage,
234 ion_flags, hnd, stride);
235 default:
236 ALOGE("invalid yuv format %d\n", format);
237 return -EINVAL;
238 }
239
240 err = ion_alloc_fd(ionfd, luma_size, 0, heap_mask, ion_flags, &fd);
241 if (err)
242 return err;
243 err = ion_alloc_fd(ionfd, chroma_size, 0, heap_mask, ion_flags, &fd1);
244 if (err)
245 goto err1;
246 if (planes == 3) {
247 err = ion_alloc_fd(ionfd, chroma_size, 0, heap_mask, ion_flags, &fd2);
248 if (err)
249 goto err2;
250
251 *hnd = new private_handle_t(fd, fd1, fd2, luma_size, usage, w, h,
252 format, *stride, luma_vstride);
253 } else {
254 *hnd = new private_handle_t(fd, fd1, luma_size, usage, w, h, format,
255 *stride, luma_vstride);
256 }
257 return err;
258
259 err2:
260 close(fd1);
261 err1:
262 close(fd);
263 return err;
264 }
265
266 static int gralloc_alloc(alloc_device_t* dev,
267 int w, int h, int format, int usage,
268 buffer_handle_t* pHandle, int* pStride)
269 {
270 int stride;
271 int err;
272 unsigned int ion_flags = 0;
273 private_handle_t *hnd;
274
275 if (!pHandle || !pStride)
276 return -EINVAL;
277
278 if( (usage & GRALLOC_USAGE_SW_READ_MASK) == GRALLOC_USAGE_SW_READ_OFTEN )
279 ion_flags = ION_FLAG_CACHED;
280 if (usage & GRALLOC_USAGE_PROTECTED)
281 ion_flags |= ION_EXYNOS_VIDEO_MASK;
282
283 private_module_t* m = reinterpret_cast<private_module_t*>
284 (dev->common.module);
285 gralloc_module_t* module = reinterpret_cast<gralloc_module_t*>
286 (dev->common.module);
287
288 err = gralloc_alloc_rgb(m->ionfd, w, h, format, usage, ion_flags, &hnd,
289 &stride);
290 if (err)
291 err = gralloc_alloc_yuv(m->ionfd, w, h, format, usage, ion_flags,
292 &hnd, &stride);
293 if (err)
294 return err;
295
296 err = grallocMap(module, hnd);
297
298 if (err != 0)
299 goto err;
300
301 *pHandle = hnd;
302 *pStride = stride;
303 return 0;
304 err:
305 close(hnd->fd);
306 if (hnd->fd1 >= 0)
307 close(hnd->fd1);
308 if (hnd->fd2 >= 0)
309 close(hnd->fd2);
310 return err;
311 }
312
313 static int gralloc_free(alloc_device_t* dev,
314 buffer_handle_t handle)
315 {
316 if (private_handle_t::validate(handle) < 0)
317 return -EINVAL;
318
319 private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(handle);
320 gralloc_module_t* module = reinterpret_cast<gralloc_module_t*>(
321 dev->common.module);
322
323 grallocUnmap(module, const_cast<private_handle_t*>(hnd));
324 close(hnd->fd);
325 if (hnd->fd1 >= 0)
326 close(hnd->fd1);
327 if (hnd->fd2 >= 0)
328 close(hnd->fd2);
329
330 delete hnd;
331 return 0;
332 }
333
334 /*****************************************************************************/
335
336 static int gralloc_close(struct hw_device_t *dev)
337 {
338 gralloc_context_t* ctx = reinterpret_cast<gralloc_context_t*>(dev);
339 if (ctx) {
340 /* TODO: keep a list of all buffer_handle_t created, and free them
341 * all here.
342 */
343 free(ctx);
344 }
345 return 0;
346 }
347
348 int gralloc_device_open(const hw_module_t* module, const char* name,
349 hw_device_t** device)
350 {
351 int status = -EINVAL;
352 if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) {
353 gralloc_context_t *dev;
354 dev = (gralloc_context_t*)malloc(sizeof(*dev));
355
356 /* initialize our state here */
357 memset(dev, 0, sizeof(*dev));
358
359 /* initialize the procs */
360 dev->device.common.tag = HARDWARE_DEVICE_TAG;
361 dev->device.common.version = 0;
362 dev->device.common.module = const_cast<hw_module_t*>(module);
363 dev->device.common.close = gralloc_close;
364
365 dev->device.alloc = gralloc_alloc;
366 dev->device.free = gralloc_free;
367
368 private_module_t *p = reinterpret_cast<private_module_t*>(dev->device.common.module);
369 p->ionfd = ion_open();
370
371 *device = &dev->device.common;
372 status = 0;
373 } else {
374 status = fb_device_open(module, name, device);
375 }
376 return status;
377 }