1 /*
2 * Copyright (C) 2011 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 <string.h>
17 #include <pthread.h>
18 #ifdef HAVE_ANDROID_OS // just want PAGE_SIZE define
19 # include <asm/page.h>
20 #else
21 # include <sys/user.h>
22 #endif
23 #include <cutils/ashmem.h>
24 #include <unistd.h>
25 #include <errno.h>
26 #include <dlfcn.h>
27 #include <sys/mman.h>
28 #include "gralloc_cb.h"
29 #include "HostConnection.h"
30 #include "glUtils.h"
31 #include <cutils/log.h>
32 #include <cutils/properties.h>
33
34 /* Set to 1 or 2 to enable debug traces */
35 #define DEBUG 0
36
37 #if DEBUG >= 1
38 # define D(...) ALOGD(__VA_ARGS__)
39 #else
40 # define D(...) ((void)0)
41 #endif
42
43 #if DEBUG >= 2
44 # define DD(...) ALOGD(__VA_ARGS__)
45 #else
46 # define DD(...) ((void)0)
47 #endif
48
49 #define DBG_FUNC DBG("%s\n", __FUNCTION__)
50 //
51 // our private gralloc module structure
52 //
53 struct private_module_t {
54 gralloc_module_t base;
55 };
56
57 /* If not NULL, this is a pointer to the fallback module.
58 * This really is gralloc.default, which we'll use if we detect
59 * that the emulator we're running in does not support GPU emulation.
60 */
61 static gralloc_module_t* sFallback;
62 static pthread_once_t sFallbackOnce = PTHREAD_ONCE_INIT;
63
64 static void fallback_init(void); // forward
65
66
67 typedef struct _alloc_list_node {
68 buffer_handle_t handle;
69 _alloc_list_node *next;
70 _alloc_list_node *prev;
71 } AllocListNode;
72
73 //
74 // Our gralloc device structure (alloc interface)
75 //
76 struct gralloc_device_t {
77 alloc_device_t device;
78
79 AllocListNode *allocListHead; // double linked list of allocated buffers
80 pthread_mutex_t lock;
81 };
82
83 //
84 // Our framebuffer device structure
85 //
86 struct fb_device_t {
87 framebuffer_device_t device;
88 };
89
map_buffer(cb_handle_t * cb,void ** vaddr)90 static int map_buffer(cb_handle_t *cb, void **vaddr)
91 {
92 if (cb->fd < 0 || cb->ashmemSize <= 0) {
93 return -EINVAL;
94 }
95
96 void *addr = mmap(0, cb->ashmemSize, PROT_READ | PROT_WRITE,
97 MAP_SHARED, cb->fd, 0);
98 if (addr == MAP_FAILED) {
99 return -errno;
100 }
101
102 cb->ashmemBase = intptr_t(addr);
103 cb->ashmemBasePid = getpid();
104
105 *vaddr = addr;
106 return 0;
107 }
108
109 #define DEFINE_HOST_CONNECTION \
110 HostConnection *hostCon = HostConnection::get(); \
111 renderControl_encoder_context_t *rcEnc = (hostCon ? hostCon->rcEncoder() : NULL)
112
113 #define DEFINE_AND_VALIDATE_HOST_CONNECTION \
114 HostConnection *hostCon = HostConnection::get(); \
115 if (!hostCon) { \
116 ALOGE("gralloc: Failed to get host connection\n"); \
117 return -EIO; \
118 } \
119 renderControl_encoder_context_t *rcEnc = hostCon->rcEncoder(); \
120 if (!rcEnc) { \
121 ALOGE("gralloc: Failed to get renderControl encoder context\n"); \
122 return -EIO; \
123 }
124
125
126 //
127 // gralloc device functions (alloc interface)
128 //
gralloc_alloc(alloc_device_t * dev,int w,int h,int format,int usage,buffer_handle_t * pHandle,int * pStride)129 static int gralloc_alloc(alloc_device_t* dev,
130 int w, int h, int format, int usage,
131 buffer_handle_t* pHandle, int* pStride)
132 {
133 D("gralloc_alloc w=%d h=%d usage=0x%x\n", w, h, usage);
134
135 gralloc_device_t *grdev = (gralloc_device_t *)dev;
136 if (!grdev || !pHandle || !pStride)
137 return -EINVAL;
138
139 //
140 // Validate usage: buffer cannot be written both by s/w and h/w access.
141 //
142 bool sw_write = (0 != (usage & GRALLOC_USAGE_SW_WRITE_MASK));
143 bool hw_write = (usage & GRALLOC_USAGE_HW_RENDER);
144 if (hw_write && sw_write) {
145 return -EINVAL;
146 }
147 bool sw_read = (0 != (usage & GRALLOC_USAGE_SW_READ_MASK));
148
149 int ashmem_size = 0;
150 int stride = w;
151
152 GLenum glFormat = 0;
153 GLenum glType = 0;
154
155 int bpp = 0;
156 int align = 1;
157 switch (format) {
158 case HAL_PIXEL_FORMAT_RGBA_8888:
159 case HAL_PIXEL_FORMAT_RGBX_8888:
160 case HAL_PIXEL_FORMAT_BGRA_8888:
161 bpp = 4;
162 glFormat = GL_RGBA;
163 glType = GL_UNSIGNED_BYTE;
164 break;
165 case HAL_PIXEL_FORMAT_RGB_888:
166 bpp = 3;
167 glFormat = GL_RGB;
168 glType = GL_UNSIGNED_BYTE;
169 break;
170 case HAL_PIXEL_FORMAT_RGB_565:
171 bpp = 2;
172 glFormat = GL_RGB;
173 glType = GL_UNSIGNED_SHORT_5_6_5;
174 break;
175 case HAL_PIXEL_FORMAT_RGBA_5551:
176 bpp = 2;
177 glFormat = GL_RGB5_A1_OES;
178 glType = GL_UNSIGNED_SHORT_5_5_5_1;
179 break;
180 case HAL_PIXEL_FORMAT_RGBA_4444:
181 bpp = 2;
182 glFormat = GL_RGBA4_OES;
183 glType = GL_UNSIGNED_SHORT_4_4_4_4;
184 break;
185 case HAL_PIXEL_FORMAT_RAW_SENSOR:
186 bpp = 2;
187 align = 16*bpp;
188 if (! (sw_read && sw_write) ) {
189 // Raw sensor data cannot be used by HW
190 return -EINVAL;
191 }
192 glFormat = GL_LUMINANCE;
193 glType = GL_UNSIGNED_SHORT;
194 break;
195 default:
196 return -EINVAL;
197 }
198
199 if (usage & GRALLOC_USAGE_HW_FB) {
200 // keep space for postCounter
201 ashmem_size += sizeof(uint32_t);
202 }
203
204 if (sw_read || sw_write) {
205 // keep space for image on guest memory if SW access is needed
206
207 size_t bpr = (w*bpp + (align-1)) & ~(align-1);
208 ashmem_size += (bpr * h);
209 stride = bpr / bpp;
210 }
211
212 D("gralloc_alloc ashmem_size=%d, stride=%d, tid %d\n", ashmem_size, stride,
213 gettid());
214
215 //
216 // Allocate space in ashmem if needed
217 //
218 int fd = -1;
219 if (ashmem_size > 0) {
220 // round to page size;
221 ashmem_size = (ashmem_size + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1);
222
223 fd = ashmem_create_region("gralloc-buffer", ashmem_size);
224 if (fd < 0) {
225 ALOGE("gralloc_alloc failed to create ashmem region: %s\n",
226 strerror(errno));
227 return -errno;
228 }
229 }
230
231 cb_handle_t *cb = new cb_handle_t(fd, ashmem_size, usage,
232 w, h, glFormat, glType);
233
234 if (ashmem_size > 0) {
235 //
236 // map ashmem region if exist
237 //
238 void *vaddr;
239 int err = map_buffer(cb, &vaddr);
240 if (err) {
241 close(fd);
242 delete cb;
243 return err;
244 }
245
246 cb->setFd(fd);
247 }
248
249 //
250 // Allocate ColorBuffer handle on the host (only if h/w access is allowed)
251 //
252 if (usage & GRALLOC_USAGE_HW_MASK) {
253 DEFINE_HOST_CONNECTION;
254 if (hostCon && rcEnc) {
255 cb->hostHandle = rcEnc->rcCreateColorBuffer(rcEnc, w, h, glFormat);
256 D("Created host ColorBuffer 0x%x\n", cb->hostHandle);
257 }
258
259 if (!cb->hostHandle) {
260 // Could not create colorbuffer on host !!!
261 close(fd);
262 delete cb;
263 return -EIO;
264 }
265 }
266
267 //
268 // alloc succeeded - insert the allocated handle to the allocated list
269 //
270 AllocListNode *node = new AllocListNode();
271 pthread_mutex_lock(&grdev->lock);
272 node->handle = cb;
273 node->next = grdev->allocListHead;
274 node->prev = NULL;
275 if (grdev->allocListHead) {
276 grdev->allocListHead->prev = node;
277 }
278 grdev->allocListHead = node;
279 pthread_mutex_unlock(&grdev->lock);
280
281 *pHandle = cb;
282 *pStride = stride;
283 return 0;
284 }
285
gralloc_free(alloc_device_t * dev,buffer_handle_t handle)286 static int gralloc_free(alloc_device_t* dev,
287 buffer_handle_t handle)
288 {
289 const cb_handle_t *cb = (const cb_handle_t *)handle;
290 if (!cb_handle_t::validate((cb_handle_t*)cb)) {
291 ERR("gralloc_free: invalid handle");
292 return -EINVAL;
293 }
294
295 if (cb->hostHandle != 0) {
296 DEFINE_AND_VALIDATE_HOST_CONNECTION;
297 D("Closing host ColorBuffer 0x%x\n", cb->hostHandle);
298 rcEnc->rcCloseColorBuffer(rcEnc, cb->hostHandle);
299 }
300
301 //
302 // detach and unmap ashmem area if present
303 //
304 if (cb->fd > 0) {
305 if (cb->ashmemSize > 0 && cb->ashmemBase) {
306 munmap((void *)cb->ashmemBase, cb->ashmemSize);
307 }
308 close(cb->fd);
309 }
310
311 // remove it from the allocated list
312 gralloc_device_t *grdev = (gralloc_device_t *)dev;
313 pthread_mutex_lock(&grdev->lock);
314 AllocListNode *n = grdev->allocListHead;
315 while( n && n->handle != cb ) {
316 n = n->next;
317 }
318 if (n) {
319 // buffer found on list - remove it from list
320 if (n->next) {
321 n->next->prev = n->prev;
322 }
323 if (n->prev) {
324 n->prev->next = n->next;
325 }
326 else {
327 grdev->allocListHead = n->next;
328 }
329
330 delete n;
331 }
332 pthread_mutex_unlock(&grdev->lock);
333
334 delete cb;
335
336 return 0;
337 }
338
gralloc_device_close(struct hw_device_t * dev)339 static int gralloc_device_close(struct hw_device_t *dev)
340 {
341 gralloc_device_t* d = reinterpret_cast<gralloc_device_t*>(dev);
342 if (d) {
343
344 // free still allocated buffers
345 while( d->allocListHead != NULL ) {
346 gralloc_free(&d->device, d->allocListHead->handle);
347 }
348
349 // free device
350 free(d);
351 }
352 return 0;
353 }
354
fb_compositionComplete(struct framebuffer_device_t * dev)355 static int fb_compositionComplete(struct framebuffer_device_t* dev)
356 {
357 return 0;
358 }
359
360 //
361 // Framebuffer device functions
362 //
fb_post(struct framebuffer_device_t * dev,buffer_handle_t buffer)363 static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)
364 {
365 fb_device_t *fbdev = (fb_device_t *)dev;
366 cb_handle_t *cb = (cb_handle_t *)buffer;
367
368 if (!fbdev || !cb_handle_t::validate(cb) || !cb->canBePosted()) {
369 return -EINVAL;
370 }
371
372 // Make sure we have host connection
373 DEFINE_AND_VALIDATE_HOST_CONNECTION;
374
375 // increment the post count of the buffer
376 uint32_t *postCountPtr = (uint32_t *)cb->ashmemBase;
377 if (!postCountPtr) {
378 // This should not happen
379 return -EINVAL;
380 }
381 (*postCountPtr)++;
382
383 // send post request to host
384 rcEnc->rcFBPost(rcEnc, cb->hostHandle);
385 hostCon->flush();
386
387 return 0;
388 }
389
fb_setUpdateRect(struct framebuffer_device_t * dev,int l,int t,int w,int h)390 static int fb_setUpdateRect(struct framebuffer_device_t* dev,
391 int l, int t, int w, int h)
392 {
393 fb_device_t *fbdev = (fb_device_t *)dev;
394
395 if (!fbdev) {
396 return -EINVAL;
397 }
398
399 // Make sure we have host connection
400 DEFINE_AND_VALIDATE_HOST_CONNECTION;
401
402 // send request to host
403 // TODO: XXX - should be implemented
404 //rcEnc->rc_XXX
405
406 return 0;
407 }
408
fb_setSwapInterval(struct framebuffer_device_t * dev,int interval)409 static int fb_setSwapInterval(struct framebuffer_device_t* dev,
410 int interval)
411 {
412 fb_device_t *fbdev = (fb_device_t *)dev;
413
414 if (!fbdev) {
415 return -EINVAL;
416 }
417
418 // Make sure we have host connection
419 DEFINE_AND_VALIDATE_HOST_CONNECTION;
420
421 // send request to host
422 rcEnc->rcFBSetSwapInterval(rcEnc, interval);
423 hostCon->flush();
424
425 return 0;
426 }
427
fb_close(struct hw_device_t * dev)428 static int fb_close(struct hw_device_t *dev)
429 {
430 fb_device_t *fbdev = (fb_device_t *)dev;
431
432 delete fbdev;
433
434 return 0;
435 }
436
437
438 //
439 // gralloc module functions - refcount + locking interface
440 //
gralloc_register_buffer(gralloc_module_t const * module,buffer_handle_t handle)441 static int gralloc_register_buffer(gralloc_module_t const* module,
442 buffer_handle_t handle)
443 {
444 pthread_once(&sFallbackOnce, fallback_init);
445 if (sFallback != NULL) {
446 return sFallback->registerBuffer(sFallback, handle);
447 }
448
449 D("gralloc_register_buffer(%p) called", handle);
450
451 private_module_t *gr = (private_module_t *)module;
452 cb_handle_t *cb = (cb_handle_t *)handle;
453 if (!gr || !cb_handle_t::validate(cb)) {
454 ERR("gralloc_register_buffer(%p): invalid buffer", cb);
455 return -EINVAL;
456 }
457
458 if (cb->hostHandle != 0) {
459 DEFINE_AND_VALIDATE_HOST_CONNECTION;
460 D("Opening host ColorBuffer 0x%x\n", cb->hostHandle);
461 rcEnc->rcOpenColorBuffer(rcEnc, cb->hostHandle);
462 }
463
464 //
465 // if the color buffer has ashmem region and it is not mapped in this
466 // process map it now.
467 //
468 if (cb->ashmemSize > 0 && cb->mappedPid != getpid()) {
469 void *vaddr;
470 int err = map_buffer(cb, &vaddr);
471 if (err) {
472 ERR("gralloc_register_buffer(%p): map failed: %s", cb, strerror(-err));
473 return -err;
474 }
475 cb->mappedPid = getpid();
476 }
477
478 return 0;
479 }
480
gralloc_unregister_buffer(gralloc_module_t const * module,buffer_handle_t handle)481 static int gralloc_unregister_buffer(gralloc_module_t const* module,
482 buffer_handle_t handle)
483 {
484 if (sFallback != NULL) {
485 return sFallback->unregisterBuffer(sFallback, handle);
486 }
487
488 private_module_t *gr = (private_module_t *)module;
489 cb_handle_t *cb = (cb_handle_t *)handle;
490 if (!gr || !cb_handle_t::validate(cb)) {
491 ERR("gralloc_unregister_buffer(%p): invalid buffer", cb);
492 return -EINVAL;
493 }
494
495 if (cb->hostHandle != 0) {
496 DEFINE_AND_VALIDATE_HOST_CONNECTION;
497 D("Closing host ColorBuffer 0x%x\n", cb->hostHandle);
498 rcEnc->rcCloseColorBuffer(rcEnc, cb->hostHandle);
499 }
500
501 //
502 // unmap ashmem region if it was previously mapped in this process
503 // (through register_buffer)
504 //
505 if (cb->ashmemSize > 0 && cb->mappedPid == getpid()) {
506 void *vaddr;
507 int err = munmap((void *)cb->ashmemBase, cb->ashmemSize);
508 if (err) {
509 ERR("gralloc_unregister_buffer(%p): unmap failed", cb);
510 return -EINVAL;
511 }
512 cb->ashmemBase = NULL;
513 cb->mappedPid = 0;
514 }
515
516 D("gralloc_unregister_buffer(%p) done\n", cb);
517
518 return 0;
519 }
520
gralloc_lock(gralloc_module_t const * module,buffer_handle_t handle,int usage,int l,int t,int w,int h,void ** vaddr)521 static int gralloc_lock(gralloc_module_t const* module,
522 buffer_handle_t handle, int usage,
523 int l, int t, int w, int h,
524 void** vaddr)
525 {
526 if (sFallback != NULL) {
527 return sFallback->lock(sFallback, handle, usage, l, t, w, h, vaddr);
528 }
529
530 private_module_t *gr = (private_module_t *)module;
531 cb_handle_t *cb = (cb_handle_t *)handle;
532 if (!gr || !cb_handle_t::validate(cb)) {
533 ALOGE("gralloc_lock bad handle\n");
534 return -EINVAL;
535 }
536
537 // Validate usage,
538 // 1. cannot be locked for hw access
539 // 2. lock for either sw read or write.
540 // 3. locked sw access must match usage during alloc time.
541 bool sw_read = (0 != (usage & GRALLOC_USAGE_SW_READ_MASK));
542 bool sw_write = (0 != (usage & GRALLOC_USAGE_SW_WRITE_MASK));
543 bool hw_read = (usage & GRALLOC_USAGE_HW_TEXTURE);
544 bool hw_write = (usage & GRALLOC_USAGE_HW_RENDER);
545 bool sw_read_allowed = (0 != (cb->usage & GRALLOC_USAGE_SW_READ_MASK));
546 bool sw_write_allowed = (0 != (cb->usage & GRALLOC_USAGE_SW_WRITE_MASK));
547
548 if ( (hw_read || hw_write) ||
549 (!sw_read && !sw_write) ||
550 (sw_read && !sw_read_allowed) ||
551 (sw_write && !sw_write_allowed) ) {
552 ALOGE("gralloc_lock usage mismatch usage=0x%x cb->usage=0x%x\n", usage, cb->usage);
553 return -EINVAL;
554 }
555
556 EGLint postCount = 0;
557 void *cpu_addr = NULL;
558
559 //
560 // make sure ashmem area is mapped if needed
561 //
562 if (cb->canBePosted() || sw_read || sw_write) {
563 if (cb->ashmemBasePid != getpid() || !cb->ashmemBase) {
564 return -EACCES;
565 }
566
567 if (cb->canBePosted()) {
568 postCount = *((int *)cb->ashmemBase);
569 cpu_addr = (void *)(cb->ashmemBase + sizeof(int));
570 }
571 else {
572 cpu_addr = (void *)(cb->ashmemBase);
573 }
574 }
575
576 if (cb->hostHandle) {
577 // Make sure we have host connection
578 DEFINE_AND_VALIDATE_HOST_CONNECTION;
579
580 //
581 // flush color buffer write cache on host and get its sync status.
582 //
583 int hostSyncStatus = rcEnc->rcColorBufferCacheFlush(rcEnc, cb->hostHandle,
584 postCount,
585 sw_read);
586 if (hostSyncStatus < 0) {
587 // host failed the color buffer sync - probably since it was already
588 // locked for write access. fail the lock.
589 ALOGE("gralloc_lock cacheFlush failed postCount=%d sw_read=%d\n",
590 postCount, sw_read);
591 return -EBUSY;
592 }
593
594 }
595
596 //
597 // is virtual address required ?
598 //
599 if (sw_read || sw_write) {
600 *vaddr = cpu_addr;
601 }
602
603 if (sw_write) {
604 //
605 // Keep locked region if locked for s/w write access.
606 //
607 cb->lockedLeft = l;
608 cb->lockedTop = t;
609 cb->lockedWidth = w;
610 cb->lockedHeight = h;
611 }
612
613 return 0;
614 }
615
gralloc_unlock(gralloc_module_t const * module,buffer_handle_t handle)616 static int gralloc_unlock(gralloc_module_t const* module,
617 buffer_handle_t handle)
618 {
619 if (sFallback != NULL) {
620 return sFallback->unlock(sFallback, handle);
621 }
622
623 private_module_t *gr = (private_module_t *)module;
624 cb_handle_t *cb = (cb_handle_t *)handle;
625 if (!gr || !cb_handle_t::validate(cb)) {
626 return -EINVAL;
627 }
628
629 //
630 // if buffer was locked for s/w write, we need to update the host with
631 // the updated data
632 //
633 if (cb->lockedWidth > 0 && cb->lockedHeight > 0 && cb->hostHandle) {
634
635 // Make sure we have host connection
636 DEFINE_AND_VALIDATE_HOST_CONNECTION;
637
638 void *cpu_addr;
639 if (cb->canBePosted()) {
640 cpu_addr = (void *)(cb->ashmemBase + sizeof(int));
641 }
642 else {
643 cpu_addr = (void *)(cb->ashmemBase);
644 }
645
646 if (cb->lockedWidth < cb->width || cb->lockedHeight < cb->height) {
647 int bpp = glUtilsPixelBitSize(cb->glFormat, cb->glType) >> 3;
648 char *tmpBuf = new char[cb->lockedWidth * cb->lockedHeight * bpp];
649
650 int dst_line_len = cb->lockedWidth * bpp;
651 int src_line_len = cb->width * bpp;
652 char *src = (char *)cpu_addr + cb->lockedTop*src_line_len + cb->lockedLeft*bpp;
653 char *dst = tmpBuf;
654 for (int y=0; y<cb->lockedHeight; y++) {
655 memcpy(dst, src, dst_line_len);
656 src += src_line_len;
657 dst += dst_line_len;
658 }
659
660 rcEnc->rcUpdateColorBuffer(rcEnc, cb->hostHandle,
661 cb->lockedLeft, cb->lockedTop,
662 cb->lockedWidth, cb->lockedHeight,
663 cb->glFormat, cb->glType,
664 tmpBuf);
665
666 delete [] tmpBuf;
667 }
668 else {
669 rcEnc->rcUpdateColorBuffer(rcEnc, cb->hostHandle, 0, 0,
670 cb->width, cb->height,
671 cb->glFormat, cb->glType,
672 cpu_addr);
673 }
674 }
675
676 cb->lockedWidth = cb->lockedHeight = 0;
677 return 0;
678 }
679
680
gralloc_device_open(const hw_module_t * module,const char * name,hw_device_t ** device)681 static int gralloc_device_open(const hw_module_t* module,
682 const char* name,
683 hw_device_t** device)
684 {
685 int status = -EINVAL;
686
687 D("gralloc_device_open %s\n", name);
688
689 pthread_once( &sFallbackOnce, fallback_init );
690 if (sFallback != NULL) {
691 return sFallback->common.methods->open(&sFallback->common, name, device);
692 }
693
694 if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) {
695
696 // Create host connection and keep it in the TLS.
697 // return error if connection with host can not be established
698 HostConnection *hostCon = HostConnection::get();
699 if (!hostCon) {
700 ALOGE("gralloc: failed to get host connection while opening %s\n", name);
701 return -EIO;
702 }
703
704 //
705 // Allocate memory for the gralloc device (alloc interface)
706 //
707 gralloc_device_t *dev;
708 dev = (gralloc_device_t*)malloc(sizeof(gralloc_device_t));
709 if (NULL == dev) {
710 return -ENOMEM;
711 }
712
713 // Initialize our device structure
714 //
715 dev->device.common.tag = HARDWARE_DEVICE_TAG;
716 dev->device.common.version = 0;
717 dev->device.common.module = const_cast<hw_module_t*>(module);
718 dev->device.common.close = gralloc_device_close;
719
720 dev->device.alloc = gralloc_alloc;
721 dev->device.free = gralloc_free;
722 dev->allocListHead = NULL;
723 pthread_mutex_init(&dev->lock, NULL);
724
725 *device = &dev->device.common;
726 status = 0;
727 }
728 else if (!strcmp(name, GRALLOC_HARDWARE_FB0)) {
729
730 // return error if connection with host can not be established
731 DEFINE_AND_VALIDATE_HOST_CONNECTION;
732
733 //
734 // Query the host for Framebuffer attributes
735 //
736 D("gralloc: query Frabuffer attribs\n");
737 EGLint width = rcEnc->rcGetFBParam(rcEnc, FB_WIDTH);
738 D("gralloc: width=%d\n", width);
739 EGLint height = rcEnc->rcGetFBParam(rcEnc, FB_HEIGHT);
740 D("gralloc: height=%d\n", height);
741 EGLint xdpi = rcEnc->rcGetFBParam(rcEnc, FB_XDPI);
742 D("gralloc: xdpi=%d\n", xdpi);
743 EGLint ydpi = rcEnc->rcGetFBParam(rcEnc, FB_YDPI);
744 D("gralloc: ydpi=%d\n", ydpi);
745 EGLint fps = rcEnc->rcGetFBParam(rcEnc, FB_FPS);
746 D("gralloc: fps=%d\n", fps);
747 EGLint min_si = rcEnc->rcGetFBParam(rcEnc, FB_MIN_SWAP_INTERVAL);
748 D("gralloc: min_swap=%d\n", min_si);
749 EGLint max_si = rcEnc->rcGetFBParam(rcEnc, FB_MAX_SWAP_INTERVAL);
750 D("gralloc: max_swap=%d\n", max_si);
751
752 //
753 // Allocate memory for the framebuffer device
754 //
755 fb_device_t *dev;
756 dev = (fb_device_t*)malloc(sizeof(fb_device_t));
757 if (NULL == dev) {
758 return -ENOMEM;
759 }
760 memset(dev, 0, sizeof(fb_device_t));
761
762 // Initialize our device structure
763 //
764 dev->device.common.tag = HARDWARE_DEVICE_TAG;
765 dev->device.common.version = 0;
766 dev->device.common.module = const_cast<hw_module_t*>(module);
767 dev->device.common.close = fb_close;
768 dev->device.setSwapInterval = fb_setSwapInterval;
769 dev->device.post = fb_post;
770 dev->device.setUpdateRect = 0; //fb_setUpdateRect;
771 dev->device.compositionComplete = fb_compositionComplete; //XXX: this is a dummy
772
773 const_cast<uint32_t&>(dev->device.flags) = 0;
774 const_cast<uint32_t&>(dev->device.width) = width;
775 const_cast<uint32_t&>(dev->device.height) = height;
776 const_cast<int&>(dev->device.stride) = width;
777 const_cast<int&>(dev->device.format) = HAL_PIXEL_FORMAT_RGBA_8888;
778 const_cast<float&>(dev->device.xdpi) = xdpi;
779 const_cast<float&>(dev->device.ydpi) = ydpi;
780 const_cast<float&>(dev->device.fps) = fps;
781 const_cast<int&>(dev->device.minSwapInterval) = min_si;
782 const_cast<int&>(dev->device.maxSwapInterval) = max_si;
783 *device = &dev->device.common;
784
785 status = 0;
786 }
787
788 return status;
789 }
790
791 //
792 // define the HMI symbol - our module interface
793 //
794 static struct hw_module_methods_t gralloc_module_methods = {
795 open: gralloc_device_open
796 };
797
798 struct private_module_t HAL_MODULE_INFO_SYM = {
799 base: {
800 common: {
801 tag: HARDWARE_MODULE_TAG,
802 version_major: 1,
803 version_minor: 0,
804 id: GRALLOC_HARDWARE_MODULE_ID,
805 name: "Graphics Memory Allocator Module",
806 author: "The Android Open Source Project",
807 methods: &gralloc_module_methods,
808 dso: NULL,
809 reserved: {0, }
810 },
811 registerBuffer: gralloc_register_buffer,
812 unregisterBuffer: gralloc_unregister_buffer,
813 lock: gralloc_lock,
814 unlock: gralloc_unlock,
815 perform: NULL,
816 reserved_proc : {NULL, }
817 }
818 };
819
820 /* This function is called once to detect whether the emulator supports
821 * GPU emulation (this is done by looking at the qemu.gles kernel
822 * parameter, which must be > 0 if this is the case).
823 *
824 * If not, then load gralloc.default instead as a fallback.
825 */
826 static void
fallback_init(void)827 fallback_init(void)
828 {
829 char prop[PROPERTY_VALUE_MAX];
830 void* module;
831
832 property_get("ro.kernel.qemu.gles", prop, "0");
833 if (atoi(prop) > 0) {
834 return;
835 }
836 ALOGD("Emulator without GPU emulation detected.");
837 module = dlopen("/system/lib/hw/gralloc.default.so", RTLD_LAZY|RTLD_LOCAL);
838 if (module != NULL) {
839 sFallback = reinterpret_cast<gralloc_module_t*>(dlsym(module, HAL_MODULE_INFO_SYM_AS_STR));
840 if (sFallback == NULL) {
841 dlclose(module);
842 }
843 }
844 if (sFallback == NULL) {
845 ALOGE("Could not find software fallback module!?");
846 }
847 }
848