1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 * Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#include <limits.h>
19#include <errno.h>
20#include <pthread.h>
21#include <unistd.h>
22#include <string.h>
23#include <stdarg.h>
24
25#include <sys/mman.h>
26#include <sys/stat.h>
27#include <sys/types.h>
28#include <sys/ioctl.h>
29
30#include <cutils/log.h>
31#include <cutils/atomic.h>
32
33#include <hardware/hardware.h>
34#include <hardware/gralloc.h>
35
36#include "gralloc_priv.h"
37#include "gr.h"
38#include "alloc_controller.h"
39#include "memalloc.h"
40#include <qdMetaData.h>
41
42using namespace gralloc;
43/*****************************************************************************/
44
45// Return the type of allocator -
46// these are used for mapping/unmapping
47static IMemAlloc* getAllocator(int flags)
48{
49    IMemAlloc* memalloc;
50    IAllocController* alloc_ctrl = IAllocController::getInstance();
51    memalloc = alloc_ctrl->getAllocator(flags);
52    return memalloc;
53}
54
55static int gralloc_map(gralloc_module_t const* module,
56                       buffer_handle_t handle)
57{
58    if(!module)
59        return -EINVAL;
60
61    private_handle_t* hnd = (private_handle_t*)handle;
62    void *mappedAddress;
63    if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) &&
64        !(hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER)) {
65        size_t size = hnd->size;
66        IMemAlloc* memalloc = getAllocator(hnd->flags) ;
67        int err = memalloc->map_buffer(&mappedAddress, size,
68                                       hnd->offset, hnd->fd);
69        if(err || mappedAddress == MAP_FAILED) {
70            ALOGE("Could not mmap handle %p, fd=%d (%s)",
71                  handle, hnd->fd, strerror(errno));
72            hnd->base = 0;
73            return -errno;
74        }
75
76        hnd->base = intptr_t(mappedAddress) + hnd->offset;
77        mappedAddress = MAP_FAILED;
78        size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
79        err = memalloc->map_buffer(&mappedAddress, size,
80                                       hnd->offset_metadata, hnd->fd_metadata);
81        if(err || mappedAddress == MAP_FAILED) {
82            ALOGE("Could not mmap handle %p, fd=%d (%s)",
83                  handle, hnd->fd_metadata, strerror(errno));
84            hnd->base_metadata = 0;
85            return -errno;
86        }
87        hnd->base_metadata = intptr_t(mappedAddress) + hnd->offset_metadata;
88    }
89    return 0;
90}
91
92static int gralloc_unmap(gralloc_module_t const* module,
93                         buffer_handle_t handle)
94{
95    if(!module)
96        return -EINVAL;
97
98    private_handle_t* hnd = (private_handle_t*)handle;
99    if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
100        int err = -EINVAL;
101        void* base = (void*)hnd->base;
102        size_t size = hnd->size;
103        IMemAlloc* memalloc = getAllocator(hnd->flags) ;
104        if(memalloc != NULL) {
105            err = memalloc->unmap_buffer(base, size, hnd->offset);
106            if (err) {
107                ALOGE("Could not unmap memory at address %p", base);
108            }
109            base = (void*)hnd->base_metadata;
110            size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
111            err = memalloc->unmap_buffer(base, size, hnd->offset_metadata);
112            if (err) {
113                ALOGE("Could not unmap memory at address %p", base);
114            }
115        }
116    }
117    /* need to initialize the pointer to NULL otherwise unmapping for that
118     * buffer happens twice which leads to crash */
119    hnd->base = 0;
120    hnd->base_metadata = 0;
121    return 0;
122}
123
124/*****************************************************************************/
125
126static pthread_mutex_t sMapLock = PTHREAD_MUTEX_INITIALIZER;
127
128/*****************************************************************************/
129
130int gralloc_register_buffer(gralloc_module_t const* module,
131                            buffer_handle_t handle)
132{
133    if (!module || private_handle_t::validate(handle) < 0)
134        return -EINVAL;
135
136    // In this implementation, we don't need to do anything here
137
138    /* NOTE: we need to initialize the buffer as not mapped/not locked
139     * because it shouldn't when this function is called the first time
140     * in a new process. Ideally these flags shouldn't be part of the
141     * handle, but instead maintained in the kernel or at least
142     * out-of-line
143     */
144
145    private_handle_t* hnd = (private_handle_t*)handle;
146    hnd->base = 0;
147    hnd->base_metadata = 0;
148    int err = gralloc_map(module, handle);
149    if (err) {
150        ALOGE("%s: gralloc_map failed", __FUNCTION__);
151        return err;
152    }
153
154    return 0;
155}
156
157int gralloc_unregister_buffer(gralloc_module_t const* module,
158                              buffer_handle_t handle)
159{
160    if (!module || private_handle_t::validate(handle) < 0)
161        return -EINVAL;
162
163    /*
164     * If the buffer has been mapped during a lock operation, it's time
165     * to un-map it. It's an error to be here with a locked buffer.
166     * NOTE: the framebuffer is handled differently and is never unmapped.
167     */
168
169    private_handle_t* hnd = (private_handle_t*)handle;
170
171    if (hnd->base != 0) {
172        gralloc_unmap(module, handle);
173    }
174    hnd->base = 0;
175    hnd->base_metadata = 0;
176    return 0;
177}
178
179int terminateBuffer(gralloc_module_t const* module,
180                    private_handle_t* hnd)
181{
182    if(!module)
183        return -EINVAL;
184
185    /*
186     * If the buffer has been mapped during a lock operation, it's time
187     * to un-map it. It's an error to be here with a locked buffer.
188     */
189
190    if (hnd->base != 0) {
191        // this buffer was mapped, unmap it now
192        if (hnd->flags & (private_handle_t::PRIV_FLAGS_USES_PMEM |
193                          private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP |
194                          private_handle_t::PRIV_FLAGS_USES_ASHMEM |
195                          private_handle_t::PRIV_FLAGS_USES_ION)) {
196                gralloc_unmap(module, hnd);
197        } else {
198            ALOGE("terminateBuffer: unmapping a non pmem/ashmem buffer flags = 0x%x",
199                  hnd->flags);
200            gralloc_unmap(module, hnd);
201        }
202    }
203
204    return 0;
205}
206
207static int gralloc_map_and_invalidate (gralloc_module_t const* module,
208                                       buffer_handle_t handle, int usage)
209{
210    if (!module || private_handle_t::validate(handle) < 0)
211        return -EINVAL;
212
213    int err = 0;
214    private_handle_t* hnd = (private_handle_t*)handle;
215    if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) {
216        if (hnd->base == 0) {
217            // we need to map for real
218            pthread_mutex_t* const lock = &sMapLock;
219            pthread_mutex_lock(lock);
220            err = gralloc_map(module, handle);
221            pthread_mutex_unlock(lock);
222        }
223        if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) {
224            //Invalidate if reading in software. No need to do this for the
225            //metadata buffer as it is only read/written in software.
226            IMemAlloc* memalloc = getAllocator(hnd->flags) ;
227            err = memalloc->clean_buffer((void*)hnd->base,
228                                         hnd->size, hnd->offset, hnd->fd,
229                                         CACHE_INVALIDATE);
230            if (usage & GRALLOC_USAGE_SW_WRITE_MASK) {
231                // Mark the buffer to be flushed after cpu read/write
232                hnd->flags |= private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
233            }
234        }
235    } else {
236        hnd->flags |= private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH;
237    }
238    return err;
239}
240
241int gralloc_lock(gralloc_module_t const* module,
242                 buffer_handle_t handle, int usage,
243                 int /*l*/, int /*t*/, int /*w*/, int /*h*/,
244                 void** vaddr)
245{
246    private_handle_t* hnd = (private_handle_t*)handle;
247    int err = gralloc_map_and_invalidate(module, handle, usage);
248    if(!err)
249        *vaddr = (void*)hnd->base;
250    return err;
251}
252
253int gralloc_lock_ycbcr(gralloc_module_t const* module,
254                 buffer_handle_t handle, int usage,
255                 int /*l*/, int /*t*/, int /*w*/, int /*h*/,
256                 struct android_ycbcr *ycbcr)
257{
258    private_handle_t* hnd = (private_handle_t*)handle;
259    int err = gralloc_map_and_invalidate(module, handle, usage);
260    if(!err)
261        err = getYUVPlaneInfo(hnd, ycbcr);
262    return err;
263}
264
265int gralloc_unlock(gralloc_module_t const* module,
266                   buffer_handle_t handle)
267{
268    if (!module || private_handle_t::validate(handle) < 0)
269        return -EINVAL;
270
271    int err = 0;
272    private_handle_t* hnd = (private_handle_t*)handle;
273
274    if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) {
275        IMemAlloc* memalloc = getAllocator(hnd->flags);
276        if (hnd->flags & private_handle_t::PRIV_FLAGS_NEEDS_FLUSH) {
277            err = memalloc->clean_buffer((void*)hnd->base,
278                                         hnd->size, hnd->offset, hnd->fd,
279                                         CACHE_CLEAN_AND_INVALIDATE);
280            hnd->flags &= ~private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
281        } else if(hnd->flags & private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH) {
282            hnd->flags &= ~private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH;
283        } else {
284            //Probably a round about way to do this, but this avoids adding new
285            //flags
286            err = memalloc->clean_buffer((void*)hnd->base,
287                                         hnd->size, hnd->offset, hnd->fd,
288                                         CACHE_INVALIDATE);
289        }
290    }
291
292    return err;
293}
294
295/*****************************************************************************/
296
297int gralloc_perform(struct gralloc_module_t const* module,
298                    int operation, ... )
299{
300    int res = -EINVAL;
301    va_list args;
302    if(!module)
303        return res;
304
305    va_start(args, operation);
306    switch (operation) {
307        case GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER:
308            {
309                int fd = va_arg(args, int);
310                size_t size = va_arg(args, size_t);
311                size_t offset = va_arg(args, size_t);
312                void* base = va_arg(args, void*);
313                int width = va_arg(args, int);
314                int height = va_arg(args, int);
315                int format = va_arg(args, int);
316
317                native_handle_t** handle = va_arg(args, native_handle_t**);
318                private_handle_t* hnd = (private_handle_t*)native_handle_create(
319                    private_handle_t::sNumFds, private_handle_t::sNumInts);
320                hnd->magic = private_handle_t::sMagic;
321                hnd->fd = fd;
322                hnd->flags =  private_handle_t::PRIV_FLAGS_USES_ION;
323                hnd->size = size;
324                hnd->offset = offset;
325                hnd->base = intptr_t(base) + offset;
326                hnd->gpuaddr = 0;
327                hnd->width = width;
328                hnd->height = height;
329                hnd->format = format;
330                *handle = (native_handle_t *)hnd;
331                res = 0;
332                break;
333
334            }
335#ifdef QCOM_BSP
336        case GRALLOC_MODULE_PERFORM_UPDATE_BUFFER_GEOMETRY:
337            {
338                int width = va_arg(args, int);
339                int height = va_arg(args, int);
340                int format = va_arg(args, int);
341                private_handle_t* hnd =  va_arg(args, private_handle_t*);
342                if (private_handle_t::validate(hnd)) {
343                    return res;
344                }
345                hnd->width = width;
346                hnd->height = height;
347                hnd->format = format;
348                res = 0;
349            }
350            break;
351#endif
352        case GRALLOC_MODULE_PERFORM_GET_STRIDE:
353            {
354                int width   = va_arg(args, int);
355                int format  = va_arg(args, int);
356                int *stride = va_arg(args, int *);
357                int alignedw = 0, alignedh = 0;
358                AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
359                        0, format, false, alignedw, alignedh);
360                *stride = alignedw;
361                res = 0;
362            } break;
363
364        case GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_FROM_HANDLE:
365            {
366                private_handle_t* hnd =  va_arg(args, private_handle_t*);
367                int *stride = va_arg(args, int *);
368                if (private_handle_t::validate(hnd)) {
369                    return res;
370                }
371                MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
372                if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
373                    *stride = metadata->bufferDim.sliceWidth;
374                } else {
375                    *stride = hnd->width;
376                }
377                res = 0;
378            } break;
379
380        case GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_AND_HEIGHT_FROM_HANDLE:
381            {
382                private_handle_t* hnd =  va_arg(args, private_handle_t*);
383                int *stride = va_arg(args, int *);
384                int *height = va_arg(args, int *);
385                if (private_handle_t::validate(hnd)) {
386                    return res;
387                }
388                MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
389                if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
390                    *stride = metadata->bufferDim.sliceWidth;
391                    *height = metadata->bufferDim.sliceHeight;
392                } else {
393                    *stride = hnd->width;
394                    *height = hnd->height;
395                }
396                res = 0;
397            } break;
398
399        case GRALLOC_MODULE_PERFORM_GET_ATTRIBUTES:
400            {
401                int width   = va_arg(args, int);
402                int height  = va_arg(args, int);
403                int format  = va_arg(args, int);
404                int usage   = va_arg(args, int);
405                int *alignedWidth = va_arg(args, int *);
406                int *alignedHeight = va_arg(args, int *);
407                int *tileEnabled = va_arg(args,int *);
408                *tileEnabled = isMacroTileEnabled(format, usage);
409                AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
410                        height, format, *tileEnabled, *alignedWidth,
411                        *alignedHeight);
412                res = 0;
413            } break;
414
415        case GRALLOC_MODULE_PERFORM_GET_COLOR_SPACE_FROM_HANDLE:
416            {
417                private_handle_t* hnd =  va_arg(args, private_handle_t*);
418                int *color_space = va_arg(args, int *);
419                if (private_handle_t::validate(hnd)) {
420                    return res;
421                }
422                MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
423                if(metadata && metadata->operation & UPDATE_COLOR_SPACE) {
424                    *color_space = metadata->colorSpace;
425                    res = 0;
426                }
427            } break;
428        case GRALLOC_MODULE_PERFORM_GET_YUV_PLANE_INFO:
429            {
430                private_handle_t* hnd =  va_arg(args, private_handle_t*);
431                android_ycbcr* ycbcr = va_arg(args, struct android_ycbcr *);
432                if (!private_handle_t::validate(hnd)) {
433                    res = getYUVPlaneInfo(hnd, ycbcr);
434                }
435            } break;
436
437        default:
438            break;
439    }
440    va_end(args);
441    return res;
442}
443