aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.android1
-rw-r--r--Makefile.target2
-rw-r--r--android/avd/hardware-properties.ini8
-rw-r--r--android/hw-pipe-net.c27
-rw-r--r--android/opengles.c167
-rw-r--r--android/opengles.h37
-rw-r--r--android/skin/scaler.c22
-rw-r--r--android/skin/scaler.h6
-rw-r--r--android/skin/window.c54
-rw-r--r--android/utils/debug.h1
-rw-r--r--vl-android.c24
11 files changed, 346 insertions, 3 deletions
diff --git a/Makefile.android b/Makefile.android
index 01cb35b..95287fd 100644
--- a/Makefile.android
+++ b/Makefile.android
@@ -242,6 +242,7 @@ LOCAL_SRC_FILES := \
android/snapshot.c \
android/main-common.c \
android/main.c \
+ android/opengles.c \
android/utils/setenv.c \
vl-android-ui.c \
android/protocol/core-connection.c \
diff --git a/Makefile.target b/Makefile.target
index ccc86b4..07940bb 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -269,6 +269,7 @@ LOCAL_SRC_FILES := \
user-events-qemu.c \
vl-android.c \
android/console.c \
+ android/opengles.c \
android/display-core.c \
android/protocol/attach-ui-proxy.c \
android/protocol/fb-updates-proxy.c \
@@ -353,6 +354,7 @@ LOCAL_SRC_FILES := \
android/help.c \
android/main-common.c \
android/main.c \
+ android/opengles.c \
android/protocol/core-commands-qemu.c \
android/protocol/ui-commands-qemu.c \
android/
diff --git a/android/avd/hardware-properties.ini b/android/avd/hardware-properties.ini
index 0e650bb..e7eb445 100644
--- a/android/avd/hardware-properties.ini
+++ b/android/avd/hardware-properties.ini
@@ -224,6 +224,14 @@ default = yes
abstract = LCD backlight
description = Enable/Disable LCD backlight simulation,yes-enabled,no-disabled.
+# Hardware OpenGLES emulation support
+#
+name = hw.gpu.enabled
+type = boolean
+default = no
+abstract = GPU emulation
+description = Enable/Disable emulated OpenGLES GPU
+
# Maximum VM heap size
# Higher values are required for high-dpi devices
# Default will depend on RAM size.
diff --git a/android/hw-pipe-net.c b/android/hw-pipe-net.c
index dd8c8b1..8b8017d 100644
--- a/android/hw-pipe-net.c
+++ b/android/hw-pipe-net.c
@@ -23,6 +23,7 @@
#include "android/utils/panic.h"
#include "android/utils/system.h"
#include "android/async-utils.h"
+#include "android/opengles.h"
#include "android/looper.h"
#include "hw/goldfish_pipe.h"
@@ -454,7 +455,11 @@ static const GoldfishPipeFuncs netPipeUnix_funcs = {
};
#endif
-#define DEFAULT_OPENGLES_PORT 22468
+/* This is set to 1 in android_init_opengles() below, and tested
+ * by openglesPipe_init() to refuse a pipe connection if the function
+ * was never called.
+ */
+static int _opengles_init;
static void*
openglesPipe_init( void* hwpipe, void* _looper, const char* args )
@@ -462,8 +467,15 @@ openglesPipe_init( void* hwpipe, void* _looper, const char* args )
char temp[32];
NetPipe *pipe;
+ if (!_opengles_init) {
+ /* This should never happen, unless there is a bug in the
+ * emulator's initialization, or the system image. */
+ D("Trying to open the OpenGLES pipe without GPU emulation!");
+ return NULL;
+ }
+
/* For now, simply connect through tcp */
- snprintf(temp, sizeof temp, "%d", DEFAULT_OPENGLES_PORT);
+ snprintf(temp, sizeof temp, "%d", ANDROID_OPENGLES_BASE_PORT);
pipe = (NetPipe *)netPipe_initTcp(hwpipe, _looper, temp);
if (pipe != NULL) {
@@ -496,7 +508,6 @@ static const GoldfishPipeFuncs openglesPipe_funcs = {
netPipe_wakeOn,
};
-
void
android_net_pipes_init(void)
{
@@ -508,3 +519,13 @@ android_net_pipes_init(void)
#endif
goldfish_pipe_add_type( "opengles", looper, &openglesPipe_funcs );
}
+
+int
+android_init_opengles_pipes(void)
+{
+ /* TODO: Check that we can load and initialize the host emulation
+ * libraries, and return -1 in case of error.
+ */
+ _opengles_init = 1;
+ return 0;
+}
diff --git a/android/opengles.c b/android/opengles.c
new file mode 100644
index 0000000..5d0c152
--- /dev/null
+++ b/android/opengles.c
@@ -0,0 +1,167 @@
+/* Copyright (C) 2011 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+
+#include "config-host.h"
+#include "android/opengles.h"
+#include <android/utils/debug.h>
+#include <android/utils/path.h>
+#include <android/utils/bufprint.h>
+#include <android/utils/dll.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define D(...) VERBOSE_PRINT(init,__VA_ARGS__)
+#define DD(...) VERBOSE_PRINT(gles,__VA_ARGS__)
+
+/* Name of the GLES rendering library we're going to use */
+#define RENDERER_LIB_NAME "libOpenglRender"
+
+/* These definitions *must* match those under:
+ * development/tools/emulator/opengl/host/include/libOpenglRender/render_api.h
+ */
+#define DYNLINK_FUNCTIONS \
+ DYNLINK_FUNC(int,initLibrary,(void),(),return) \
+ DYNLINK_FUNC(int,initOpenGLRenderer,(int width, int height, int port),(width,height,port),return) \
+ DYNLINK_FUNC(int,createOpenGLSubwindow,(void* window, int x, int y, int width, int height, float zRot),(window,x,y,width,height,zRot),return)\
+ DYNLINK_FUNC(int,destroyOpenGLSubwindow,(void),(),return)\
+ DYNLINK_FUNC(void,repaintOpenGLDisplay,(void),(),)\
+ DYNLINK_FUNC(void,stopOpenGLRenderer,(void),(),)
+
+
+#ifndef CONFIG_STANDALONE_UI
+/* Defined in android/hw-pipe-net.c */
+extern int android_init_opengles_pipes(void);
+#endif
+
+static ADynamicLibrary* rendererLib;
+
+/* Define the pointers and the wrapper functions to call them */
+#define DYNLINK_FUNC(result,name,sig,params,ret) \
+ static result (*_ptr_##name) sig; \
+ static result name sig { \
+ ret (*_ptr_##name) params ; \
+ }
+
+DYNLINK_FUNCTIONS
+
+#undef DYNLINK_FUNC
+
+static int
+initOpenglesEmulationFuncs(ADynamicLibrary* rendererLib)
+{
+ void* symbol;
+ char* error;
+#define DYNLINK_FUNC(result,name,sig,params,ret) \
+ symbol = adynamicLibrary_findSymbol( rendererLib, #name, &error ); \
+ if (symbol != NULL) { \
+ _ptr_##name = symbol; \
+ } else { \
+ derror("GLES emulation: Could not find required symbol (%s): %s", #name, error); \
+ free(error); \
+ return -1; \
+ }
+DYNLINK_FUNCTIONS
+#undef DYNLINK_FUNC
+ return 0;
+}
+
+int
+android_initOpenglesEmulation(void)
+{
+ char* error = NULL;
+
+ if (rendererLib != NULL)
+ return 0;
+
+ D("Initializing hardware OpenGLES emulation support");
+
+ rendererLib = adynamicLibrary_open(RENDERER_LIB_NAME, &error);
+ if (rendererLib == NULL) {
+ derror("Could not load OpenGLES emulation library: %s", error);
+ return -1;
+ }
+
+#ifndef CONFIG_STANDALONE_UI
+ android_init_opengles_pipes();
+#endif
+
+
+ /* Resolve the functions */
+ if (initOpenglesEmulationFuncs(rendererLib) < 0) {
+ derror("OpenGLES emulation library mismatch. Be sure to use the correct version!");
+ goto BAD_EXIT;
+ }
+
+ if (!initLibrary()) {
+ derror("OpenGLES initialization failed!");
+ goto BAD_EXIT;
+ }
+
+ return 0;
+
+BAD_EXIT:
+ derror("OpenGLES emulation library could not be initialized!");
+ adynamicLibrary_close(rendererLib);
+ rendererLib = NULL;
+ return -1;
+}
+
+int
+android_startOpenglesRenderer(int width, int height)
+{
+ if (!rendererLib) {
+ D("Can't start OpenGLES renderer without support libraries");
+ return -1;
+ }
+
+ if (initOpenGLRenderer(width, height,ANDROID_OPENGLES_BASE_PORT) != 0) {
+ D("Can't start OpenGLES renderer?");
+ return -1;
+ }
+ return 0;
+}
+
+void
+android_stopOpenglesRenderer(void)
+{
+ if (rendererLib) {
+ stopOpenGLRenderer();
+ }
+}
+
+int
+android_showOpenglesWindow(void* window, int x, int y, int width, int height, float rotation)
+{
+ if (rendererLib) {
+ return createOpenGLSubwindow(window, x, y, width, height, rotation);
+ } else {
+ return -1;
+ }
+}
+
+int
+android_hideOpenglesWindow(void)
+{
+ if (rendererLib) {
+ return destroyOpenGLSubwindow();
+ } else {
+ return -1;
+ }
+}
+
+void
+android_redrawOpenglesWindow(void)
+{
+ if (rendererLib) {
+ repaintOpenGLDisplay();
+ }
+}
diff --git a/android/opengles.h b/android/opengles.h
new file mode 100644
index 0000000..b31ce11
--- /dev/null
+++ b/android/opengles.h
@@ -0,0 +1,37 @@
+/* Copyright (C) 2011 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+#ifndef ANDROID_OPENGLES_H
+#define ANDROID_OPENGLES_H
+
+#define ANDROID_OPENGLES_BASE_PORT 22468
+
+/* Call this function to initialize the hardware opengles emulation.
+ * This function will abort if we can't find the corresponding host
+ * libraries through dlopen() or equivalent.
+ */
+int android_initOpenglesEmulation(void);
+
+/* Tries to start the renderer process. Returns 0 on success, -1 on error.
+ * At the moment, this must be done before the VM starts.
+ */
+int android_startOpenglesRenderer(int width, int height);
+
+int android_showOpenglesWindow(void* window, int x, int y, int width, int height, float rotation);
+
+int android_hideOpenglesWindow(void);
+
+void android_redrawOpenglesWindow(void);
+
+/* Stop the renderer process */
+void android_stopOpenglesRenderer(void);
+
+#endif /* ANDROID_OPENGLES_H */
diff --git a/android/skin/scaler.c b/android/skin/scaler.c
index 907c5ca..5672869 100644
--- a/android/skin/scaler.c
+++ b/android/skin/scaler.c
@@ -81,6 +81,28 @@ typedef struct {
void
+skin_scaler_get_scaled_rect( SkinScaler* scaler,
+ SkinRect* srect,
+ SkinRect* drect )
+{
+ int sx = srect->pos.x;
+ int sy = srect->pos.y;
+ int sw = srect->size.w;
+ int sh = srect->size.h;
+ double scale = scaler->scale;
+
+ if (!scaler->valid) {
+ drect[0] = srect[0];
+ return;
+ }
+
+ drect->pos.x = (int)(sx * scale + scaler->xdisp);
+ drect->pos.y = (int)(sy * scale + scaler->ydisp);
+ drect->size.w = (int)(ceil((sx + sw) * scale + scaler->xdisp)) - drect->pos.x;
+ drect->size.h = (int)(ceil((sy + sh) * scale + scaler->ydisp)) - drect->pos.y;
+}
+
+void
skin_scaler_scale( SkinScaler* scaler,
SDL_Surface* dst_surface,
SDL_Surface* src_surface,
diff --git a/android/skin/scaler.h b/android/skin/scaler.h
index 4e0ec5a..e2d7641 100644
--- a/android/skin/scaler.h
+++ b/android/skin/scaler.h
@@ -26,6 +26,12 @@ extern int skin_scaler_set( SkinScaler* scaler,
double xDisp,
double yDisp );
+/* retrieve the position of the scaled source rectangle 'srect' into 'drect'
+ * you can use the same pointer for both parameters. */
+extern void skin_scaler_get_scaled_rect( SkinScaler* scaler,
+ SkinRect* srect,
+ SkinRect* drect );
+
extern void skin_scaler_free( SkinScaler* scaler );
extern void skin_scaler_scale( SkinScaler* scaler,
diff --git a/android/skin/window.c b/android/skin/window.c
index 9a72db5..5d8c684 100644
--- a/android/skin/window.c
+++ b/android/skin/window.c
@@ -22,6 +22,7 @@
#include <math.h>
#include "android/framebuffer.h"
+#include "android/opengles.h"
/* when shrinking, we reduce the pixel ratio by this fixed amount */
#define SHRINK_SCALE 0.6
@@ -1140,6 +1141,44 @@ skin_window_show_trackball( SkinWindow* window, int enable )
}
}
+/* Hide the OpenGL ES framebuffer */
+static void
+skin_window_hide_opengles( SkinWindow* window )
+{
+ android_hideOpenglesWindow();
+}
+
+/* Show the OpenGL ES framebuffer window */
+static void
+skin_window_show_opengles( SkinWindow* window )
+{
+ {
+ SDL_SysWMinfo wminfo;
+ void* winhandle;
+ ADisplay* disp = window->layout.displays;
+ SkinRect drect = disp->rect;
+
+ memset(&wminfo, 0, sizeof(wminfo));
+ SDL_GetWMInfo(&wminfo);
+#ifdef _WIN32
+ winhandle = (void*)wminfo.window;
+#elif defined(CONFIG_DARWIN)
+ winhandle = (void*)wminfo.nsWindowPtr;
+#else
+ winhandle = (void*)wminfo.info.x11.window;
+#endif
+ skin_scaler_get_scaled_rect(window->scaler, &drect, &drect);
+
+ android_showOpenglesWindow(winhandle, drect.pos.x, drect.pos.y,
+ drect.size.w, drect.size.h, disp->rotation * -90.);
+ }
+}
+
+static void
+skin_window_redraw_opengles( SkinWindow* window )
+{
+ android_redrawOpenglesWindow();
+}
static int skin_window_reset_internal (SkinWindow*, SkinLayout*);
@@ -1224,6 +1263,8 @@ skin_window_create( SkinLayout* slayout, int x, int y, double scale, int no
dprint( "emulator window was out of view and was recentered\n" );
}
+ skin_window_show_opengles(window);
+
return window;
}
@@ -1261,6 +1302,9 @@ skin_window_set_title( SkinWindow* window, const char* title )
static void
skin_window_resize( SkinWindow* window )
{
+ if ( !window->no_display )
+ skin_window_hide_opengles(window);
+
/* now resize window */
if (window->surface) {
SDL_FreeSurface(window->surface);
@@ -1342,7 +1386,10 @@ skin_window_resize( SkinWindow* window )
}
if (scale == 1.0)
+ {
window->surface = surface;
+ skin_scaler_set( window->scaler, 1.0, 0, 0 );
+ }
else
{
window_w = (int) ceil(window_w / scale );
@@ -1361,6 +1408,8 @@ skin_window_resize( SkinWindow* window )
}
skin_scaler_set( window->scaler, scale, window->effective_x, window->effective_y );
}
+
+ skin_window_show_opengles(window);
}
}
@@ -1552,6 +1601,7 @@ skin_window_redraw( SkinWindow* window, SkinRect* rect )
SDL_UpdateRects( window->surface, 1, &rd );
}
+ skin_window_redraw_opengles( window );
}
}
@@ -1681,6 +1731,10 @@ skin_window_process_event( SkinWindow* window, SDL_Event* ev )
}
}
break;
+
+ case SDL_VIDEOEXPOSE:
+ skin_window_redraw_opengles(window);
+ break;
}
}
diff --git a/android/utils/debug.h b/android/utils/debug.h
index 76b21be..096b002 100644
--- a/android/utils/debug.h
+++ b/android/utils/debug.h
@@ -36,6 +36,7 @@
_VERBOSE_TAG(sensors, "emulated sensors") \
_VERBOSE_TAG(memcheck, "memory checker") \
_VERBOSE_TAG(camera, "camera") \
+ _VERBOSE_TAG(gles, "hardware OpenGLES emulation") \
#define _VERBOSE_TAG(x,y) VERBOSE_##x,
typedef enum {
diff --git a/vl-android.c b/vl-android.c
index 32b5eac..4c2a433 100644
--- a/vl-android.c
+++ b/vl-android.c
@@ -65,6 +65,7 @@
#include "android/display-core.h"
#include "android/utils/timezone.h"
#include "android/snapshot.h"
+#include "android/opengles.h"
#include "targphys.h"
#include "tcpdump.h"
@@ -3813,6 +3814,29 @@ 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.
+ */
+ {
+ int gles_emul = 0;
+
+ if (android_hw->hw_gpu_enabled) {
+ if (android_initOpenglesEmulation() == 0) {
+ gles_emul = 1;
+ android_startOpenglesRenderer(android_hw->hw_lcd_width, android_hw->hw_lcd_height);
+ } else {
+ dwarning("Could not initialize OpenglES emulation, using software renderer.");
+ }
+ }
+ if (gles_emul) {
+ stralloc_add_str(kernel_params, " qemu.gles=1");
+ } else {
+ stralloc_add_str(kernel_params, " qemu.gles=0");
+ }
+ }
+
/* We always force qemu=1 when running inside QEMU */
stralloc_add_str(kernel_params, " qemu=1");