Add hw.gpu.enabled hardware property
This patch adds a new hardware property to enable GPU emulation
(named hw.gpu.enabled). It is currently disabled by default.
It also modifies the UI code to display the GL output properly
inside the UI window. And sets the kernel parameter qemu.gles
to either 0 or 1 to indicate to the guest system's GLES libraries
whether to use GPU emulation or fallback to the software renderer.
A future patch will also add auto-detection of desktop GL capabilities.
For example, if the emulator is started on a headless server without
an X11/GL display, hw.gpu.enabled will be forced to 'no', forcing the
guest to use the software renderer.
Another patch will allow to change the property from the command-line
for debugging purpose.
NOTE: If you want to test GPU emulation, change the default value of
the property in android/avd/hardware-properties.ini from 'no'
to 'yes'. You will need to run a ToT master AOSP tree with
the following pending patches applied:
https://review.source.android.com/25797
https://review.source.android.com/25154
https://review.source.android.com/25759
Change-Id: I1fa3512be24395244fd5068f2bf59ad54db5c7d5
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();
+ }
+}