exynos: gralloc: implement gralloc_lock_ycbcr
[GitHub/LineageOS/android_hardware_samsung_slsi_exynos5.git] / gralloc / mapper.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 #include <limits.h>
18 #include <errno.h>
19 #include <pthread.h>
20 #include <unistd.h>
21 #include <string.h>
22
23 #include <sys/mman.h>
24 #include <sys/stat.h>
25 #include <sys/types.h>
26
27 #include <cutils/log.h>
28 #include <cutils/atomic.h>
29
30 #include <hardware/hardware.h>
31 #include <hardware/gralloc.h>
32
33 #include "gralloc_priv.h"
34 #include "exynos_format.h"
35
36 #include <ion/ion.h>
37 #include <linux/ion.h>
38
39 /*****************************************************************************/
40
41 static int gralloc_map(gralloc_module_t const* module, buffer_handle_t handle)
42 {
43 private_handle_t* hnd = (private_handle_t*)handle;
44
45 void* mappedAddress = mmap(0, hnd->size, PROT_READ|PROT_WRITE, MAP_SHARED,
46 hnd->fd, 0);
47 if (mappedAddress == MAP_FAILED) {
48 ALOGE("%s: could not mmap %s", __func__, strerror(errno));
49 return -errno;
50 }
51 ALOGV("%s: base %p %d %d %d %d\n", __func__, mappedAddress, hnd->size,
52 hnd->width, hnd->height, hnd->stride);
53 hnd->base = mappedAddress;
54 return 0;
55 }
56
57 static int gralloc_unmap(gralloc_module_t const* module, buffer_handle_t handle)
58 {
59 private_handle_t* hnd = (private_handle_t*)handle;
60
61 if (hnd->base != NULL && munmap(hnd->base, hnd->size) < 0) {
62 ALOGE("%s :could not unmap %s %p %d", __func__, strerror(errno),
63 hnd->base, hnd->size);
64 }
65 hnd->base = NULL;
66 if (hnd->base1 != NULL && hnd->format == HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED) {
67 // unmap plane-2 of mapped NV12 TILED format
68 size_t chroma_vstride = ALIGN(hnd->height / 2, 32);
69 size_t chroma_size = chroma_vstride * hnd->stride;
70 if (munmap(hnd->base1, chroma_size) < 0) {
71 ALOGE("%s :could not unmap %s %p %zd", __func__, strerror(errno),
72 hnd->base1, chroma_size);
73 }
74 hnd->base1 = NULL;
75 }
76 ALOGV("%s: base %p %d %d %d %d\n", __func__, hnd->base, hnd->size,
77 hnd->width, hnd->height, hnd->stride);
78 return 0;
79 }
80
81
82 static int gralloc_map_yuv(gralloc_module_t const* module, buffer_handle_t handle)
83 {
84 private_handle_t* hnd = (private_handle_t*)handle;
85
86 // only support NV12 TILED format
87 if (hnd->format != HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED) {
88 return -EINVAL;
89 }
90
91 size_t chroma_vstride = ALIGN(hnd->height / 2, 32);
92 size_t chroma_size = chroma_vstride * hnd->stride;
93 ALOGI("map_yuv: size=%d/%zu", hnd->size, chroma_size);
94
95 if (hnd->base == NULL) {
96 int err = gralloc_map(module, handle);
97 if (err != 0) {
98 return err;
99 }
100 }
101
102 // map plane-2 for NV12 TILED format
103 void* mappedAddress = mmap(0, chroma_size, PROT_READ|PROT_WRITE, MAP_SHARED,
104 hnd->fd1, 0);
105 if (mappedAddress == MAP_FAILED) {
106 ALOGE("%s: could not mmap %s", __func__, strerror(errno));
107 gralloc_unmap(module, handle);
108 return -errno;
109 }
110
111 ALOGV("%s: chroma %p %d %d %d %d\n", __func__, mappedAddress, hnd->size,
112 hnd->width, hnd->height, hnd->stride);
113 hnd->base1 = mappedAddress;
114 return 0;
115 }
116
117 /*****************************************************************************/
118
119 int getIonFd(gralloc_module_t const *module)
120 {
121 private_module_t* m = const_cast<private_module_t*>(reinterpret_cast<const private_module_t*>(module));
122 if (m->ionfd == -1)
123 m->ionfd = ion_open();
124 return m->ionfd;
125 }
126
127 static pthread_mutex_t sMapLock = PTHREAD_MUTEX_INITIALIZER;
128
129 /*****************************************************************************/
130
131 int gralloc_register_buffer(gralloc_module_t const* module,
132 buffer_handle_t handle)
133 {
134 if (private_handle_t::validate(handle) < 0)
135 return -EINVAL;
136
137 private_handle_t* hnd = (private_handle_t*)handle;
138 ALOGV("%s: base %p %d %d %d %d\n", __func__, hnd->base, hnd->size,
139 hnd->width, hnd->height, hnd->stride);
140
141 int ret;
142 ret = ion_import(getIonFd(module), hnd->fd, &hnd->handle);
143 if (ret)
144 ALOGE("error importing handle %d %x\n", hnd->fd, hnd->format);
145 if (hnd->fd1 >= 0) {
146 ret = ion_import(getIonFd(module), hnd->fd1, &hnd->handle1);
147 if (ret)
148 ALOGE("error importing handle1 %d %x\n", hnd->fd1, hnd->format);
149 }
150 if (hnd->fd2 >= 0) {
151 ret = ion_import(getIonFd(module), hnd->fd2, &hnd->handle2);
152 if (ret)
153 ALOGE("error importing handle2 %d %x\n", hnd->fd2, hnd->format);
154 }
155
156 return ret;
157 }
158
159 int gralloc_unregister_buffer(gralloc_module_t const* module,
160 buffer_handle_t handle)
161 {
162 if (private_handle_t::validate(handle) < 0)
163 return -EINVAL;
164
165 private_handle_t* hnd = (private_handle_t*)handle;
166 ALOGV("%s: base %p %d %d %d %d\n", __func__, hnd->base, hnd->size,
167 hnd->width, hnd->height, hnd->stride);
168
169 gralloc_unmap(module, handle);
170
171 if (hnd->handle)
172 ion_free(getIonFd(module), hnd->handle);
173 if (hnd->handle1)
174 ion_free(getIonFd(module), hnd->handle1);
175 if (hnd->handle2)
176 ion_free(getIonFd(module), hnd->handle2);
177
178 return 0;
179 }
180
181 int gralloc_lock(gralloc_module_t const* module,
182 buffer_handle_t handle, int usage,
183 int l, int t, int w, int h,
184 void** vaddr)
185 {
186 // this is called when a buffer is being locked for software
187 // access. in thin implementation we have nothing to do since
188 // not synchronization with the h/w is needed.
189 // typically this is used to wait for the h/w to finish with
190 // this buffer if relevant. the data cache may need to be
191 // flushed or invalidated depending on the usage bits and the
192 // hardware.
193
194 if (private_handle_t::validate(handle) < 0)
195 return -EINVAL;
196
197 private_handle_t* hnd = (private_handle_t*)handle;
198 if (!hnd->base)
199 gralloc_map(module, hnd);
200 *vaddr = (void*)hnd->base;
201 return 0;
202 }
203
204 int gralloc_lock_ycbcr(gralloc_module_t const* module,
205 buffer_handle_t handle, int usage,
206 int l, int t, int w, int h,
207 struct android_ycbcr *ycbcr)
208 {
209 // This is called when a YUV buffer is being locked for software
210 // access. In this implementation we have nothing to do since
211 // no synchronization with the HW is needed.
212 // Typically this is used to wait for the h/w to finish with
213 // this buffer if relevant. The data cache may need to be
214 // flushed or invalidated depending on the usage bits and the
215 // hardware.
216
217 if (private_handle_t::validate(handle) < 0)
218 return -EINVAL;
219
220 private_handle_t* hnd = (private_handle_t*)handle;
221 ALOGV("lock_ycbcr for fmt=%d %dx%d %dx%d %d", hnd->format, hnd->width, hnd->height,
222 hnd->stride, hnd->vstride, hnd->size);
223 switch (hnd->format) {
224 case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
225 {
226 int err = 0;
227 if (hnd->base1 == NULL || hnd->base == NULL) {
228 err = gralloc_map_yuv(module, hnd);
229 }
230 if (err == 0) {
231 ycbcr->y = (void*)hnd->base;
232 ycbcr->cb = (void*)hnd->base1;
233 ycbcr->cr = (void*)((uint8_t *)hnd->base + 1);
234 ycbcr->ystride = hnd->stride;
235 ycbcr->cstride = hnd->stride;
236 ycbcr->chroma_step = 2;
237 memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved));
238 }
239 return err;
240 }
241 default:
242 return -EINVAL;
243 }
244 }
245
246 int gralloc_perform(struct gralloc_module_t const* module, int operation, ... )
247 {
248 // dummy implementation required to implement lock_ycbcr
249 return -EINVAL;
250 }
251
252 int gralloc_unlock(gralloc_module_t const* module,
253 buffer_handle_t handle)
254 {
255 // we're done with a software buffer. nothing to do in this
256 // implementation. typically this is used to flush the data cache.
257 private_handle_t* hnd = (private_handle_t*)handle;
258 ion_sync_fd(getIonFd(module), hnd->fd);
259 if (hnd->fd1 >= 0)
260 ion_sync_fd(getIonFd(module), hnd->fd1);
261 if (hnd->fd2 >= 0)
262 ion_sync_fd(getIonFd(module), hnd->fd2);
263
264 if (private_handle_t::validate(handle) < 0)
265 return -EINVAL;
266 return 0;
267 }