diff options
-rw-r--r-- | android/android.h | 7 | ||||
-rw-r--r-- | android/opengles.c | 57 | ||||
-rw-r--r-- | android/opengles.h | 12 | ||||
-rw-r--r-- | android/qemu-setup.c | 33 | ||||
-rw-r--r-- | vl-android.c | 49 |
5 files changed, 132 insertions, 26 deletions
diff --git a/android/android.h b/android/android.h index 189b5c2..e32f9f5 100644 --- a/android/android.h +++ b/android/android.h @@ -97,6 +97,13 @@ extern int android_parse_network_speed(const char* speed); * accordingly. returns -1 on error, 0 on success */ extern int android_parse_network_latency(const char* delay); +/** in qemu_setup.c */ + +#define ANDROID_GLSTRING_BUF_SIZE 128 +extern char android_gl_vendor[ANDROID_GLSTRING_BUF_SIZE]; +extern char android_gl_renderer[ANDROID_GLSTRING_BUF_SIZE]; +extern char android_gl_version[ANDROID_GLSTRING_BUF_SIZE]; + extern void android_emulation_setup( void ); extern void android_emulation_teardown( void ); diff --git a/android/opengles.c b/android/opengles.c index d1f4322..521dc03 100644 --- a/android/opengles.c +++ b/android/opengles.c @@ -46,6 +46,7 @@ int android_gles_fast_pipes = 1; DYNLINK_FUNC(initLibrary) \ DYNLINK_FUNC(setStreamMode) \ DYNLINK_FUNC(initOpenGLRenderer) \ + DYNLINK_FUNC(getHardwareStrings) \ DYNLINK_FUNC(createOpenGLSubwindow) \ DYNLINK_FUNC(destroyOpenGLSubwindow) \ DYNLINK_FUNC(repaintOpenGLDisplay) \ @@ -151,6 +152,62 @@ android_startOpenglesRenderer(int width, int height, OnPostFunc onPost, void* on return 0; } +static void strncpy_safe(char* dst, const char* src, size_t n) +{ + strncpy(dst, src, n); + dst[n-1] = '\0'; +} + +static void extractBaseString(char* dst, const char* src, size_t dstSize) +{ + size_t len = strlen(src); + const char* begin = strchr(src, '('); + const char* end = strrchr(src, ')'); + + if (!begin || !end) { + strncpy_safe(dst, src, dstSize); + return; + } + begin += 1; + + // "foo (bar)" + // ^ ^ + // b e + // = 5 8 + // substring with NUL-terminator is end-begin+1 bytes + if (end - begin + 1 > dstSize) { + end = begin + dstSize - 1; + } + + strncpy_safe(dst, begin, end - begin + 1); +} + +void +android_getOpenglesHardwareStrings(char* vendor, size_t vendorBufSize, + char* renderer, size_t rendererBufSize, + char* version, size_t versionBufSize) +{ + const char *vendorSrc, *rendererSrc, *versionSrc; + + getHardwareStrings(&vendorSrc, &rendererSrc, &versionSrc); + if (!vendorSrc) vendorSrc = ""; + if (!rendererSrc) rendererSrc = ""; + if (!versionSrc) versionSrc = ""; + + /* Special case for the default ES to GL translators: extract the strings + * of the underlying OpenGL implementation. */ + if (strncmp(vendorSrc, "Google", 6) == 0 && + strncmp(rendererSrc, "Android Emulator OpenGL ES Translator", 37) == 0) { + extractBaseString(vendor, vendorSrc, vendorBufSize); + extractBaseString(renderer, rendererSrc, rendererBufSize); + extractBaseString(version, versionSrc, versionBufSize); + } else { + strncpy_safe(vendor, vendorSrc, vendorBufSize); + strncpy_safe(renderer, rendererSrc, rendererBufSize); + strncpy_safe(version, versionSrc, versionBufSize); + } +} + void android_stopOpenglesRenderer(void) { diff --git a/android/opengles.h b/android/opengles.h index 60e125d..4e83c02 100644 --- a/android/opengles.h +++ b/android/opengles.h @@ -33,6 +33,18 @@ int android_initOpenglesEmulation(void); int android_startOpenglesRenderer(int width, int height, OnPostFunc onPost, void* onPostContext); +/* Retrieve the Vendor/Renderer/Version strings describing the underlying GL + * implementation. The call only works while the renderer is started. + * + * Each string is copied into the corresponding buffer. If the original string + * (including NUL terminator) is more than xxBufSize bytes, it will be + * truncated. In all cases, including failure, the buffer will be NUL- + * terminated when this function returns. + */ +void android_getOpenglesHardwareStrings(char* vendor, size_t vendorBufSize, + char* renderer, size_t rendererBufSize, + char* version, size_t versionBufSize); + int android_showOpenglesWindow(void* window, int x, int y, int width, int height, float rotation); int android_hideOpenglesWindow(void); diff --git a/android/qemu-setup.c b/android/qemu-setup.c index 181c95b..8b8f0b0 100644 --- a/android/qemu-setup.c +++ b/android/qemu-setup.c @@ -47,6 +47,11 @@ char* op_http_proxy = NULL; /* Base port for the emulated system. */ int android_base_port; +/* Strings describing the host system's OpenGL implementation */ +char android_gl_vendor[ANDROID_GLSTRING_BUF_SIZE]; +char android_gl_renderer[ANDROID_GLSTRING_BUF_SIZE]; +char android_gl_version[ANDROID_GLSTRING_BUF_SIZE]; + /*** APPLICATION DIRECTORY *** Where are we ? ***/ @@ -483,6 +488,14 @@ void android_emulation_setup( void ) char tmp[PATH_MAX]; const char* appdir = get_app_dir(); + const size_t ARGSLEN = + PATH_MAX + // max ping program path + 10 + // max VERSION_STRING length + 3*ANDROID_GLSTRING_BUF_SIZE + // max GL string lengths + 29 + // static args characters + 1; // NUL terminator + char args[ARGSLEN]; + if (snprintf( tmp, PATH_MAX, "%s%s%s", appdir, PATH_SEP, _ANDROID_PING_PROGRAM ) >= PATH_MAX) { dprint( "Application directory too long: %s", appdir); @@ -507,10 +520,12 @@ void android_emulation_setup( void ) if (!comspec) comspec = "cmd.exe"; // Run - char args[PATH_MAX + 30]; - if (snprintf( args, PATH_MAX, "/C \"%s\" ping emulator " VERSION_STRING, - tmp) >= PATH_MAX ) { - D( "DDMS path too long: %s", tmp); + if (snprintf(args, ARGSLEN, + "/C \"%s\" ping emulator " VERSION_STRING " \"%s\" \"%s\" \"%s\"", + tmp, android_gl_vendor, android_gl_renderer, android_gl_version) + >= ARGSLEN) + { + D( "DDMS command line too long: %s", args); return; } @@ -540,13 +555,17 @@ void android_emulation_setup( void ) int fd = open("/dev/null", O_WRONLY); dup2(fd, 1); dup2(fd, 2); - execl( tmp, _ANDROID_PING_PROGRAM, "ping", "emulator", VERSION_STRING, NULL ); + execl( tmp, _ANDROID_PING_PROGRAM, "ping", "emulator", VERSION_STRING, + android_gl_vendor, android_gl_renderer, android_gl_version, + NULL ); } END_NOSIGALRM /* don't do anything in the parent or in case of error */ - strncat( tmp, " ping emulator " VERSION_STRING, PATH_MAX - strlen(tmp) ); - D( "ping command: %s", tmp ); + snprintf(args, ARGSLEN, + "%s ping emulator " VERSION_STRING " \"%s\" \"%s\" \"%s\"", + tmp, android_gl_vendor, android_gl_renderer, android_gl_version); + D( "ping command: %s", args ); #endif } } diff --git a/vl-android.c b/vl-android.c index 74a2dc4..1513541 100644 --- a/vl-android.c +++ b/vl-android.c @@ -3867,29 +3867,40 @@ int main(int argc, char **argv, char **envp) nand_add_dev(tmp); } - /* qemu.gles will be read by the OpenGLES emulation libraries. - * If set to 0, the software GLES renderer will be used as a fallback. - * If the parameter is undefined, this means the system image runs - * inside an emulator that doesn't support GPU emulation at all. - */ + /* qemu.gles will be read by the OpenGL ES emulation libraries. + * If set to 0, the software GL ES renderer will be used as a fallback. + * If the parameter is undefined, this means the system image runs + * inside an emulator that doesn't support GPU emulation at all. + * + * We always start the GL ES renderer so we can gather stats on the + * underlying GL implementation. If GL ES acceleration is disabled, + * we just shut it down again once we have the strings. */ { - int gles_emul = 0; - - if (android_hw->hw_gpu_enabled) { - /* Set framebuffer change notification callback when starting - * GLES emulation. Currently only multi-touch emulation is - * interested in FB changes (to transmit them to the device), so - * the callback is set within MT emulation.*/ - if (android_initOpenglesEmulation() == 0 && - android_startOpenglesRenderer(android_hw->hw_lcd_width, - android_hw->hw_lcd_height, - multitouch_opengles_fb_update, NULL) == 0) { - gles_emul = 1; + int qemu_gles = 0; + + /* Set framebuffer change notification callback when starting + * GLES emulation. Currently only multi-touch emulation is + * interested in FB changes (to transmit them to the device), so + * the callback is set within MT emulation. */ + if (android_initOpenglesEmulation() == 0 && + android_startOpenglesRenderer(android_hw->hw_lcd_width, + android_hw->hw_lcd_height, + multitouch_opengles_fb_update, NULL) == 0) + { + android_getOpenglesHardwareStrings( + android_gl_vendor, sizeof(android_gl_vendor), + android_gl_renderer, sizeof(android_gl_renderer), + android_gl_version, sizeof(android_gl_version)); + if (android_hw->hw_gpu_enabled) { + qemu_gles = 1; } else { - dwarning("Could not initialize OpenglES emulation, using software renderer."); + android_stopOpenglesRenderer(); + qemu_gles = 0; } + } else { + dwarning("Could not initialize OpenglES emulation, using software renderer."); } - if (gles_emul) { + if (qemu_gles) { stralloc_add_str(kernel_params, " qemu.gles=1"); } else { stralloc_add_str(kernel_params, " qemu.gles=0"); |