Home | History | Annotate | Download | only in gralloc
      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 <errno.h>
     18 #include <fcntl.h>
     19 #include <limits.h>
     20 #include <pthread.h>
     21 #include <stdlib.h>
     22 #include <string.h>
     23 #include <sys/ioctl.h>
     24 #include <sys/mman.h>
     25 #include <sys/stat.h>
     26 #include <sys/types.h>
     27 #include <unistd.h>
     28 
     29 #include <cutils/ashmem.h>
     30 #include <cutils/atomic.h>
     31 #include <log/log.h>
     32 
     33 #include <hardware/gralloc.h>
     34 #include <hardware/hardware.h>
     35 
     36 #include "gralloc_priv.h"
     37 #include "gr.h"
     38 
     39 /*****************************************************************************/
     40 
     41 struct gralloc_context_t {
     42     alloc_device_t  device;
     43     /* our private data here */
     44 };
     45 
     46 static int gralloc_alloc_buffer(alloc_device_t* dev,
     47         size_t size, int usage, buffer_handle_t* pHandle);
     48 
     49 /*****************************************************************************/
     50 
     51 int fb_device_open(const hw_module_t* module, const char* name,
     52         hw_device_t** device);
     53 
     54 static int gralloc_device_open(const hw_module_t* module, const char* name,
     55         hw_device_t** device);
     56 
     57 extern int gralloc_lock(gralloc_module_t const* module,
     58         buffer_handle_t handle, int usage,
     59         int l, int t, int w, int h,
     60         void** vaddr);
     61 
     62 extern int gralloc_unlock(gralloc_module_t const* module,
     63         buffer_handle_t handle);
     64 
     65 extern int gralloc_register_buffer(gralloc_module_t const* module,
     66         buffer_handle_t handle);
     67 
     68 extern int gralloc_unregister_buffer(gralloc_module_t const* module,
     69         buffer_handle_t handle);
     70 
     71 /*****************************************************************************/
     72 
     73 static struct hw_module_methods_t gralloc_module_methods = {
     74         .open = gralloc_device_open
     75 };
     76 
     77 struct private_module_t HAL_MODULE_INFO_SYM = {
     78     .base = {
     79         .common = {
     80             .tag = HARDWARE_MODULE_TAG,
     81             .version_major = 1,
     82             .version_minor = 0,
     83             .id = GRALLOC_HARDWARE_MODULE_ID,
     84             .name = "Graphics Memory Allocator Module",
     85             .author = "The Android Open Source Project",
     86             .methods = &gralloc_module_methods
     87         },
     88         .registerBuffer = gralloc_register_buffer,
     89         .unregisterBuffer = gralloc_unregister_buffer,
     90         .lock = gralloc_lock,
     91         .unlock = gralloc_unlock,
     92     },
     93     .framebuffer = 0,
     94     .flags = 0,
     95     .numBuffers = 0,
     96     .bufferMask = 0,
     97     .lock = PTHREAD_MUTEX_INITIALIZER,
     98     .currentBuffer = 0,
     99 };
    100 
    101 /*****************************************************************************/
    102 
    103 static int gralloc_alloc_framebuffer_locked(alloc_device_t* dev,
    104         size_t size, int usage, buffer_handle_t* pHandle)
    105 {
    106     private_module_t* m = reinterpret_cast<private_module_t*>(
    107             dev->common.module);
    108 
    109     // allocate the framebuffer
    110     if (m->framebuffer == NULL) {
    111         // initialize the framebuffer, the framebuffer is mapped once
    112         // and forever.
    113         int err = mapFrameBufferLocked(m);
    114         if (err < 0) {
    115             return err;
    116         }
    117     }
    118 
    119     const uint32_t bufferMask = m->bufferMask;
    120     const uint32_t numBuffers = m->numBuffers;
    121     const size_t bufferSize = m->finfo.line_length * m->info.yres;
    122     if (numBuffers == 1) {
    123         // If we have only one buffer, we never use page-flipping. Instead,
    124         // we return a regular buffer which will be memcpy'ed to the main
    125         // screen when post is called.
    126         int newUsage = (usage & ~GRALLOC_USAGE_HW_FB) | GRALLOC_USAGE_HW_2D;
    127         return gralloc_alloc_buffer(dev, bufferSize, newUsage, pHandle);
    128     }
    129 
    130     if (bufferMask >= ((1LU<<numBuffers)-1)) {
    131         // We ran out of buffers.
    132         return -ENOMEM;
    133     }
    134 
    135     // create a "fake" handles for it
    136     intptr_t vaddr = intptr_t(m->framebuffer->base);
    137     private_handle_t* hnd = new private_handle_t(dup(m->framebuffer->fd), size,
    138             private_handle_t::PRIV_FLAGS_FRAMEBUFFER);
    139 
    140     // find a free slot
    141     for (uint32_t i=0 ; i<numBuffers ; i++) {
    142         if ((bufferMask & (1LU<<i)) == 0) {
    143             m->bufferMask |= (1LU<<i);
    144             break;
    145         }
    146         vaddr += bufferSize;
    147     }
    148 
    149     hnd->base = vaddr;
    150     hnd->offset = vaddr - intptr_t(m->framebuffer->base);
    151     *pHandle = hnd;
    152 
    153     return 0;
    154 }
    155 
    156 static int gralloc_alloc_framebuffer(alloc_device_t* dev,
    157         size_t size, int usage, buffer_handle_t* pHandle)
    158 {
    159     private_module_t* m = reinterpret_cast<private_module_t*>(
    160             dev->common.module);
    161     pthread_mutex_lock(&m->lock);
    162     int err = gralloc_alloc_framebuffer_locked(dev, size, usage, pHandle);
    163     pthread_mutex_unlock(&m->lock);
    164     return err;
    165 }
    166 
    167 static int gralloc_alloc_buffer(alloc_device_t* dev,
    168         size_t size, int /*usage*/, buffer_handle_t* pHandle)
    169 {
    170     int err = 0;
    171     int fd = -1;
    172 
    173     size = roundUpToPageSize(size);
    174 
    175     fd = ashmem_create_region("gralloc-buffer", size);
    176     if (fd < 0) {
    177         ALOGE("couldn't create ashmem (%s)", strerror(-errno));
    178         err = -errno;
    179     }
    180 
    181     if (err == 0) {
    182         private_handle_t* hnd = new private_handle_t(fd, size, 0);
    183         gralloc_module_t* module = reinterpret_cast<gralloc_module_t*>(
    184                 dev->common.module);
    185         err = mapBuffer(module, hnd);
    186         if (err == 0) {
    187             *pHandle = hnd;
    188         }
    189     }
    190 
    191     ALOGE_IF(err, "gralloc failed err=%s", strerror(-err));
    192 
    193     return err;
    194 }
    195 
    196 /*****************************************************************************/
    197 
    198 inline size_t align(size_t value, size_t alignment)
    199 {
    200     return ((value + alignment - 1) / alignment) * alignment;
    201 }
    202 
    203 static int gralloc_alloc(alloc_device_t* dev,
    204         int width, int height, int format, int usage,
    205         buffer_handle_t* pHandle, int* pStride)
    206 {
    207     if (!pHandle || !pStride)
    208         return -EINVAL;
    209 
    210     int bytesPerPixel = 0;
    211     switch (format) {
    212         case HAL_PIXEL_FORMAT_RGBA_FP16:
    213             bytesPerPixel = 8;
    214             break;
    215         case HAL_PIXEL_FORMAT_RGBA_8888:
    216         case HAL_PIXEL_FORMAT_RGBX_8888:
    217         case HAL_PIXEL_FORMAT_BGRA_8888:
    218             bytesPerPixel = 4;
    219             break;
    220         case HAL_PIXEL_FORMAT_RGB_888:
    221             bytesPerPixel = 3;
    222             break;
    223         case HAL_PIXEL_FORMAT_RGB_565:
    224         case HAL_PIXEL_FORMAT_RAW16:
    225             bytesPerPixel = 2;
    226             break;
    227         default:
    228             return -EINVAL;
    229     }
    230 
    231     const size_t tileWidth = 2;
    232     const size_t tileHeight = 2;
    233 
    234     size_t stride = align(width, tileWidth);
    235     size_t size = align(height, tileHeight) * stride * bytesPerPixel + 4;
    236 
    237     int err;
    238     if (usage & GRALLOC_USAGE_HW_FB) {
    239         err = gralloc_alloc_framebuffer(dev, size, usage, pHandle);
    240     } else {
    241         err = gralloc_alloc_buffer(dev, size, usage, pHandle);
    242     }
    243 
    244     if (err < 0) {
    245         return err;
    246     }
    247 
    248     *pStride = stride;
    249     return 0;
    250 }
    251 
    252 static int gralloc_free(alloc_device_t* dev,
    253         buffer_handle_t handle)
    254 {
    255     if (private_handle_t::validate(handle) < 0)
    256         return -EINVAL;
    257 
    258     private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(handle);
    259     if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
    260         // free this buffer
    261         private_module_t* m = reinterpret_cast<private_module_t*>(
    262                 dev->common.module);
    263         const size_t bufferSize = m->finfo.line_length * m->info.yres;
    264         int index = (hnd->base - m->framebuffer->base) / bufferSize;
    265         m->bufferMask &= ~(1<<index);
    266     } else {
    267         gralloc_module_t* module = reinterpret_cast<gralloc_module_t*>(
    268                 dev->common.module);
    269         terminateBuffer(module, const_cast<private_handle_t*>(hnd));
    270     }
    271 
    272     close(hnd->fd);
    273     delete hnd;
    274     return 0;
    275 }
    276 
    277 /*****************************************************************************/
    278 
    279 static int gralloc_close(struct hw_device_t *dev)
    280 {
    281     gralloc_context_t* ctx = reinterpret_cast<gralloc_context_t*>(dev);
    282     if (ctx) {
    283         /* TODO: keep a list of all buffer_handle_t created, and free them
    284          * all here.
    285          */
    286         free(ctx);
    287     }
    288     return 0;
    289 }
    290 
    291 int gralloc_device_open(const hw_module_t* module, const char* name,
    292         hw_device_t** device)
    293 {
    294     int status = -EINVAL;
    295     if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) {
    296         gralloc_context_t *dev;
    297         dev = (gralloc_context_t*)malloc(sizeof(*dev));
    298 
    299         /* initialize our state here */
    300         memset(dev, 0, sizeof(*dev));
    301 
    302         /* initialize the procs */
    303         dev->device.common.tag = HARDWARE_DEVICE_TAG;
    304         dev->device.common.version = 0;
    305         dev->device.common.module = const_cast<hw_module_t*>(module);
    306         dev->device.common.close = gralloc_close;
    307 
    308         dev->device.alloc   = gralloc_alloc;
    309         dev->device.free    = gralloc_free;
    310 
    311         *device = &dev->device.common;
    312         status = 0;
    313     } else {
    314         status = fb_device_open(module, name, device);
    315     }
    316     return status;
    317 }
    318