mapper.cpp revision 202a77d28ac251545f6f998a974690212309b927
1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 * Copyright (c) 2011 Code Aurora Forum. 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#include <linux/ashmem.h>
30
31#include <cutils/log.h>
32#include <cutils/atomic.h>
33#include <cutils/ashmem.h>
34
35#include <hardware/hardware.h>
36#include <hardware/gralloc.h>
37#include <genlock.h>
38
39#include <linux/android_pmem.h>
40
41#include "gralloc_priv.h"
42#include "gr.h"
43#include "alloc_controller.h"
44#include "memalloc.h"
45
46using namespace gralloc;
47using android::sp;
48/*****************************************************************************/
49
50// Return the type of allocator -
51// these are used for mapping/unmapping
52static sp<IMemAlloc> getAllocator(int flags)
53{
54    sp<IMemAlloc> memalloc;
55    sp<IAllocController> alloc_ctrl = IAllocController::getInstance(true);
56    memalloc = alloc_ctrl->getAllocator(flags);
57    return memalloc;
58}
59
60static int gralloc_map(gralloc_module_t const* module,
61        buffer_handle_t handle,
62        void** vaddr)
63{
64    private_handle_t* hnd = (private_handle_t*)handle;
65    void *mappedAddress;
66    if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) &&
67        !(hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER)) {
68        size_t size = hnd->size;
69        sp<IMemAlloc> memalloc = getAllocator(hnd->flags) ;
70        int err = memalloc->map_buffer(&mappedAddress, size,
71                hnd->offset, hnd->fd);
72        if(err) {
73            ALOGE("Could not mmap handle %p, fd=%d (%s)",
74                    handle, hnd->fd, strerror(errno));
75            hnd->base = 0;
76            return -errno;
77        }
78
79        if (mappedAddress == MAP_FAILED) {
80            ALOGE("Could not mmap handle %p, fd=%d (%s)",
81                    handle, hnd->fd, strerror(errno));
82            hnd->base = 0;
83            return -errno;
84        }
85        hnd->base = intptr_t(mappedAddress) + hnd->offset;
86        //ALOGD("gralloc_map() succeeded fd=%d, off=%d, size=%d, vaddr=%p",
87        //        hnd->fd, hnd->offset, hnd->size, mappedAddress);
88    }
89    *vaddr = (void*)hnd->base;
90    return 0;
91}
92
93static int gralloc_unmap(gralloc_module_t const* module,
94        buffer_handle_t handle)
95{
96    private_handle_t* hnd = (private_handle_t*)handle;
97    if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
98        int err = -EINVAL;
99        void* base = (void*)hnd->base;
100        size_t size = hnd->size;
101        sp<IMemAlloc> memalloc = getAllocator(hnd->flags) ;
102        if(memalloc != NULL)
103            err = memalloc->unmap_buffer(base, size, hnd->offset);
104        if (err) {
105            ALOGE("Could not unmap memory at address %p", base);
106        }
107    }
108    hnd->base = 0;
109    return 0;
110}
111
112/*****************************************************************************/
113
114static pthread_mutex_t sMapLock = PTHREAD_MUTEX_INITIALIZER;
115
116/*****************************************************************************/
117
118int gralloc_register_buffer(gralloc_module_t const* module,
119        buffer_handle_t handle)
120{
121    if (private_handle_t::validate(handle) < 0)
122        return -EINVAL;
123
124    // In this implementation, we don't need to do anything here
125
126    /* NOTE: we need to initialize the buffer as not mapped/not locked
127     * because it shouldn't when this function is called the first time
128     * in a new process. Ideally these flags shouldn't be part of the
129     * handle, but instead maintained in the kernel or at least
130     * out-of-line
131     */
132
133    // if this handle was created in this process, then we keep it as is.
134    private_handle_t* hnd = (private_handle_t*)handle;
135    if (hnd->pid != getpid()) {
136        hnd->base = 0;
137        void *vaddr;
138        int err = gralloc_map(module, handle, &vaddr);
139        if (err) {
140            ALOGE("%s: gralloc_map failed", __FUNCTION__);
141            return err;
142        }
143
144        // Reset the genlock private fd flag in the handle
145        hnd->genlockPrivFd = -1;
146
147        // Check if there is a valid lock attached to the handle.
148        if (-1 == hnd->genlockHandle) {
149            ALOGE("%s: the lock is invalid.", __FUNCTION__);
150            gralloc_unmap(module, handle);
151            hnd->base = 0;
152            return -EINVAL;
153        }
154
155        // Attach the genlock handle
156        if (GENLOCK_NO_ERROR != genlock_attach_lock((native_handle_t *)handle)) {
157            ALOGE("%s: genlock_attach_lock failed", __FUNCTION__);
158            gralloc_unmap(module, handle);
159            hnd->base = 0;
160            return -EINVAL;
161        }
162    }
163    return 0;
164}
165
166int gralloc_unregister_buffer(gralloc_module_t const* module,
167        buffer_handle_t handle)
168{
169    if (private_handle_t::validate(handle) < 0)
170        return -EINVAL;
171
172    /*
173     * If the buffer has been mapped during a lock operation, it's time
174     * to un-map it. It's an error to be here with a locked buffer.
175     * NOTE: the framebuffer is handled differently and is never unmapped.
176     */
177
178    private_handle_t* hnd = (private_handle_t*)handle;
179
180    // never unmap buffers that were created in this process
181    if (hnd->pid != getpid()) {
182        if (hnd->base != 0) {
183            gralloc_unmap(module, handle);
184        }
185        hnd->base = 0;
186        // Release the genlock
187        if (-1 != hnd->genlockHandle) {
188            return genlock_release_lock((native_handle_t *)handle);
189        } else {
190            ALOGE("%s: there was no genlock attached to this buffer", __FUNCTION__);
191            return -EINVAL;
192        }
193    }
194    return 0;
195}
196
197int terminateBuffer(gralloc_module_t const* module,
198        private_handle_t* hnd)
199{
200    /*
201     * If the buffer has been mapped during a lock operation, it's time
202     * to un-map it. It's an error to be here with a locked buffer.
203     */
204
205    if (hnd->base != 0) {
206        // this buffer was mapped, unmap it now
207        if (hnd->flags & (private_handle_t::PRIV_FLAGS_USES_PMEM |
208                          private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP |
209                          private_handle_t::PRIV_FLAGS_USES_ASHMEM |
210                          private_handle_t::PRIV_FLAGS_USES_ION)) {
211            if (hnd->pid != getpid()) {
212                // ... unless it's a "master" pmem buffer, that is a buffer
213                // mapped in the process it's been allocated.
214                // (see gralloc_alloc_buffer())
215                gralloc_unmap(module, hnd);
216            }
217        } else {
218            ALOGE("terminateBuffer: unmapping a non pmem/ashmem buffer flags = 0x%x", hnd->flags);
219            gralloc_unmap(module, hnd);
220        }
221    }
222
223    return 0;
224}
225
226int gralloc_lock(gralloc_module_t const* module,
227        buffer_handle_t handle, int usage,
228        int l, int t, int w, int h,
229        void** vaddr)
230{
231    if (private_handle_t::validate(handle) < 0)
232        return -EINVAL;
233
234    int err = 0;
235    private_handle_t* hnd = (private_handle_t*)handle;
236    if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) {
237        if (hnd->base == 0) {
238            // we need to map for real
239            pthread_mutex_t* const lock = &sMapLock;
240            pthread_mutex_lock(lock);
241            err = gralloc_map(module, handle, vaddr);
242            pthread_mutex_unlock(lock);
243        }
244        *vaddr = (void*)hnd->base;
245
246        // Lock the buffer for read/write operation as specified. Write lock
247        // has a higher priority over read lock.
248        int lockType = 0;
249        if (usage & GRALLOC_USAGE_SW_WRITE_MASK) {
250            lockType = GENLOCK_WRITE_LOCK;
251        } else if (usage & GRALLOC_USAGE_SW_READ_MASK) {
252            lockType = GENLOCK_READ_LOCK;
253        }
254
255        int timeout = GENLOCK_MAX_TIMEOUT;
256        if (GENLOCK_NO_ERROR != genlock_lock_buffer((native_handle_t *)handle,
257                                                   (genlock_lock_type)lockType,
258                                                   timeout)) {
259            ALOGE("%s: genlock_lock_buffer (lockType=0x%x) failed", __FUNCTION__,
260                lockType);
261            return -EINVAL;
262        } else {
263            // Mark this buffer as locked for SW read/write operation.
264            hnd->flags |= private_handle_t::PRIV_FLAGS_SW_LOCK;
265        }
266
267        if ((usage & GRALLOC_USAGE_SW_WRITE_MASK) &&
268            !(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
269            // Mark the buffer to be flushed after cpu read/write
270            hnd->flags |= private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
271        }
272    }
273    return err;
274}
275
276int gralloc_unlock(gralloc_module_t const* module,
277        buffer_handle_t handle)
278{
279    if (private_handle_t::validate(handle) < 0)
280        return -EINVAL;
281
282    private_handle_t* hnd = (private_handle_t*)handle;
283
284    if (hnd->flags & private_handle_t::PRIV_FLAGS_NEEDS_FLUSH) {
285        int err;
286        sp<IMemAlloc> memalloc = getAllocator(hnd->flags) ;
287        err = memalloc->clean_buffer((void*)hnd->base,
288                hnd->size, hnd->offset, hnd->fd);
289        ALOGE_IF(err < 0, "cannot flush handle %p (offs=%x len=%x, flags = 0x%x) err=%s\n",
290                hnd, hnd->offset, hnd->size, hnd->flags, strerror(errno));
291        hnd->flags &= ~private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
292    }
293
294    if ((hnd->flags & private_handle_t::PRIV_FLAGS_SW_LOCK)) {
295        // Unlock the buffer.
296        if (GENLOCK_NO_ERROR != genlock_unlock_buffer((native_handle_t *)handle)) {
297            ALOGE("%s: genlock_unlock_buffer failed", __FUNCTION__);
298            return -EINVAL;
299        } else
300            hnd->flags &= ~private_handle_t::PRIV_FLAGS_SW_LOCK;
301    }
302    return 0;
303}
304
305/*****************************************************************************/
306
307int gralloc_perform(struct gralloc_module_t const* module,
308        int operation, ... )
309{
310    int res = -EINVAL;
311    va_list args;
312    va_start(args, operation);
313    switch (operation) {
314        case GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER:
315            {
316                int fd = va_arg(args, int);
317                size_t size = va_arg(args, size_t);
318                size_t offset = va_arg(args, size_t);
319                void* base = va_arg(args, void*);
320                int width = va_arg(args, int);
321                int height = va_arg(args, int);
322                int format = va_arg(args, int);
323
324                native_handle_t** handle = va_arg(args, native_handle_t**);
325                int memoryFlags = va_arg(args, int);
326                private_handle_t* hnd = (private_handle_t*)native_handle_create(
327                        private_handle_t::sNumFds, private_handle_t::sNumInts);
328                hnd->magic = private_handle_t::sMagic;
329                hnd->fd = fd;
330                unsigned int contigFlags = GRALLOC_USAGE_PRIVATE_ADSP_HEAP |
331                                  GRALLOC_USAGE_PRIVATE_UI_CONTIG_HEAP |
332                                  GRALLOC_USAGE_PRIVATE_SMI_HEAP;
333
334                if (memoryFlags & contigFlags) {
335                    // check if the buffer is a pmem buffer
336                    pmem_region region;
337                    if (ioctl(fd, PMEM_GET_SIZE, &region) < 0)
338                        hnd->flags =  private_handle_t::PRIV_FLAGS_USES_ION;
339                    else
340                        hnd->flags =  private_handle_t::PRIV_FLAGS_USES_PMEM |
341                                      private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH;
342                } else {
343                    if (memoryFlags & GRALLOC_USAGE_PRIVATE_ION)
344                        hnd->flags =  private_handle_t::PRIV_FLAGS_USES_ION;
345                    else
346                        hnd->flags =  private_handle_t::PRIV_FLAGS_USES_ASHMEM;
347                }
348
349                hnd->size = size;
350                hnd->offset = offset;
351                hnd->base = intptr_t(base) + offset;
352                hnd->gpuaddr = 0;
353                hnd->width = width;
354                hnd->height = height;
355                hnd->format = format;
356                *handle = (native_handle_t *)hnd;
357                res = 0;
358                break;
359
360            }
361        default:
362            break;
363    }
364    va_end(args);
365    return res;
366}
367