From 783cc1bb53dc025a8ca6b08c1e35755e83734d08 Mon Sep 17 00:00:00 2001 From: David 'Digit' Turner Date: Fri, 26 Aug 2011 17:29:10 +0200 Subject: [PATCH] emulator: opengl: fallback gralloc module This patch modifies the gralloc.goldfish module to check that the emulator does, indeed, support GPU emulation. If this is not the case, it loads the framebuffer-based fallback module (gralloc.default) explicitely and uses it instead. This is necessary because sometimes the emulator will be started in headless mode in restricted environment, i.e. without access to the display subsystem or GL libraries, which make GPU emulation impossible. We check for ro.kernel.qemu.gles which will be either undefined or set to 0 if the emulator doesn't support GPU emulation, or 1 otherwise. Change-Id: Ib6b143e6dcdfb44ff2c5b889138d0fb4118bb461 --- .../opengl/system/gralloc/gralloc.cpp | 66 ++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/tools/emulator/opengl/system/gralloc/gralloc.cpp b/tools/emulator/opengl/system/gralloc/gralloc.cpp index 93fe6ac86..258b0db85 100644 --- a/tools/emulator/opengl/system/gralloc/gralloc.cpp +++ b/tools/emulator/opengl/system/gralloc/gralloc.cpp @@ -23,11 +23,12 @@ #include #include #include +#include #include #include "HostConnection.h" #include "glUtils.h" #include - +#include #define DBG_FUNC DBG("%s\n", __FUNCTION__) // @@ -37,6 +38,16 @@ struct private_module_t { gralloc_module_t base; }; +/* If not NULL, this is a pointer to the fallback module. + * This really is gralloc.default, which we'll use if we detect + * that the emulator we're running in does not support GPU emulation. + */ +static gralloc_module_t* sFallback; +static pthread_once_t sFallbackOnce = PTHREAD_ONCE_INIT; + +static void fallback_init(void); // forward + + typedef struct _alloc_list_node { buffer_handle_t handle; _alloc_list_node *next; @@ -401,6 +412,12 @@ static int fb_close(struct hw_device_t *dev) static int gralloc_register_buffer(gralloc_module_t const* module, buffer_handle_t handle) { + pthread_once(&sFallbackOnce, fallback_init); + if (sFallback != NULL) { + return sFallback->registerBuffer(sFallback, handle); + } + + private_module_t *gr = (private_module_t *)module; cb_handle_t *cb = (cb_handle_t *)handle; if (!gr || !cb_handle_t::validate(cb)) { @@ -428,6 +445,10 @@ static int gralloc_register_buffer(gralloc_module_t const* module, static int gralloc_unregister_buffer(gralloc_module_t const* module, buffer_handle_t handle) { + if (sFallback != NULL) { + return sFallback->unregisterBuffer(sFallback, handle); + } + private_module_t *gr = (private_module_t *)module; cb_handle_t *cb = (cb_handle_t *)handle; if (!gr || !cb_handle_t::validate(cb)) { @@ -458,6 +479,10 @@ static int gralloc_lock(gralloc_module_t const* module, int l, int t, int w, int h, void** vaddr) { + if (sFallback != NULL) { + return sFallback->lock(sFallback, handle, usage, l, t, w, h, vaddr); + } + private_module_t *gr = (private_module_t *)module; cb_handle_t *cb = (cb_handle_t *)handle; if (!gr || !cb_handle_t::validate(cb)) { @@ -546,6 +571,10 @@ static int gralloc_lock(gralloc_module_t const* module, static int gralloc_unlock(gralloc_module_t const* module, buffer_handle_t handle) { + if (sFallback != NULL) { + return sFallback->unlock(sFallback, handle); + } + private_module_t *gr = (private_module_t *)module; cb_handle_t *cb = (cb_handle_t *)handle; if (!gr || !cb_handle_t::validate(cb)) { @@ -603,6 +632,7 @@ static int gralloc_unlock(gralloc_module_t const* module, return 0; } + static int gralloc_device_open(const hw_module_t* module, const char* name, hw_device_t** device) @@ -611,6 +641,11 @@ static int gralloc_device_open(const hw_module_t* module, LOGD("gralloc_device_open %s\n", name); + pthread_once( &sFallbackOnce, fallback_init ); + if (sFallback != NULL) { + return sFallback->common.methods->open(&sFallback->common, name, device); + } + if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) { // Create host connection and keep it in the TLS. @@ -731,3 +766,32 @@ struct private_module_t HAL_MODULE_INFO_SYM = { reserved_proc : {NULL, } } }; + +/* This function is called once to detect whether the emulator supports + * GPU emulation (this is done by looking at the qemu.gles kernel + * parameter, which must be > 0 if this is the case). + * + * If not, then load gralloc.default instead as a fallback. + */ +static void +fallback_init(void) +{ + char prop[PROPERTY_VALUE_MAX]; + void* module; + + property_get("ro.kernel.qemu.gles", prop, "0"); + if (atoi(prop) > 0) { + return; + } + LOGD("Emulator without GPU emulation detected."); + module = dlopen("/system/lib/hw/gralloc.default.so", RTLD_LAZY|RTLD_LOCAL); + if (module != NULL) { + sFallback = reinterpret_cast(dlsym(module, HAL_MODULE_INFO_SYM_AS_STR)); + if (sFallback == NULL) { + dlclose(module); + } + } + if (sFallback == NULL) { + LOGE("Could not find software fallback module!?"); + } +}