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 <assert.h> 16 17 /* Declared in "android/globals.h" */ 18 int android_gles_fast_pipes = 1; 19 20 #if CONFIG_ANDROID_OPENGLES 21 22 #include "android/globals.h" 23 #include <android/utils/debug.h> 24 #include <android/utils/path.h> 25 #include <android/utils/bufprint.h> 26 #include <android/utils/dll.h> 27 28 #define RENDER_API_NO_PROTOTYPES 1 29 #include <libOpenglRender/render_api.h> 30 31 #include <stdio.h> 32 #include <stdlib.h> 33 34 #define D(...) VERBOSE_PRINT(init,__VA_ARGS__) 35 #define DD(...) VERBOSE_PRINT(gles,__VA_ARGS__) 36 37 /* Name of the GLES rendering library we're going to use */ 38 #if HOST_LONG_BITS == 32 39 #define RENDERER_LIB_NAME "libOpenglRender" 40 #elif HOST_LONG_BITS == 64 41 #define RENDERER_LIB_NAME "lib64OpenglRender" 42 #else 43 #error Unknown HOST_LONG_BITS 44 #endif 45 46 #define DYNLINK_FUNCTIONS \ 47 DYNLINK_FUNC(initLibrary) \ 48 DYNLINK_FUNC(setStreamMode) \ 49 DYNLINK_FUNC(initOpenGLRenderer) \ 50 DYNLINK_FUNC(setPostCallback) \ 51 DYNLINK_FUNC(getHardwareStrings) \ 52 DYNLINK_FUNC(createOpenGLSubwindow) \ 53 DYNLINK_FUNC(destroyOpenGLSubwindow) \ 54 DYNLINK_FUNC(repaintOpenGLDisplay) \ 55 DYNLINK_FUNC(stopOpenGLRenderer) 56 57 #ifndef CONFIG_STANDALONE_UI 58 /* Defined in android/hw-pipe-net.c */ 59 extern int android_init_opengles_pipes(void); 60 #endif 61 62 static ADynamicLibrary* rendererLib; 63 static int rendererStarted; 64 static char rendererAddress[256]; 65 66 /* Define the function pointers */ 67 #define DYNLINK_FUNC(name) \ 68 static name##Fn name = NULL; 69 DYNLINK_FUNCTIONS 70 #undef DYNLINK_FUNC 71 72 static int 73 initOpenglesEmulationFuncs(ADynamicLibrary* rendererLib) 74 { 75 void* symbol; 76 char* error; 77 78 #define DYNLINK_FUNC(name) \ 79 symbol = adynamicLibrary_findSymbol(rendererLib, #name, &error); \ 80 if (symbol != NULL) { \ 81 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 90 return 0; 91 } 92 93 int 94 android_initOpenglesEmulation(void) 95 { 96 char* error = NULL; 97 98 if (rendererLib != NULL) 99 return 0; 100 101 D("Initializing hardware OpenGLES emulation support"); 102 103 rendererLib = adynamicLibrary_open(RENDERER_LIB_NAME, &error); 104 if (rendererLib == NULL) { 105 derror("Could not load OpenGLES emulation library: %s", error); 106 return -1; 107 } 108 109 #ifndef CONFIG_STANDALONE_UI 110 android_init_opengles_pipes(); 111 #endif 112 113 114 /* Resolve the functions */ 115 if (initOpenglesEmulationFuncs(rendererLib) < 0) { 116 derror("OpenGLES emulation library mismatch. Be sure to use the correct version!"); 117 goto BAD_EXIT; 118 } 119 120 if (!initLibrary()) { 121 derror("OpenGLES initialization failed!"); 122 goto BAD_EXIT; 123 } 124 125 if (android_gles_fast_pipes) { 126 #ifdef _WIN32 127 /* XXX: NEED Win32 pipe implementation */ 128 setStreamMode(STREAM_MODE_TCP); 129 #else 130 setStreamMode(STREAM_MODE_UNIX); 131 #endif 132 } else { 133 setStreamMode(STREAM_MODE_TCP); 134 } 135 return 0; 136 137 BAD_EXIT: 138 derror("OpenGLES emulation library could not be initialized!"); 139 adynamicLibrary_close(rendererLib); 140 rendererLib = NULL; 141 return -1; 142 } 143 144 int 145 android_startOpenglesRenderer(int width, int height) 146 { 147 if (!rendererLib) { 148 D("Can't start OpenGLES renderer without support libraries"); 149 return -1; 150 } 151 152 if (rendererStarted) { 153 return 0; 154 } 155 156 if (!initOpenGLRenderer(width, height, rendererAddress, sizeof(rendererAddress))) { 157 D("Can't start OpenGLES renderer?"); 158 return -1; 159 } 160 161 rendererStarted = 1; 162 return 0; 163 } 164 165 void 166 android_setPostCallback(OnPostFunc onPost, void* onPostContext) 167 { 168 if (rendererLib) { 169 setPostCallback(onPost, onPostContext); 170 } 171 } 172 173 static void strncpy_safe(char* dst, const char* src, size_t n) 174 { 175 strncpy(dst, src, n); 176 dst[n-1] = '\0'; 177 } 178 179 static void extractBaseString(char* dst, const char* src, size_t dstSize) 180 { 181 const char* begin = strchr(src, '('); 182 const char* end = strrchr(src, ')'); 183 184 if (!begin || !end) { 185 strncpy_safe(dst, src, dstSize); 186 return; 187 } 188 begin += 1; 189 190 // "foo (bar)" 191 // ^ ^ 192 // b e 193 // = 5 8 194 // substring with NUL-terminator is end-begin+1 bytes 195 if (end - begin + 1 > dstSize) { 196 end = begin + dstSize - 1; 197 } 198 199 strncpy_safe(dst, begin, end - begin + 1); 200 } 201 202 void 203 android_getOpenglesHardwareStrings(char* vendor, size_t vendorBufSize, 204 char* renderer, size_t rendererBufSize, 205 char* version, size_t versionBufSize) 206 { 207 const char *vendorSrc, *rendererSrc, *versionSrc; 208 209 assert(vendorBufSize > 0 && rendererBufSize > 0 && versionBufSize > 0); 210 assert(vendor != NULL && renderer != NULL && version != NULL); 211 212 if (!rendererStarted) { 213 D("Can't get OpenGL ES hardware strings when renderer not started"); 214 vendor[0] = renderer[0] = version[0] = '\0'; 215 return; 216 } 217 218 getHardwareStrings(&vendorSrc, &rendererSrc, &versionSrc); 219 if (!vendorSrc) vendorSrc = ""; 220 if (!rendererSrc) rendererSrc = ""; 221 if (!versionSrc) versionSrc = ""; 222 223 /* Special case for the default ES to GL translators: extract the strings 224 * of the underlying OpenGL implementation. */ 225 if (strncmp(vendorSrc, "Google", 6) == 0 && 226 strncmp(rendererSrc, "Android Emulator OpenGL ES Translator", 37) == 0) { 227 extractBaseString(vendor, vendorSrc, vendorBufSize); 228 extractBaseString(renderer, rendererSrc, rendererBufSize); 229 extractBaseString(version, versionSrc, versionBufSize); 230 } else { 231 strncpy_safe(vendor, vendorSrc, vendorBufSize); 232 strncpy_safe(renderer, rendererSrc, rendererBufSize); 233 strncpy_safe(version, versionSrc, versionBufSize); 234 } 235 } 236 237 void 238 android_stopOpenglesRenderer(void) 239 { 240 if (rendererStarted) { 241 stopOpenGLRenderer(); 242 rendererStarted = 0; 243 } 244 } 245 246 int 247 android_showOpenglesWindow(void* window, int x, int y, int width, int height, float rotation) 248 { 249 if (rendererStarted) { 250 int success = createOpenGLSubwindow((FBNativeWindowType)window, x, y, width, height, rotation); 251 return success ? 0 : -1; 252 } else { 253 return -1; 254 } 255 } 256 257 int 258 android_hideOpenglesWindow(void) 259 { 260 if (rendererStarted) { 261 int success = destroyOpenGLSubwindow(); 262 return success ? 0 : -1; 263 } else { 264 return -1; 265 } 266 } 267 268 void 269 android_redrawOpenglesWindow(void) 270 { 271 if (rendererStarted) { 272 repaintOpenGLDisplay(); 273 } 274 } 275 276 void 277 android_gles_server_path(char* buff, size_t buffsize) 278 { 279 strncpy_safe(buff, rendererAddress, buffsize); 280 } 281 282 #else // CONFIG_ANDROID_OPENGLES 283 284 int android_initOpenglesEmulation(void) 285 { 286 return -1; 287 } 288 289 int android_startOpenglesRenderer(int width, int height) 290 { 291 return -1; 292 } 293 294 void 295 android_setPostCallback(OnPostFunc onPost, void* onPostContext) 296 { 297 } 298 299 void android_getOpenglesHardwareStrings(char* vendor, size_t vendorBufSize, 300 char* renderer, size_t rendererBufSize, 301 char* version, size_t versionBufSize) 302 { 303 assert(vendorBufSize > 0 && rendererBufSize > 0 && versionBufSize > 0); 304 assert(vendor != NULL && renderer != NULL && version != NULL); 305 vendor[0] = renderer[0] = version[0] = 0; 306 } 307 308 void android_stopOpenglesRenderer(void) 309 {} 310 311 int android_showOpenglesWindow(void* window, int x, int y, int width, int height, float rotation) 312 { 313 return -1; 314 } 315 316 int android_hideOpenglesWindow(void) 317 { 318 return -1; 319 } 320 321 void android_redrawOpenglesWindow(void) 322 {} 323 324 void android_gles_server_path(char* buff, size_t buffsize) 325 { 326 buff[0] = '\0'; 327 } 328 329 #endif // !CONFIG_ANDROID_OPENGLES 330