• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <cutils/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 #ifdef GRALLOC_MODULE_API_VERSION_0_2
199     VSOC_STATIC_INITIALIZER(perform) NULL,
200     VSOC_STATIC_INITIALIZER(lock_ycbcr) gralloc_lock_ycbcr,
201 #endif
202   },
203 };
204