Home | History | Annotate | Download | only in legacy
      1 /*
      2  * Copyright (C) 2016 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 #include <limits.h>
     17 #include <unistd.h>
     18 #include <fcntl.h>
     19 #include <errno.h>
     20 #include <pthread.h>
     21 #include <stdlib.h>
     22 #include <string.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/ashmem.h>
     30 #include <log/log.h>
     31 #include <cutils/atomic.h>
     32 #include <utils/String8.h>
     33 
     34 #include <hardware/hardware.h>
     35 #include <hardware/gralloc.h>
     36 
     37 #include <guest/libs/platform_support/api_level_fixes.h>
     38 
     39 #include "common/libs/auto_resources/auto_resources.h"
     40 #include "common/vsoc/lib/screen_region_view.h"
     41 #include "gralloc_vsoc_priv.h"
     42 #include "region_registry.h"
     43 
     44 using vsoc::screen::ScreenRegionView;
     45 
     46 /*****************************************************************************/
     47 
     48 static inline size_t roundUpToPageSize(size_t x) {
     49   return (x + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1);
     50 }
     51 
     52 static int gralloc_alloc_buffer(
     53     alloc_device_t* /*dev*/, int format, int w, int h,
     54     buffer_handle_t* pHandle, int* pStrideInPixels) {
     55   int err = 0;
     56   int fd = -1;
     57   static int sequence = 0;
     58 
     59   int bytes_per_pixel = formatToBytesPerPixel(format);
     60   int bytes_per_line;
     61   int stride_in_pixels;
     62   int size = 0;
     63   // SwiftShader can't handle RGB_888, so fail fast and hard if we try to create
     64   // a gralloc buffer in this format.
     65   ALOG_ASSERT(format != HAL_PIXEL_FORMAT_RGB_888);
     66   if (format == HAL_PIXEL_FORMAT_YV12) {
     67     bytes_per_line = ScreenRegionView::align(bytes_per_pixel * w, 16);
     68   } else {
     69     bytes_per_line = ScreenRegionView::align(bytes_per_pixel * w);
     70   }
     71   size = roundUpToPageSize(size + formatToBytesPerFrame(format, w, h));
     72   size += PAGE_SIZE;
     73   fd = ashmem_create_region(
     74       android::String8::format(
     75           "gralloc-%d.%d", getpid(), sequence++).string(),
     76       size);
     77   if (fd < 0) {
     78     ALOGE("couldn't create ashmem (%s)", strerror(-errno));
     79     err = -errno;
     80   }
     81 
     82   if (err == 0) {
     83     stride_in_pixels = bytes_per_line / bytes_per_pixel;
     84     private_handle_t* hnd =
     85         new private_handle_t(fd, size, format, w, h, stride_in_pixels, 0);
     86     void* base = reference_region(__FUNCTION__, hnd);
     87     if (base) {
     88       *pHandle = hnd;
     89       *pStrideInPixels = stride_in_pixels;
     90     } else {
     91       err = -EIO;
     92     }
     93   }
     94 
     95   ALOGE_IF(err, "gralloc failed err=%s", strerror(-err));
     96 
     97   return err;
     98 }
     99 
    100 /*****************************************************************************/
    101 
    102 static int gralloc_alloc(alloc_device_t* dev, int w, int h, int format,
    103                          int /*usage*/, buffer_handle_t* pHandle,
    104                          int* pStrideInPixels) {
    105   if (!pHandle || !pStrideInPixels)
    106     return -EINVAL;
    107 
    108   int err = gralloc_alloc_buffer(dev, format, w, h, pHandle, pStrideInPixels);
    109 
    110   if (err < 0) {
    111     return err;
    112   }
    113   return 0;
    114 }
    115 
    116 static int gralloc_free(alloc_device_t* /*dev*/, buffer_handle_t handle) {
    117   if (private_handle_t::validate(handle) < 0) {
    118     return -EINVAL;
    119   }
    120 
    121   private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(
    122     handle);
    123   int retval = unreference_region(__FUNCTION__, hnd);
    124 
    125   close(hnd->fd);
    126   delete hnd;
    127   return retval;
    128 }
    129 
    130 /*****************************************************************************/
    131 
    132 static int gralloc_close(struct hw_device_t *dev) {
    133   priv_alloc_device_t* ctx = reinterpret_cast<priv_alloc_device_t*>(dev);
    134   if (ctx) {
    135     /* TODO: keep a list of all buffer_handle_t created, and free them
    136      * all here.
    137      */
    138     free(ctx);
    139   }
    140   return 0;
    141 }
    142 
    143 static int gralloc_device_open(
    144     const hw_module_t* module, const char* name, hw_device_t** device) {
    145   int status = -EINVAL;
    146   if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) {
    147     priv_alloc_device_t *dev;
    148     dev = (priv_alloc_device_t*) malloc(sizeof(*dev));
    149     LOG_FATAL_IF(!dev, "%s: malloc returned NULL.", __FUNCTION__);
    150 
    151     /* initialize our state here */
    152     memset(dev, 0, sizeof(*dev));
    153 
    154     /* initialize the procs */
    155     dev->device.common.tag = HARDWARE_DEVICE_TAG;
    156     dev->device.common.version = 0;
    157     dev->device.common.module = const_cast<hw_module_t*>(module);
    158     dev->device.common.close = gralloc_close;
    159 
    160     dev->device.alloc   = gralloc_alloc;
    161     dev->device.free    = gralloc_free;
    162 
    163     *device = &dev->device.common;
    164     status = 0;
    165   } else {
    166     status = fb_device_open(module, name, device);
    167   }
    168   return status;
    169 }
    170 
    171 /*****************************************************************************/
    172 
    173 static struct hw_module_methods_t gralloc_module_methods = {
    174   VSOC_STATIC_INITIALIZER(open) gralloc_device_open
    175 };
    176 
    177 struct private_module_t HAL_MODULE_INFO_SYM = {
    178   VSOC_STATIC_INITIALIZER(base) {
    179     VSOC_STATIC_INITIALIZER(common) {
    180       VSOC_STATIC_INITIALIZER(tag) HARDWARE_MODULE_TAG,
    181 #ifdef GRALLOC_MODULE_API_VERSION_0_2
    182       VSOC_STATIC_INITIALIZER(version_major) GRALLOC_MODULE_API_VERSION_0_2,
    183 #else
    184       VSOC_STATIC_INITIALIZER(version_major) 1,
    185 #endif
    186       VSOC_STATIC_INITIALIZER(version_minor) 0,
    187       VSOC_STATIC_INITIALIZER(id) GRALLOC_HARDWARE_MODULE_ID,
    188       VSOC_STATIC_INITIALIZER(name) "VSOC X86 Graphics Memory Allocator Module",
    189       VSOC_STATIC_INITIALIZER(author) "The Android Open Source Project",
    190       VSOC_STATIC_INITIALIZER(methods) &gralloc_module_methods,
    191       VSOC_STATIC_INITIALIZER(dso) NULL,
    192       VSOC_STATIC_INITIALIZER(reserved) {0},
    193     },
    194     VSOC_STATIC_INITIALIZER(registerBuffer) gralloc_register_buffer,
    195     VSOC_STATIC_INITIALIZER(unregisterBuffer) gralloc_unregister_buffer,
    196     VSOC_STATIC_INITIALIZER(lock) gralloc_lock,
    197     VSOC_STATIC_INITIALIZER(unlock) gralloc_unlock,
    198     VSOC_STATIC_INITIALIZER(validateBufferSize) NULL,
    199     VSOC_STATIC_INITIALIZER(getTransportSize) NULL,
    200 #ifdef GRALLOC_MODULE_API_VERSION_0_2
    201     VSOC_STATIC_INITIALIZER(perform) NULL,
    202     VSOC_STATIC_INITIALIZER(lock_ycbcr) gralloc_lock_ycbcr,
    203 #endif
    204   },
    205 };
    206