• 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 <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 "gralloc_priv.h"
38 #include "allocator.h"
39 
40 #if HAVE_ANDROID_OS
41 #include <linux/android_pmem.h>
42 #endif
43 
44 /*****************************************************************************/
45 
46 static SimpleBestFitAllocator sAllocator;
47 
48 /*****************************************************************************/
49 
50 struct gralloc_context_t {
51     alloc_device_t  device;
52     /* our private data here */
53 };
54 
55 static int gralloc_alloc_buffer(alloc_device_t* dev,
56         size_t size, int usage, buffer_handle_t* pHandle);
57 
58 /*****************************************************************************/
59 
60 int fb_device_open(const hw_module_t* module, const char* name,
61         hw_device_t** device);
62 
63 static int gralloc_device_open(const hw_module_t* module, const char* name,
64         hw_device_t** device);
65 
66 extern int gralloc_lock(gralloc_module_t const* module,
67         buffer_handle_t handle, int usage,
68         int l, int t, int w, int h,
69         void** vaddr);
70 
71 extern int gralloc_unlock(gralloc_module_t const* module,
72         buffer_handle_t handle);
73 
74 extern int gralloc_register_buffer(gralloc_module_t const* module,
75         buffer_handle_t handle);
76 
77 extern int gralloc_unregister_buffer(gralloc_module_t const* module,
78         buffer_handle_t handle);
79 
80 /*****************************************************************************/
81 
82 static struct hw_module_methods_t gralloc_module_methods = {
83         open: gralloc_device_open
84 };
85 
86 struct private_module_t HAL_MODULE_INFO_SYM = {
87     base: {
88         common: {
89             tag: HARDWARE_MODULE_TAG,
90             version_major: 1,
91             version_minor: 0,
92             id: GRALLOC_HARDWARE_MODULE_ID,
93             name: "Graphics Memory Allocator Module",
94             author: "The Android Open Source Project",
95             methods: &gralloc_module_methods
96         },
97         registerBuffer: gralloc_register_buffer,
98         unregisterBuffer: gralloc_unregister_buffer,
99         lock: gralloc_lock,
100         unlock: gralloc_unlock,
101     },
102     framebuffer: 0,
103     flags: 0,
104     numBuffers: 0,
105     bufferMask: 0,
106     lock: PTHREAD_MUTEX_INITIALIZER,
107     currentBuffer: 0,
108     pmem_master: -1,
109     pmem_master_base: 0
110 };
111 
112 /*****************************************************************************/
113 
gralloc_alloc_framebuffer_locked(alloc_device_t * dev,size_t size,int usage,buffer_handle_t * pHandle)114 static int gralloc_alloc_framebuffer_locked(alloc_device_t* dev,
115         size_t size, int usage, buffer_handle_t* pHandle)
116 {
117     private_module_t* m = reinterpret_cast<private_module_t*>(
118             dev->common.module);
119 
120     // allocate the framebuffer
121     if (m->framebuffer == NULL) {
122         // initialize the framebuffer, the framebuffer is mapped once
123         // and forever.
124         int err = mapFrameBufferLocked(m);
125         if (err < 0) {
126             return err;
127         }
128     }
129 
130     const uint32_t bufferMask = m->bufferMask;
131     const uint32_t numBuffers = m->numBuffers;
132     const size_t bufferSize = m->finfo.line_length * m->info.yres;
133     if (numBuffers == 1) {
134         // If we have only one buffer, we never use page-flipping. Instead,
135         // we return a regular buffer which will be memcpy'ed to the main
136         // screen when post is called.
137         int newUsage = (usage & ~GRALLOC_USAGE_HW_FB) | GRALLOC_USAGE_HW_2D;
138         return gralloc_alloc_buffer(dev, bufferSize, newUsage, pHandle);
139     }
140 
141     if (bufferMask >= ((1LU<<numBuffers)-1)) {
142         // We ran out of buffers.
143         return -ENOMEM;
144     }
145 
146     // create a "fake" handles for it
147     intptr_t vaddr = intptr_t(m->framebuffer->base);
148     private_handle_t* hnd = new private_handle_t(dup(m->framebuffer->fd), size,
149             private_handle_t::PRIV_FLAGS_USES_PMEM |
150             private_handle_t::PRIV_FLAGS_FRAMEBUFFER);
151 
152     // find a free slot
153     for (uint32_t i=0 ; i<numBuffers ; i++) {
154         if ((bufferMask & (1LU<<i)) == 0) {
155             m->bufferMask |= (1LU<<i);
156             break;
157         }
158         vaddr += bufferSize;
159     }
160 
161     hnd->base = vaddr;
162     hnd->offset = vaddr - intptr_t(m->framebuffer->base);
163     *pHandle = hnd;
164 
165     return 0;
166 }
167 
gralloc_alloc_framebuffer(alloc_device_t * dev,size_t size,int usage,buffer_handle_t * pHandle)168 static int gralloc_alloc_framebuffer(alloc_device_t* dev,
169         size_t size, int usage, buffer_handle_t* pHandle)
170 {
171     private_module_t* m = reinterpret_cast<private_module_t*>(
172             dev->common.module);
173     pthread_mutex_lock(&m->lock);
174     int err = gralloc_alloc_framebuffer_locked(dev, size, usage, pHandle);
175     pthread_mutex_unlock(&m->lock);
176     return err;
177 }
178 
init_pmem_area_locked(private_module_t * m)179 static int init_pmem_area_locked(private_module_t* m)
180 {
181     int err = 0;
182 #if HAVE_ANDROID_OS // should probably define HAVE_PMEM somewhere
183     int master_fd = open("/dev/pmem", O_RDWR, 0);
184     if (master_fd >= 0) {
185 
186         size_t size;
187         pmem_region region;
188         if (ioctl(master_fd, PMEM_GET_TOTAL_SIZE, &region) < 0) {
189             LOGE("PMEM_GET_TOTAL_SIZE failed, limp mode");
190             size = 8<<20;   // 8 MiB
191         } else {
192             size = region.len;
193         }
194         sAllocator.setSize(size);
195 
196         void* base = mmap(0, size,
197                 PROT_READ|PROT_WRITE, MAP_SHARED, master_fd, 0);
198         if (base == MAP_FAILED) {
199             err = -errno;
200             base = 0;
201             close(master_fd);
202             master_fd = -1;
203         }
204         m->pmem_master = master_fd;
205         m->pmem_master_base = base;
206     } else {
207         err = -errno;
208     }
209     return err;
210 #else
211     return -1;
212 #endif
213 }
214 
init_pmem_area(private_module_t * m)215 static int init_pmem_area(private_module_t* m)
216 {
217     pthread_mutex_lock(&m->lock);
218     int err = m->pmem_master;
219     if (err == -1) {
220         // first time, try to initialize pmem
221         err = init_pmem_area_locked(m);
222         if (err) {
223             m->pmem_master = err;
224         }
225     } else if (err < 0) {
226         // pmem couldn't be initialized, never use it
227     } else {
228         // pmem OK
229         err = 0;
230     }
231     pthread_mutex_unlock(&m->lock);
232     return err;
233 }
234 
gralloc_alloc_buffer(alloc_device_t * dev,size_t size,int usage,buffer_handle_t * pHandle)235 static int gralloc_alloc_buffer(alloc_device_t* dev,
236         size_t size, int usage, buffer_handle_t* pHandle)
237 {
238     int err = 0;
239     int flags = 0;
240 
241     int fd = -1;
242     void* base = 0;
243     int offset = 0;
244     int lockState = 0;
245 
246     size = roundUpToPageSize(size);
247 
248 #if HAVE_ANDROID_OS // should probably define HAVE_PMEM somewhere
249 
250     if (usage & GRALLOC_USAGE_HW_TEXTURE) {
251         // enable pmem in that case, so our software GL can fallback to
252         // the copybit module.
253         flags |= private_handle_t::PRIV_FLAGS_USES_PMEM;
254     }
255 
256     if (usage & GRALLOC_USAGE_HW_2D) {
257         flags |= private_handle_t::PRIV_FLAGS_USES_PMEM;
258     }
259 
260     if ((flags & private_handle_t::PRIV_FLAGS_USES_PMEM) == 0) {
261 try_ashmem:
262         fd = ashmem_create_region("gralloc-buffer", size);
263         if (fd < 0) {
264             LOGE("couldn't create ashmem (%s)", strerror(-errno));
265             err = -errno;
266         }
267     } else {
268         private_module_t* m = reinterpret_cast<private_module_t*>(
269                 dev->common.module);
270 
271         err = init_pmem_area(m);
272         if (err == 0) {
273             // PMEM buffers are always mmapped
274             base = m->pmem_master_base;
275             lockState |= private_handle_t::LOCK_STATE_MAPPED;
276 
277             offset = sAllocator.allocate(size);
278             if (offset < 0) {
279                 // no more pmem memory
280                 err = -ENOMEM;
281             } else {
282                 struct pmem_region sub = { offset, size };
283 
284                 // now create the "sub-heap"
285                 fd = open("/dev/pmem", O_RDWR, 0);
286                 err = fd < 0 ? fd : 0;
287 
288                 // and connect to it
289                 if (err == 0)
290                     err = ioctl(fd, PMEM_CONNECT, m->pmem_master);
291 
292                 // and make it available to the client process
293                 if (err == 0)
294                     err = ioctl(fd, PMEM_MAP, &sub);
295 
296                 if (err < 0) {
297                     err = -errno;
298                     close(fd);
299                     sAllocator.deallocate(offset);
300                     fd = -1;
301                 }
302                 //LOGD_IF(!err, "allocating pmem size=%d, offset=%d", size, offset);
303                 memset((char*)base + offset, 0, size);
304             }
305         } else {
306             if ((usage & GRALLOC_USAGE_HW_2D) == 0) {
307                 // the caller didn't request PMEM, so we can try something else
308                 flags &= ~private_handle_t::PRIV_FLAGS_USES_PMEM;
309                 err = 0;
310                 goto try_ashmem;
311             } else {
312                 LOGE("couldn't open pmem (%s)", strerror(-errno));
313             }
314         }
315     }
316 
317 #else // HAVE_ANDROID_OS
318 
319     fd = ashmem_create_region("Buffer", size);
320     if (fd < 0) {
321         LOGE("couldn't create ashmem (%s)", strerror(-errno));
322         err = -errno;
323     }
324 
325 #endif // HAVE_ANDROID_OS
326 
327     if (err == 0) {
328         private_handle_t* hnd = new private_handle_t(fd, size, flags);
329         hnd->offset = offset;
330         hnd->base = int(base)+offset;
331         hnd->lockState = lockState;
332         *pHandle = hnd;
333     }
334 
335     LOGE_IF(err, "gralloc failed err=%s", strerror(-err));
336 
337     return err;
338 }
339 
340 /*****************************************************************************/
341 
gralloc_alloc(alloc_device_t * dev,int w,int h,int format,int usage,buffer_handle_t * pHandle,int * pStride)342 static int gralloc_alloc(alloc_device_t* dev,
343         int w, int h, int format, int usage,
344         buffer_handle_t* pHandle, int* pStride)
345 {
346     if (!pHandle || !pStride)
347         return -EINVAL;
348 
349     size_t size, stride;
350     if (format == HAL_PIXEL_FORMAT_YCbCr_420_SP ||
351             format == HAL_PIXEL_FORMAT_YCbCr_422_SP)
352     {
353         // FIXME: there is no way to return the vstride
354         int vstride;
355         stride = (w + 1) & ~1;
356         switch (format) {
357             case HAL_PIXEL_FORMAT_YCbCr_420_SP:
358                 size = stride * h * 2;
359                 break;
360             case HAL_PIXEL_FORMAT_YCbCr_422_SP:
361                 vstride = (h+1) & ~1;
362                 size = (stride * vstride) + (w/2 * h/2) * 2;
363                 break;
364             default:
365                 return -EINVAL;
366         }
367     } else {
368         int align = 4;
369         int bpp = 0;
370         switch (format) {
371             case HAL_PIXEL_FORMAT_RGBA_8888:
372             case HAL_PIXEL_FORMAT_RGBX_8888:
373             case HAL_PIXEL_FORMAT_BGRA_8888:
374                 bpp = 4;
375                 break;
376             case HAL_PIXEL_FORMAT_RGB_888:
377                 bpp = 3;
378                 break;
379             case HAL_PIXEL_FORMAT_RGB_565:
380             case HAL_PIXEL_FORMAT_RGBA_5551:
381             case HAL_PIXEL_FORMAT_RGBA_4444:
382                 bpp = 2;
383                 break;
384             default:
385                 return -EINVAL;
386         }
387         size_t bpr = (w*bpp + (align-1)) & ~(align-1);
388         size = bpr * h;
389         stride = bpr / bpp;
390     }
391 
392     int err;
393     if (usage & GRALLOC_USAGE_HW_FB) {
394         err = gralloc_alloc_framebuffer(dev, size, usage, pHandle);
395     } else {
396         err = gralloc_alloc_buffer(dev, size, usage, pHandle);
397     }
398 
399     if (err < 0) {
400         return err;
401     }
402 
403     *pStride = stride;
404     return 0;
405 }
406 
gralloc_free(alloc_device_t * dev,buffer_handle_t handle)407 static int gralloc_free(alloc_device_t* dev,
408         buffer_handle_t handle)
409 {
410     if (private_handle_t::validate(handle) < 0)
411         return -EINVAL;
412 
413     private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(handle);
414     if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
415         // free this buffer
416         private_module_t* m = reinterpret_cast<private_module_t*>(
417                 dev->common.module);
418         const size_t bufferSize = m->finfo.line_length * m->info.yres;
419         int index = (hnd->base - m->framebuffer->base) / bufferSize;
420         m->bufferMask &= ~(1<<index);
421     } else {
422 #if HAVE_ANDROID_OS
423         if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_PMEM) {
424             if (hnd->fd >= 0) {
425                 struct pmem_region sub = { hnd->offset, hnd->size };
426                 int err = ioctl(hnd->fd, PMEM_UNMAP, &sub);
427                 LOGE_IF(err<0, "PMEM_UNMAP failed (%s), "
428                         "fd=%d, sub.offset=%lu, sub.size=%lu",
429                         strerror(errno), hnd->fd, hnd->offset, hnd->size);
430                 if (err == 0) {
431                     // we can't deallocate the memory in case of UNMAP failure
432                     // because it would give that process access to someone else's
433                     // surfaces, which would be a security breach.
434                     sAllocator.deallocate(hnd->offset);
435                 }
436             }
437         }
438 #endif // HAVE_ANDROID_OS
439         gralloc_module_t* module = reinterpret_cast<gralloc_module_t*>(
440                 dev->common.module);
441         terminateBuffer(module, const_cast<private_handle_t*>(hnd));
442     }
443 
444     close(hnd->fd);
445     delete hnd;
446     return 0;
447 }
448 
449 /*****************************************************************************/
450 
gralloc_close(struct hw_device_t * dev)451 static int gralloc_close(struct hw_device_t *dev)
452 {
453     gralloc_context_t* ctx = reinterpret_cast<gralloc_context_t*>(dev);
454     if (ctx) {
455         /* TODO: keep a list of all buffer_handle_t created, and free them
456          * all here.
457          */
458         free(ctx);
459     }
460     return 0;
461 }
462 
gralloc_device_open(const hw_module_t * module,const char * name,hw_device_t ** device)463 int gralloc_device_open(const hw_module_t* module, const char* name,
464         hw_device_t** device)
465 {
466     int status = -EINVAL;
467     if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) {
468         gralloc_context_t *dev;
469         dev = (gralloc_context_t*)malloc(sizeof(*dev));
470 
471         /* initialize our state here */
472         memset(dev, 0, sizeof(*dev));
473 
474         /* initialize the procs */
475         dev->device.common.tag = HARDWARE_DEVICE_TAG;
476         dev->device.common.version = 0;
477         dev->device.common.module = const_cast<hw_module_t*>(module);
478         dev->device.common.close = gralloc_close;
479 
480         dev->device.alloc   = gralloc_alloc;
481         dev->device.free    = gralloc_free;
482 
483         *device = &dev->device.common;
484         status = 0;
485     } else {
486         status = fb_device_open(module, name, device);
487     }
488     return status;
489 }
490