Home | History | Annotate | Download | only in libgralloc
      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 #include <stdarg.h>
     23 
     24 #include <sys/mman.h>
     25 #include <sys/stat.h>
     26 #include <sys/types.h>
     27 #include <sys/ioctl.h>
     28 
     29 #include <cutils/log.h>
     30 #include <cutils/atomic.h>
     31 
     32 #include <hardware/hardware.h>
     33 #include <hardware/gralloc.h>
     34 
     35 #include <linux/android_pmem.h>
     36 
     37 #include "gralloc_priv.h"
     38 
     39 
     40 // we need this for now because pmem cannot mmap at an offset
     41 #define PMEM_HACK   1
     42 
     43 /* desktop Linux needs a little help with gettid() */
     44 #if defined(ARCH_X86) && !defined(HAVE_ANDROID_OS)
     45 #define __KERNEL__
     46 # include <linux/unistd.h>
     47 pid_t gettid() { return syscall(__NR_gettid);}
     48 #undef __KERNEL__
     49 #endif
     50 
     51 /*****************************************************************************/
     52 
     53 static int gralloc_map(gralloc_module_t const* module,
     54         buffer_handle_t handle,
     55         void** vaddr)
     56 {
     57     private_handle_t* hnd = (private_handle_t*)handle;
     58     if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
     59         size_t size = hnd->size;
     60 #if PMEM_HACK
     61         size += hnd->offset;
     62 #endif
     63         void* mappedAddress = mmap(0, size,
     64                 PROT_READ|PROT_WRITE, MAP_SHARED, hnd->fd, 0);
     65         if (mappedAddress == MAP_FAILED) {
     66             LOGE("Could not mmap handle %p, fd=%d (%s)",
     67                     handle, hnd->fd, strerror(errno));
     68             hnd->base = 0;
     69             return -errno;
     70         }
     71         hnd->base = intptr_t(mappedAddress) + hnd->offset;
     72         //LOGD("gralloc_map() succeeded fd=%d, off=%d, size=%d, vaddr=%p",
     73         //        hnd->fd, hnd->offset, hnd->size, mappedAddress);
     74     }
     75     *vaddr = (void*)hnd->base;
     76     return 0;
     77 }
     78 
     79 static int gralloc_unmap(gralloc_module_t const* module,
     80         buffer_handle_t handle)
     81 {
     82     private_handle_t* hnd = (private_handle_t*)handle;
     83     if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
     84         void* base = (void*)hnd->base;
     85         size_t size = hnd->size;
     86 #if PMEM_HACK
     87         base = (void*)(intptr_t(base) - hnd->offset);
     88         size += hnd->offset;
     89 #endif
     90         //LOGD("unmapping from %p, size=%d, flags=%08x", base, size, hnd->flags);
     91         if (munmap(base, size) < 0) {
     92             LOGE("Could not unmap %s", strerror(errno));
     93         }
     94     }
     95     hnd->base = 0;
     96     return 0;
     97 }
     98 
     99 /*****************************************************************************/
    100 
    101 static pthread_mutex_t sMapLock = PTHREAD_MUTEX_INITIALIZER;
    102 
    103 /*****************************************************************************/
    104 
    105 int gralloc_register_buffer(gralloc_module_t const* module,
    106         buffer_handle_t handle)
    107 {
    108     if (private_handle_t::validate(handle) < 0)
    109         return -EINVAL;
    110 
    111     // if this handle was created in this process, then we keep it as is.
    112     int err = 0;
    113     private_handle_t* hnd = (private_handle_t*)handle;
    114     if (hnd->pid != getpid()) {
    115         hnd->base = NULL;
    116         if (!(hnd->flags & private_handle_t::PRIV_FLAGS_USES_GPU)) {
    117             void *vaddr;
    118             err = gralloc_map(module, handle, &vaddr);
    119         }
    120     }
    121     return err;
    122 }
    123 
    124 int gralloc_unregister_buffer(gralloc_module_t const* module,
    125         buffer_handle_t handle)
    126 {
    127     if (private_handle_t::validate(handle) < 0)
    128         return -EINVAL;
    129 
    130     // never unmap buffers that were created in this process
    131     private_handle_t* hnd = (private_handle_t*)handle;
    132     if (hnd->pid != getpid()) {
    133         if (hnd->base) {
    134             gralloc_unmap(module, handle);
    135         }
    136     }
    137     return 0;
    138 }
    139 
    140 int mapBuffer(gralloc_module_t const* module,
    141         private_handle_t* hnd)
    142 {
    143     void* vaddr;
    144     return gralloc_map(module, hnd, &vaddr);
    145 }
    146 
    147 int terminateBuffer(gralloc_module_t const* module,
    148         private_handle_t* hnd)
    149 {
    150     if (hnd->base) {
    151         // this buffer was mapped, unmap it now
    152         if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_PMEM) {
    153             if (hnd->pid != getpid()) {
    154                 // ... unless it's a "master" pmem buffer, that is a buffer
    155                 // mapped in the process it's been allocated.
    156                 // (see gralloc_alloc_buffer())
    157                 gralloc_unmap(module, hnd);
    158             }
    159         } else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_GPU) {
    160             // XXX: for now do nothing here
    161         } else {
    162             gralloc_unmap(module, hnd);
    163         }
    164     }
    165 
    166     return 0;
    167 }
    168 
    169 int gralloc_lock(gralloc_module_t const* module,
    170         buffer_handle_t handle, int usage,
    171         int l, int t, int w, int h,
    172         void** vaddr)
    173 {
    174     // this is called when a buffer is being locked for software
    175     // access. in thin implementation we have nothing to do since
    176     // not synchronization with the h/w is needed.
    177     // typically this is used to wait for the h/w to finish with
    178     // this buffer if relevant. the data cache may need to be
    179     // flushed or invalidated depending on the usage bits and the
    180     // hardware.
    181 
    182     if (private_handle_t::validate(handle) < 0)
    183         return -EINVAL;
    184 
    185     private_handle_t* hnd = (private_handle_t*)handle;
    186     *vaddr = (void*)hnd->base;
    187     return 0;
    188 }
    189 
    190 int gralloc_unlock(gralloc_module_t const* module,
    191         buffer_handle_t handle)
    192 {
    193     // we're done with a software buffer. nothing to do in this
    194     // implementation. typically this is used to flush the data cache.
    195 
    196     if (private_handle_t::validate(handle) < 0)
    197         return -EINVAL;
    198     return 0;
    199 }
    200 
    201 
    202 /*****************************************************************************/
    203 
    204 int gralloc_perform(struct gralloc_module_t const* module,
    205         int operation, ... )
    206 {
    207     int res = -EINVAL;
    208     va_list args;
    209     va_start(args, operation);
    210 
    211     switch (operation) {
    212         case GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER: {
    213             int fd = va_arg(args, int);
    214             size_t size = va_arg(args, size_t);
    215             size_t offset = va_arg(args, size_t);
    216             void* base = va_arg(args, void*);
    217 
    218             // validate that it's indeed a pmem buffer
    219             pmem_region region;
    220             if (ioctl(fd, PMEM_GET_SIZE, &region) < 0) {
    221                 break;
    222             }
    223 
    224             native_handle_t** handle = va_arg(args, native_handle_t**);
    225             private_handle_t* hnd = (private_handle_t*)native_handle_create(
    226                     private_handle_t::sNumFds, private_handle_t::sNumInts);
    227             hnd->magic = private_handle_t::sMagic;
    228             hnd->fd = fd;
    229             hnd->flags = private_handle_t::PRIV_FLAGS_USES_PMEM;
    230             hnd->size = size;
    231             hnd->offset = offset;
    232             hnd->base = intptr_t(base) + offset;
    233             *handle = (native_handle_t *)hnd;
    234             res = 0;
    235             break;
    236         }
    237     }
    238 
    239     va_end(args);
    240     return res;
    241 }
    242