• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
gralloc_alloc_framebuffer_locked(alloc_device_t * dev,size_t size,int format,int usage,buffer_handle_t * pHandle)103 static int gralloc_alloc_framebuffer_locked(alloc_device_t* dev,
104         size_t size, int format, 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, format);
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 
gralloc_alloc_framebuffer(alloc_device_t * dev,size_t size,int format,int usage,buffer_handle_t * pHandle)156 static int gralloc_alloc_framebuffer(alloc_device_t* dev,
157         size_t size, int format, 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, format, usage, pHandle);
163     pthread_mutex_unlock(&m->lock);
164     return err;
165 }
166 
gralloc_alloc_buffer(alloc_device_t * dev,size_t size,int,buffer_handle_t * pHandle)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 
align(size_t value,size_t alignment)198 inline size_t align(size_t value, size_t alignment)
199 {
200     return ((value + alignment - 1) / alignment) * alignment;
201 }
202 
gralloc_alloc(alloc_device_t * dev,int width,int height,int format,int usage,buffer_handle_t * pHandle,int * pStride)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         case HAL_PIXEL_FORMAT_BLOB:
228             bytesPerPixel = 1;
229             break;
230         default:
231             ALOGE("gralloc_alloc bad format %d", format);
232             return -EINVAL;
233     }
234 
235     const size_t tileWidth = 2;
236     const size_t tileHeight = 2;
237 
238     size_t stride = align(width, tileWidth);
239     size_t size = align(height, tileHeight) * stride * bytesPerPixel + 4;
240 
241     int err;
242     if (usage & GRALLOC_USAGE_HW_FB) {
243         err = gralloc_alloc_framebuffer(dev, size, format, usage, pHandle);
244     } else {
245         err = gralloc_alloc_buffer(dev, size, usage, pHandle);
246     }
247 
248     if (err < 0) {
249         return err;
250     }
251 
252     *pStride = stride;
253     return 0;
254 }
255 
gralloc_free(alloc_device_t * dev,buffer_handle_t handle)256 static int gralloc_free(alloc_device_t* dev,
257         buffer_handle_t handle)
258 {
259     if (private_handle_t::validate(handle) < 0)
260         return -EINVAL;
261 
262     private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(handle);
263     if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
264         // free this buffer
265         private_module_t* m = reinterpret_cast<private_module_t*>(
266                 dev->common.module);
267         const size_t bufferSize = m->finfo.line_length * m->info.yres;
268         int index = (hnd->base - m->framebuffer->base) / bufferSize;
269         m->bufferMask &= ~(1<<index);
270     } else {
271         gralloc_module_t* module = reinterpret_cast<gralloc_module_t*>(
272                 dev->common.module);
273         terminateBuffer(module, const_cast<private_handle_t*>(hnd));
274     }
275 
276     close(hnd->fd);
277     delete hnd;
278     return 0;
279 }
280 
281 /*****************************************************************************/
282 
gralloc_close(struct hw_device_t * dev)283 static int gralloc_close(struct hw_device_t *dev)
284 {
285     gralloc_context_t* ctx = reinterpret_cast<gralloc_context_t*>(dev);
286     if (ctx) {
287         /* TODO: keep a list of all buffer_handle_t created, and free them
288          * all here.
289          */
290         free(ctx);
291     }
292     return 0;
293 }
294 
gralloc_device_open(const hw_module_t * module,const char * name,hw_device_t ** device)295 int gralloc_device_open(const hw_module_t* module, const char* name,
296         hw_device_t** device)
297 {
298     int status = -EINVAL;
299     if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) {
300         gralloc_context_t *dev;
301         dev = (gralloc_context_t*)malloc(sizeof(*dev));
302 
303         /* initialize our state here */
304         memset(dev, 0, sizeof(*dev));
305 
306         /* initialize the procs */
307         dev->device.common.tag = HARDWARE_DEVICE_TAG;
308         dev->device.common.version = 0;
309         dev->device.common.module = const_cast<hw_module_t*>(module);
310         dev->device.common.close = gralloc_close;
311 
312         dev->device.alloc   = gralloc_alloc;
313         dev->device.free    = gralloc_free;
314 
315         *device = &dev->device.common;
316         status = 0;
317     } else {
318         status = fb_device_open(module, name, device);
319     }
320     return status;
321 }
322