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