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 <unistd.h>
     19 #include <fcntl.h>
     20 #include <errno.h>
     21 #include <pthread.h>
     22 #include <stdlib.h>
     23 #include <string.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/ashmem.h>
     31 #include <cutils/log.h>
     32 #include <cutils/atomic.h>
     33 
     34 #include <hardware/hardware.h>
     35 #include <hardware/gralloc.h>
     36 
     37 #include <linux/msm_hw3d.h>
     38 #include <linux/android_pmem.h>
     39 
     40 #include "gralloc_priv.h"
     41 #include "allocator.h"
     42 
     43 /*****************************************************************************/
     44 
     45 // NOTE: must be the same than in oem.h
     46 #define ALLOCATORREGION_RESERVED_SIZE           (1200<<10)
     47 #define FB_ARENA                                HW3D_EBI
     48 
     49 
     50 
     51 static SimpleBestFitAllocator sAllocator;
     52 static SimpleBestFitAllocator sAllocatorGPU(ALLOCATORREGION_RESERVED_SIZE);
     53 
     54 /*****************************************************************************/
     55 
     56 struct gralloc_context_t {
     57     alloc_device_t  device;
     58     /* our private data here */
     59 };
     60 
     61 static int gralloc_alloc_buffer(alloc_device_t* dev,
     62         size_t size, int usage, buffer_handle_t* pHandle);
     63 
     64 /*****************************************************************************/
     65 
     66 int fb_device_open(const hw_module_t* module, const char* name,
     67         hw_device_t** device);
     68 
     69 static int gralloc_device_open(const hw_module_t* module, const char* name,
     70         hw_device_t** device);
     71 
     72 extern int gralloc_lock(gralloc_module_t const* module,
     73         buffer_handle_t handle, int usage,
     74         int l, int t, int w, int h,
     75         void** vaddr);
     76 
     77 extern int gralloc_unlock(gralloc_module_t const* module,
     78         buffer_handle_t handle);
     79 
     80 extern int gralloc_register_buffer(gralloc_module_t const* module,
     81         buffer_handle_t handle);
     82 
     83 extern int gralloc_unregister_buffer(gralloc_module_t const* module,
     84         buffer_handle_t handle);
     85 
     86 extern int gralloc_perform(struct gralloc_module_t const* module,
     87         int operation, ... );
     88 
     89 /*****************************************************************************/
     90 
     91 static struct hw_module_methods_t gralloc_module_methods = {
     92         open: gralloc_device_open
     93 };
     94 
     95 struct private_module_t HAL_MODULE_INFO_SYM = {
     96     base: {
     97         common: {
     98             tag: HARDWARE_MODULE_TAG,
     99             version_major: 1,
    100             version_minor: 0,
    101             id: GRALLOC_HARDWARE_MODULE_ID,
    102             name: "Graphics Memory Allocator Module",
    103             author: "The Android Open Source Project",
    104             methods: &gralloc_module_methods
    105         },
    106         registerBuffer: gralloc_register_buffer,
    107         unregisterBuffer: gralloc_unregister_buffer,
    108         lock: gralloc_lock,
    109         unlock: gralloc_unlock,
    110         perform: gralloc_perform,
    111     },
    112     framebuffer: 0,
    113     flags: 0,
    114     numBuffers: 0,
    115     bufferMask: 0,
    116     lock: PTHREAD_MUTEX_INITIALIZER,
    117     currentBuffer: 0,
    118     pmem_master: -1,
    119     pmem_master_base: 0,
    120     master_phys: 0,
    121     gpu: -1,
    122     gpu_base: 0,
    123     fb_map_offset: 0
    124 };
    125 
    126 /*****************************************************************************/
    127 
    128 static int gralloc_alloc_framebuffer_locked(alloc_device_t* dev,
    129         size_t size, int usage, buffer_handle_t* pHandle)
    130 {
    131     private_module_t* m = reinterpret_cast<private_module_t*>(
    132             dev->common.module);
    133 
    134     // allocate the framebuffer
    135     if (m->framebuffer == NULL) {
    136         // initialize the framebuffer, the framebuffer is mapped once
    137         // and forever.
    138         int err = mapFrameBufferLocked(m);
    139         if (err < 0) {
    140             return err;
    141         }
    142     }
    143 
    144     const uint32_t bufferMask = m->bufferMask;
    145     const uint32_t numBuffers = m->numBuffers;
    146     const size_t bufferSize = m->finfo.line_length * m->info.yres;
    147     if (numBuffers == 1) {
    148         // If we have only one buffer, we never use page-flipping. Instead,
    149         // we return a regular buffer which will be memcpy'ed to the main
    150         // screen when post is called.
    151         int newUsage = (usage & ~GRALLOC_USAGE_HW_FB) | GRALLOC_USAGE_HW_2D;
    152         return gralloc_alloc_buffer(dev, bufferSize, newUsage, pHandle);
    153     }
    154 
    155     if (bufferMask >= ((1LU<<numBuffers)-1)) {
    156         // We ran out of buffers.
    157         return -ENOMEM;
    158     }
    159 
    160     // create a "fake" handles for it
    161     intptr_t vaddr = intptr_t(m->framebuffer->base);
    162     private_handle_t* hnd = new private_handle_t(dup(m->framebuffer->fd), size,
    163             private_handle_t::PRIV_FLAGS_USES_PMEM |
    164             private_handle_t::PRIV_FLAGS_FRAMEBUFFER);
    165 
    166     // find a free slot
    167     for (uint32_t i=0 ; i<numBuffers ; i++) {
    168         if ((bufferMask & (1LU<<i)) == 0) {
    169             m->bufferMask |= (1LU<<i);
    170             break;
    171         }
    172         vaddr += bufferSize;
    173     }
    174 
    175     hnd->base = vaddr;
    176     hnd->offset = vaddr - intptr_t(m->framebuffer->base);
    177     *pHandle = hnd;
    178 
    179     return 0;
    180 }
    181 
    182 static int gralloc_alloc_framebuffer(alloc_device_t* dev,
    183         size_t size, int usage, buffer_handle_t* pHandle)
    184 {
    185     private_module_t* m = reinterpret_cast<private_module_t*>(
    186             dev->common.module);
    187     pthread_mutex_lock(&m->lock);
    188     int err = gralloc_alloc_framebuffer_locked(dev, size, usage, pHandle);
    189     pthread_mutex_unlock(&m->lock);
    190     return err;
    191 }
    192 
    193 
    194 static int init_pmem_area_locked(private_module_t* m)
    195 {
    196     int err = 0;
    197     int master_fd = open("/dev/pmem", O_RDWR, 0);
    198     if (master_fd >= 0) {
    199 
    200         size_t size;
    201         pmem_region region;
    202         if (ioctl(master_fd, PMEM_GET_TOTAL_SIZE, &region) < 0) {
    203             LOGE("PMEM_GET_TOTAL_SIZE failed, limp mode");
    204             size = 8<<20;   // 8 MiB
    205         } else {
    206             size = region.len;
    207         }
    208         sAllocator.setSize(size);
    209 
    210         void* base = mmap(0, size,
    211                 PROT_READ|PROT_WRITE, MAP_SHARED, master_fd, 0);
    212         if (base == MAP_FAILED) {
    213             err = -errno;
    214             base = 0;
    215             close(master_fd);
    216             master_fd = -1;
    217         }
    218         m->pmem_master = master_fd;
    219         m->pmem_master_base = base;
    220     } else {
    221         err = -errno;
    222     }
    223     return err;
    224 }
    225 
    226 static int init_pmem_area(private_module_t* m)
    227 {
    228     pthread_mutex_lock(&m->lock);
    229     int err = m->pmem_master;
    230     if (err == -1) {
    231         // first time, try to initialize pmem
    232         err = init_pmem_area_locked(m);
    233         if (err) {
    234             m->pmem_master = err;
    235         }
    236     } else if (err < 0) {
    237         // pmem couldn't be initialized, never use it
    238     } else {
    239         // pmem OK
    240         err = 0;
    241     }
    242     pthread_mutex_unlock(&m->lock);
    243     return err;
    244 }
    245 
    246 static int init_gpu_area_locked(private_module_t* m)
    247 {
    248     int err = 0;
    249     int gpu = open("/dev/msm_hw3dm", O_RDWR, 0);
    250     LOGE_IF(gpu<0, "could not open hw3dm (%s)", strerror(errno));
    251     if (gpu >= 0) {
    252         struct hw3d_region regions[HW3D_NUM_REGIONS];
    253         if (ioctl(gpu, HW3D_GET_REGIONS, regions) < 0) {
    254             LOGE("HW3D_GET_REGIONS failed (%s)", strerror(errno));
    255             err = -errno;
    256         } else {
    257             LOGD("smi: offset=%08lx, len=%08lx, phys=%p",
    258                     regions[HW3D_SMI].map_offset,
    259                     regions[HW3D_SMI].len,
    260                     regions[HW3D_SMI].phys);
    261             LOGD("ebi: offset=%08lx, len=%08lx, phys=%p",
    262                     regions[HW3D_EBI].map_offset,
    263                     regions[HW3D_EBI].len,
    264                     regions[HW3D_EBI].phys);
    265             LOGD("reg: offset=%08lx, len=%08lx, phys=%p",
    266                     regions[HW3D_REGS].map_offset,
    267                     regions[HW3D_REGS].len,
    268                     regions[HW3D_REGS].phys);
    269 
    270             void* base = mmap(0, ALLOCATORREGION_RESERVED_SIZE,
    271                     PROT_READ|PROT_WRITE, MAP_SHARED,
    272                     gpu, regions[FB_ARENA].map_offset);
    273 
    274             if (base == MAP_FAILED) {
    275                 LOGE("mmap EBI1 (%s)", strerror(errno));
    276                 err = -errno;
    277                 base = 0;
    278                 close(gpu);
    279                 gpu = -1;
    280             }
    281 
    282             m->fb_map_offset = regions[FB_ARENA].map_offset;
    283             m->gpu = gpu;
    284             m->gpu_base = base;
    285         }
    286     } else {
    287         err = -errno;
    288         m->gpu = 0;
    289         m->gpu_base = 0;
    290     }
    291     return err;
    292 }
    293 
    294 static int init_gpu_area(private_module_t* m)
    295 {
    296     pthread_mutex_lock(&m->lock);
    297     int err = m->gpu;
    298     if (err == -1) {
    299         // first time, try to initialize gpu
    300         err = init_gpu_area_locked(m);
    301         if (err) {
    302             m->gpu = err;
    303         }
    304     } else if (err < 0) {
    305         // gpu couldn't be initialized, never use it
    306     } else {
    307         // gpu OK
    308         err = 0;
    309     }
    310     pthread_mutex_unlock(&m->lock);
    311     return err;
    312 }
    313 
    314 static int gralloc_alloc_buffer(alloc_device_t* dev,
    315         size_t size, int usage, buffer_handle_t* pHandle)
    316 {
    317     int err = 0;
    318     int flags = 0;
    319 
    320     int fd = -1;
    321     int gpu_fd = -1;
    322     void* base = 0;
    323     int offset = 0;
    324 
    325     size = roundUpToPageSize(size);
    326 
    327     if (usage & GRALLOC_USAGE_HW_TEXTURE) {
    328         // enable pmem in that case, so our software GL can fallback to
    329         // the copybit module.
    330         flags |= private_handle_t::PRIV_FLAGS_USES_PMEM;
    331     }
    332 
    333     if (usage & GRALLOC_USAGE_HW_2D) {
    334         flags |= private_handle_t::PRIV_FLAGS_USES_PMEM;
    335     }
    336 
    337     if ((flags & private_handle_t::PRIV_FLAGS_USES_PMEM) == 0) {
    338 try_ashmem:
    339         fd = ashmem_create_region("gralloc-buffer", size);
    340         if (fd < 0) {
    341             LOGE("couldn't create ashmem (%s)", strerror(errno));
    342             err = -errno;
    343         }
    344     } else if ((usage & GRALLOC_USAGE_HW_RENDER) == 0) {
    345         private_module_t* m = reinterpret_cast<private_module_t*>(
    346                 dev->common.module);
    347 
    348         err = init_pmem_area(m);
    349         if (err == 0) {
    350             // PMEM buffers are always mmapped
    351             base = m->pmem_master_base;
    352             offset = sAllocator.allocate(size);
    353             if (offset < 0) {
    354                 // no more pmem memory
    355                 err = -ENOMEM;
    356             } else {
    357                 struct pmem_region sub = { offset, size };
    358 
    359                 // now create the "sub-heap"
    360                 fd = open("/dev/pmem", O_RDWR, 0);
    361                 err = fd < 0 ? fd : 0;
    362 
    363                 // and connect to it
    364                 if (err == 0)
    365                     err = ioctl(fd, PMEM_CONNECT, m->pmem_master);
    366 
    367                 // and make it available to the client process
    368                 if (err == 0)
    369                     err = ioctl(fd, PMEM_MAP, &sub);
    370 
    371                 if (err < 0) {
    372                     err = -errno;
    373                     close(fd);
    374                     sAllocator.deallocate(offset);
    375                     fd = -1;
    376                 }
    377                 memset((char*)base + offset, 0, size);
    378                 //LOGD_IF(!err, "allocating pmem size=%d, offset=%d", size, offset);
    379             }
    380         } else {
    381             if ((usage & GRALLOC_USAGE_HW_2D) == 0) {
    382                 // the caller didn't request PMEM, so we can try something else
    383                 flags &= ~private_handle_t::PRIV_FLAGS_USES_PMEM;
    384                 err = 0;
    385                 goto try_ashmem;
    386             } else {
    387                 LOGE("couldn't open pmem (%s)", strerror(errno));
    388             }
    389         }
    390     } else {
    391         // looks like we want 3D...
    392         flags &= ~private_handle_t::PRIV_FLAGS_USES_PMEM;
    393         flags |= private_handle_t::PRIV_FLAGS_USES_GPU;
    394 
    395         private_module_t* m = reinterpret_cast<private_module_t*>(
    396                 dev->common.module);
    397 
    398         err = init_gpu_area(m);
    399         if (err == 0) {
    400             // GPU buffers are always mmapped
    401             base = m->gpu_base;
    402 
    403             // When a process holding GPU surfaces gets killed, it may take
    404             // up to a few seconds until SurfaceFlinger is notified and can
    405             // release the memory. So it's useful to wait a little bit here.
    406             long sleeptime = 0;
    407             int retry = 8; // roughly 5 seconds
    408             do {
    409                 offset = sAllocatorGPU.allocate(size);
    410                 if (offset < 0) {
    411                     // no more pmem memory
    412                     LOGW("%d KiB allocation failed in GPU memory, retrying...",
    413                             size/1024);
    414                     err = -ENOMEM;
    415                     sleeptime += 250000;
    416                     usleep(sleeptime);
    417                 } else {
    418                     LOGD("allocating GPU size=%d, offset=%d", size, offset);
    419                     fd = open("/dev/null", O_RDONLY); // just so marshalling doesn't fail
    420                     gpu_fd = m->gpu;
    421                     memset((char*)base + offset, 0, size);
    422                     err = 0;
    423                 }
    424             } while ((err == -ENOMEM) && (retry-- > 0));
    425 
    426         } else {
    427             // not enough memory, try ashmem
    428             flags &= ~private_handle_t::PRIV_FLAGS_USES_GPU;
    429             err = 0;
    430             goto try_ashmem;
    431         }
    432     }
    433 
    434     if (err == 0) {
    435         private_handle_t* hnd = new private_handle_t(fd, size, flags);
    436         if (base == NULL) {
    437             gralloc_module_t* module = reinterpret_cast<gralloc_module_t*>(
    438                     dev->common.module);
    439             err = mapBuffer(module, hnd);
    440             if (err == 0) {
    441                 *pHandle = hnd;
    442             }
    443         } else {
    444             private_module_t* m = reinterpret_cast<private_module_t*>(
    445                     dev->common.module);
    446             hnd->offset = offset;
    447             hnd->base = int(base)+offset;
    448             hnd->gpu_fd = gpu_fd;
    449             hnd->map_offset = m->fb_map_offset;
    450             *pHandle = hnd;
    451         }
    452     }
    453 
    454     LOGE_IF(err, "gralloc failed err=%s", strerror(-err));
    455 
    456     return err;
    457 }
    458 
    459 /*****************************************************************************/
    460 
    461 static int gralloc_alloc(alloc_device_t* dev,
    462         int w, int h, int format, int usage,
    463         buffer_handle_t* pHandle, int* pStride)
    464 {
    465     if (!pHandle || !pStride)
    466         return -EINVAL;
    467 
    468     size_t size, stride;
    469 
    470     int bpp = 0;
    471     switch (format) {
    472         case HAL_PIXEL_FORMAT_RGBA_8888:
    473         case HAL_PIXEL_FORMAT_RGBX_8888:
    474         case HAL_PIXEL_FORMAT_BGRA_8888:
    475             bpp = 4;
    476             break;
    477         case HAL_PIXEL_FORMAT_RGB_888:
    478             bpp = 3;
    479             break;
    480         case HAL_PIXEL_FORMAT_RGB_565:
    481         case HAL_PIXEL_FORMAT_RGBA_5551:
    482         case HAL_PIXEL_FORMAT_RGBA_4444:
    483             bpp = 2;
    484             break;
    485         default:
    486             return -EINVAL;
    487     }
    488 
    489     if (usage & GRALLOC_USAGE_HW_RENDER) {
    490         /* buffers MUST be aligned to the NEXT 8 pixels multiple any other
    491          * alignments will fail do to assumptions in the driver */
    492         const int pixelAlignment = 8;
    493         const int mask = pixelAlignment - 1;
    494         stride = (w + mask) & ~mask;
    495         size = stride * h * bpp;
    496     } else {
    497         const int align = 4;
    498         size_t bpr = (w*bpp + (align-1)) & ~(align-1);
    499         size = bpr * h;
    500         stride = bpr / bpp;
    501     }
    502 
    503     int err;
    504     if (usage & GRALLOC_USAGE_HW_FB) {
    505         err = gralloc_alloc_framebuffer(dev, size, usage, pHandle);
    506     } else {
    507         err = gralloc_alloc_buffer(dev, size, usage, pHandle);
    508     }
    509 
    510     if (err < 0) {
    511         return err;
    512     }
    513 
    514     *pStride = stride;
    515     return 0;
    516 }
    517 
    518 static int gralloc_free(alloc_device_t* dev,
    519         buffer_handle_t handle)
    520 {
    521     if (private_handle_t::validate(handle) < 0)
    522         return -EINVAL;
    523 
    524     private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(handle);
    525     if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
    526         // free this buffer
    527         private_module_t* m = reinterpret_cast<private_module_t*>(
    528                 dev->common.module);
    529         const size_t bufferSize = m->finfo.line_length * m->info.yres;
    530         int index = (hnd->base - m->framebuffer->base) / bufferSize;
    531         m->bufferMask &= ~(1<<index);
    532     } else {
    533         if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_PMEM) {
    534             if (hnd->fd >= 0) {
    535                 struct pmem_region sub = { hnd->offset, hnd->size };
    536                 int err = ioctl(hnd->fd, PMEM_UNMAP, &sub);
    537                 LOGE_IF(err<0, "PMEM_UNMAP failed (%s), "
    538                         "fd=%d, sub.offset=%lu, sub.size=%lu",
    539                         strerror(errno), hnd->fd, hnd->offset, hnd->size);
    540                 if (err == 0) {
    541                     // we can't deallocate the memory in case of UNMAP failure
    542                     // because it would give that process access to someone else's
    543                     // surfaces, which would be a security breach.
    544                     sAllocator.deallocate(hnd->offset);
    545                 }
    546             }
    547         } else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_GPU) {
    548             LOGD("freeing GPU buffer at %d", hnd->offset);
    549             sAllocatorGPU.deallocate(hnd->offset);
    550         }
    551 
    552         gralloc_module_t* module = reinterpret_cast<gralloc_module_t*>(
    553                 dev->common.module);
    554         terminateBuffer(module, const_cast<private_handle_t*>(hnd));
    555     }
    556 
    557     close(hnd->fd);
    558     delete hnd;
    559     return 0;
    560 }
    561 
    562 /*****************************************************************************/
    563 
    564 static int gralloc_close(struct hw_device_t *dev)
    565 {
    566     gralloc_context_t* ctx = reinterpret_cast<gralloc_context_t*>(dev);
    567     if (ctx) {
    568         /* TODO: keep a list of all buffer_handle_t created, and free them
    569          * all here.
    570          */
    571         free(ctx);
    572     }
    573     return 0;
    574 }
    575 
    576 int gralloc_device_open(const hw_module_t* module, const char* name,
    577         hw_device_t** device)
    578 {
    579     int status = -EINVAL;
    580     if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) {
    581         gralloc_context_t *dev;
    582         dev = (gralloc_context_t*)malloc(sizeof(*dev));
    583 
    584         /* initialize our state here */
    585         memset(dev, 0, sizeof(*dev));
    586 
    587         /* initialize the procs */
    588         dev->device.common.tag = HARDWARE_DEVICE_TAG;
    589         dev->device.common.version = 0;
    590         dev->device.common.module = const_cast<hw_module_t*>(module);
    591         dev->device.common.close = gralloc_close;
    592 
    593         dev->device.alloc   = gralloc_alloc;
    594         dev->device.free    = gralloc_free;
    595 
    596         *device = &dev->device.common;
    597         status = 0;
    598     } else {
    599         status = fb_device_open(module, name, device);
    600     }
    601     return status;
    602 }
    603