gralloc: Add vstride to gralloc handles, pad rgb surfaces
[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 /*****************************************************************************/
48
49 struct gralloc_context_t {
50 alloc_device_t device;
51 /* our private data here */
52 };
53
54 static int gralloc_alloc_buffer(alloc_device_t* dev,
55 size_t size, int usage, buffer_handle_t* pHandle);
56
57 /*****************************************************************************/
58
59 int fb_device_open(const hw_module_t* module, const char* name,
60 hw_device_t** device);
61
62 static int gralloc_device_open(const hw_module_t* module, const char* name,
63 hw_device_t** device);
64
65 extern int gralloc_lock(gralloc_module_t const* module,
66 buffer_handle_t handle, int usage,
67 int l, int t, int w, int h,
68 void** vaddr);
69
70 extern int gralloc_unlock(gralloc_module_t const* module,
71 buffer_handle_t handle);
72
73 extern int gralloc_register_buffer(gralloc_module_t const* module,
74 buffer_handle_t handle);
75
76 extern int gralloc_unregister_buffer(gralloc_module_t const* module,
77 buffer_handle_t handle);
78
79 /*****************************************************************************/
80
81 static struct hw_module_methods_t gralloc_module_methods = {
82 open: gralloc_device_open
83 };
84
85 struct private_module_t HAL_MODULE_INFO_SYM = {
86 base: {
87 common: {
88 tag: HARDWARE_MODULE_TAG,
89 version_major: 1,
90 version_minor: 0,
91 id: GRALLOC_HARDWARE_MODULE_ID,
92 name: "Graphics Memory Allocator Module",
93 author: "The Android Open Source Project",
94 methods: &gralloc_module_methods
95 },
96 registerBuffer: gralloc_register_buffer,
97 unregisterBuffer: gralloc_unregister_buffer,
98 lock: gralloc_lock,
99 unlock: gralloc_unlock,
100 },
101 framebuffer: 0,
102 flags: 0,
103 numBuffers: 0,
104 bufferMask: 0,
105 lock: PTHREAD_MUTEX_INITIALIZER,
106 currentBuffer: 0,
107 ionfd: -1,
108 };
109
110 /*****************************************************************************/
111
112 #define ALIGN(x, a) (((x) + (a - 1)) & ~(a - 1))
113
114 static int gralloc_alloc_rgb(int ionfd, int w, int h, int format, int flags,
115 private_handle_t **hnd, int *stride)
116 {
117 size_t size, bpr;
118 int bpp = 0, vstride, fd, err;
119 switch (format) {
120 case HAL_PIXEL_FORMAT_RGBA_8888:
121 case HAL_PIXEL_FORMAT_RGBX_8888:
122 case HAL_PIXEL_FORMAT_BGRA_8888:
123 bpp = 4;
124 break;
125 case HAL_PIXEL_FORMAT_RGB_888:
126 bpp = 3;
127 break;
128 case HAL_PIXEL_FORMAT_RGB_565:
129 case HAL_PIXEL_FORMAT_RGBA_5551:
130 case HAL_PIXEL_FORMAT_RGBA_4444:
131 case HAL_PIXEL_FORMAT_RAW_SENSOR:
132 bpp = 2;
133 break;
134 case HAL_PIXEL_FORMAT_BLOB:
135 bpp = 1;
136 break;
137 default:
138 return -EINVAL;
139 }
140 bpr = ALIGN(w*bpp, 16);
141 vstride = ALIGN(h, 16);
142 size = bpr * vstride;
143 *stride = bpr / bpp;
144 size = ALIGN(size, PAGE_SIZE);
145
146 err = ion_alloc_fd(ionfd, size, 0, 1 << ION_HEAP_TYPE_SYSTEM, flags, &fd);
147 *hnd = new private_handle_t(fd, size, 0, w, h, format, *stride, vstride);
148
149 return err;
150 }
151
152 static int gralloc_alloc_yuv(int ionfd, int w, int h, int format, int flags,
153 private_handle_t **hnd, int *stride)
154 {
155 size_t luma_size, chroma_size;
156 int err, planes, fd, fd1, fd2 = 0;
157 size_t luma_vstride;
158 *stride = ALIGN(w, 16);
159
160 switch (format) {
161 ALOGE("invalid yuv format %d\n", format);
162 case HAL_PIXEL_FORMAT_YV12:
163 {
164 luma_vstride = ALIGN(h, 16);
165 luma_size = luma_vstride * *stride;
166 chroma_size = (luma_vstride / 2) * ALIGN(*stride / 2, 16);
167 planes = 3;
168 break;
169 }
170 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
171 case HAL_PIXEL_FORMAT_YCbCr_420_SP:
172 case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
173 {
174 size_t chroma_vstride = ALIGN(h / 2, 32);
175 luma_vstride = ALIGN(h, 32);
176 luma_size = luma_vstride * *stride;
177 chroma_size = chroma_vstride * *stride;
178 planes = 2;
179 break;
180 }
181 default:
182 ALOGE("invalid yuv format %d\n", format);
183 return -EINVAL;
184 }
185
186 err = ion_alloc_fd(ionfd, luma_size, 0, 1 << ION_HEAP_TYPE_SYSTEM, flags,
187 &fd);
188 if (err)
189 return err;
190 err = ion_alloc_fd(ionfd, chroma_size, 0, 1 << ION_HEAP_TYPE_SYSTEM, flags,
191 &fd1);
192 if (err)
193 goto err1;
194 if (planes == 3) {
195 err = ion_alloc_fd(ionfd, chroma_size, 0, 1 << ION_HEAP_TYPE_SYSTEM,
196 flags, &fd2);
197 if (err)
198 goto err2;
199 }
200
201 *hnd = new private_handle_t(fd, fd1, fd2, luma_size, 0, w, h, format,
202 *stride, luma_vstride);
203 return err;
204
205 err2:
206 close(fd1);
207 err1:
208 close(fd);
209 return err;
210 }
211
212 static int gralloc_alloc(alloc_device_t* dev,
213 int w, int h, int format, int usage,
214 buffer_handle_t* pHandle, int* pStride)
215 {
216 int stride;
217 int err;
218 int flags = 0;
219 private_handle_t *hnd;
220
221 if (!pHandle || !pStride)
222 return -EINVAL;
223
224 if( (usage & GRALLOC_USAGE_SW_READ_MASK) == GRALLOC_USAGE_SW_READ_OFTEN )
225 flags = ION_FLAG_CACHED;
226
227 private_module_t* m = reinterpret_cast<private_module_t*>
228 (dev->common.module);
229 gralloc_module_t* module = reinterpret_cast<gralloc_module_t*>
230 (dev->common.module);
231
232 err = gralloc_alloc_rgb(m->ionfd, w, h, format, flags, &hnd, &stride);
233 if (err)
234 err = gralloc_alloc_yuv(m->ionfd, w, h, format, flags, &hnd, &stride);
235 if (err)
236 return err;
237
238 err = grallocMap(module, hnd);
239
240 if (err != 0)
241 goto err;
242
243 *pHandle = hnd;
244 *pStride = stride;
245 return 0;
246 err:
247 close(hnd->fd);
248 if (hnd->fd1 > 0)
249 close(hnd->fd1);
250 if (hnd->fd2 > 0)
251 close(hnd->fd2);
252 return err;
253 }
254
255 static int gralloc_free(alloc_device_t* dev,
256 buffer_handle_t handle)
257 {
258 if (private_handle_t::validate(handle) < 0)
259 return -EINVAL;
260
261 private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(handle);
262 gralloc_module_t* module = reinterpret_cast<gralloc_module_t*>(
263 dev->common.module);
264
265 grallocUnmap(module, const_cast<private_handle_t*>(hnd));
266 close(hnd->fd);
267 if (hnd->fd1 > 0)
268 close(hnd->fd1);
269 if (hnd->fd2 > 0)
270 close(hnd->fd2);
271
272 delete hnd;
273 return 0;
274 }
275
276 /*****************************************************************************/
277
278 static int gralloc_close(struct hw_device_t *dev)
279 {
280 gralloc_context_t* ctx = reinterpret_cast<gralloc_context_t*>(dev);
281 if (ctx) {
282 /* TODO: keep a list of all buffer_handle_t created, and free them
283 * all here.
284 */
285 free(ctx);
286 }
287 return 0;
288 }
289
290 int gralloc_device_open(const hw_module_t* module, const char* name,
291 hw_device_t** device)
292 {
293 int status = -EINVAL;
294 if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) {
295 gralloc_context_t *dev;
296 dev = (gralloc_context_t*)malloc(sizeof(*dev));
297
298 /* initialize our state here */
299 memset(dev, 0, sizeof(*dev));
300
301 /* initialize the procs */
302 dev->device.common.tag = HARDWARE_DEVICE_TAG;
303 dev->device.common.version = 0;
304 dev->device.common.module = const_cast<hw_module_t*>(module);
305 dev->device.common.close = gralloc_close;
306
307 dev->device.alloc = gralloc_alloc;
308 dev->device.free = gralloc_free;
309
310 private_module_t *p = reinterpret_cast<private_module_t*>(dev->device.common.module);
311 p->ionfd = ion_open();
312
313 *device = &dev->device.common;
314 status = 0;
315 } else {
316 status = fb_device_open(module, name, device);
317 }
318 return status;
319 }