1 /* Copyright (C) 2011 The Android Open Source Project 2 ** 3 ** This software is licensed under the terms of the GNU General Public 4 ** License version 2, as published by the Free Software Foundation, and 5 ** may be copied, distributed, and modified under those terms. 6 ** 7 ** This program is distributed in the hope that it will be useful, 8 ** but WITHOUT ANY WARRANTY; without even the implied warranty of 9 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 ** GNU General Public License for more details. 11 */ 12 13 #include "config-host.h" 14 #include "android/opengles.h" 15 #include "android/globals.h" 16 #include <android/utils/debug.h> 17 #include <android/utils/path.h> 18 #include <android/utils/bufprint.h> 19 #include <android/utils/dll.h> 20 #include <stdio.h> 21 #include <stdlib.h> 22 23 #define D(...) VERBOSE_PRINT(init,__VA_ARGS__) 24 #define DD(...) VERBOSE_PRINT(gles,__VA_ARGS__) 25 26 /* Declared in "android/globals.h" */ 27 int android_gles_fast_pipes = 1; 28 29 /* Name of the GLES rendering library we're going to use */ 30 #if HOST_LONG_BITS == 32 31 #define RENDERER_LIB_NAME "libOpenglRender" 32 #elif HOST_LONG_BITS == 64 33 #define RENDERER_LIB_NAME "lib64OpenglRender" 34 #else 35 #error Unknown HOST_LONG_BITS 36 #endif 37 38 /* These definitions *must* match those under: 39 * development/tools/emulator/opengl/host/include/libOpenglRender/render_api.h 40 */ 41 #define DYNLINK_FUNCTIONS \ 42 DYNLINK_FUNC(int,initLibrary,(void),(),return) \ 43 DYNLINK_FUNC(int,setStreamMode,(int a),(a),return) \ 44 DYNLINK_FUNC(int,initOpenGLRenderer,(int width, int height, int port, OnPostFn onPost, void* onPostContext),(width,height,port,onPost,onPostContext),return) \ 45 DYNLINK_FUNC(int,createOpenGLSubwindow,(void* window, int x, int y, int width, int height, float zRot),(window,x,y,width,height,zRot),return)\ 46 DYNLINK_FUNC(int,destroyOpenGLSubwindow,(void),(),return)\ 47 DYNLINK_FUNC(void,repaintOpenGLDisplay,(void),(),)\ 48 DYNLINK_FUNC(void,stopOpenGLRenderer,(void),(),) 49 50 #define STREAM_MODE_DEFAULT 0 51 #define STREAM_MODE_TCP 1 52 #define STREAM_MODE_UNIX 2 53 #define STREAM_MODE_PIPE 3 54 55 #ifndef CONFIG_STANDALONE_UI 56 /* Defined in android/hw-pipe-net.c */ 57 extern int android_init_opengles_pipes(void); 58 #endif 59 60 static ADynamicLibrary* rendererLib; 61 62 /* Define the pointers and the wrapper functions to call them */ 63 #define DYNLINK_FUNC(result,name,sig,params,ret) \ 64 static result (*_ptr_##name) sig; \ 65 static result name sig { \ 66 ret (*_ptr_##name) params ; \ 67 } 68 69 DYNLINK_FUNCTIONS 70 71 #undef DYNLINK_FUNC 72 73 static int 74 initOpenglesEmulationFuncs(ADynamicLibrary* rendererLib) 75 { 76 void* symbol; 77 char* error; 78 #define DYNLINK_FUNC(result,name,sig,params,ret) \ 79 symbol = adynamicLibrary_findSymbol( rendererLib, #name, &error ); \ 80 if (symbol != NULL) { \ 81 _ptr_##name = symbol; \ 82 } else { \ 83 derror("GLES emulation: Could not find required symbol (%s): %s", #name, error); \ 84 free(error); \ 85 return -1; \ 86 } 87 DYNLINK_FUNCTIONS 88 #undef DYNLINK_FUNC 89 return 0; 90 } 91 92 int 93 android_initOpenglesEmulation(void) 94 { 95 char* error = NULL; 96 97 if (rendererLib != NULL) 98 return 0; 99 100 D("Initializing hardware OpenGLES emulation support"); 101 102 rendererLib = adynamicLibrary_open(RENDERER_LIB_NAME, &error); 103 if (rendererLib == NULL) { 104 derror("Could not load OpenGLES emulation library: %s", error); 105 return -1; 106 } 107 108 #ifndef CONFIG_STANDALONE_UI 109 android_init_opengles_pipes(); 110 #endif 111 112 113 /* Resolve the functions */ 114 if (initOpenglesEmulationFuncs(rendererLib) < 0) { 115 derror("OpenGLES emulation library mismatch. Be sure to use the correct version!"); 116 goto BAD_EXIT; 117 } 118 119 if (!initLibrary()) { 120 derror("OpenGLES initialization failed!"); 121 goto BAD_EXIT; 122 } 123 124 if (android_gles_fast_pipes) { 125 #ifdef _WIN32 126 /* XXX: NEED Win32 pipe implementation */ 127 setStreamMode(STREAM_MODE_TCP); 128 #else 129 setStreamMode(STREAM_MODE_UNIX); 130 #endif 131 } else { 132 setStreamMode(STREAM_MODE_TCP); 133 } 134 return 0; 135 136 BAD_EXIT: 137 derror("OpenGLES emulation library could not be initialized!"); 138 adynamicLibrary_close(rendererLib); 139 rendererLib = NULL; 140 return -1; 141 } 142 143 int 144 android_startOpenglesRenderer(int width, int height, OnPostFn onPost, void* onPostContext) 145 { 146 if (!rendererLib) { 147 D("Can't start OpenGLES renderer without support libraries"); 148 return -1; 149 } 150 151 if (initOpenGLRenderer(width, height, ANDROID_OPENGLES_BASE_PORT, onPost, onPostContext) != 0) { 152 D("Can't start OpenGLES renderer?"); 153 return -1; 154 } 155 return 0; 156 } 157 158 void 159 android_stopOpenglesRenderer(void) 160 { 161 if (rendererLib) { 162 stopOpenGLRenderer(); 163 } 164 } 165 166 int 167 android_showOpenglesWindow(void* window, int x, int y, int width, int height, float rotation) 168 { 169 if (rendererLib) { 170 return createOpenGLSubwindow(window, x, y, width, height, rotation); 171 } else { 172 return -1; 173 } 174 } 175 176 int 177 android_hideOpenglesWindow(void) 178 { 179 if (rendererLib) { 180 return destroyOpenGLSubwindow(); 181 } else { 182 return -1; 183 } 184 } 185 186 void 187 android_redrawOpenglesWindow(void) 188 { 189 if (rendererLib) { 190 repaintOpenGLDisplay(); 191 } 192 } 193 194 void 195 android_gles_unix_path(char* buff, size_t buffsize, int port) 196 { 197 const char* user = getenv("USER"); 198 char *p = buff, *end = buff + buffsize; 199 200 /* The logic here must correspond to the one inside 201 * development/tools/emulator/opengl/shared/libOpenglCodecCommon/UnixStream.cpp */ 202 p = bufprint(p, end, "/tmp/"); 203 if (user && user[0]) { 204 p = bufprint(p, end, "android-%s/", user); 205 } 206 p = bufprint(p, end, "qemu-gles-%d", port); 207 } 208