opengles.c revision 6674489666e2a5ca2f12a1c1015cd0bf3bd36494
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" */ 18int 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 */ 59extern int android_init_opengles_pipes(void); 60#endif 61 62static ADynamicLibrary* rendererLib; 63 64/* Define the function pointers */ 65#define DYNLINK_FUNC(name) \ 66 static name##Fn name = NULL; 67DYNLINK_FUNCTIONS 68#undef DYNLINK_FUNC 69 70static int 71initOpenglesEmulationFuncs(ADynamicLibrary* rendererLib) 72{ 73 void* symbol; 74 char* error; 75 76#define DYNLINK_FUNC(name) \ 77 symbol = adynamicLibrary_findSymbol(rendererLib, #name, &error); \ 78 if (symbol != NULL) { \ 79 name = symbol; \ 80 } else { \ 81 derror("GLES emulation: Could not find required symbol (%s): %s", #name, error); \ 82 free(error); \ 83 return -1; \ 84 } 85DYNLINK_FUNCTIONS 86#undef DYNLINK_FUNC 87 88 return 0; 89} 90 91int 92android_initOpenglesEmulation(void) 93{ 94 char* error = NULL; 95 96 if (rendererLib != NULL) 97 return 0; 98 99 D("Initializing hardware OpenGLES emulation support"); 100 101 rendererLib = adynamicLibrary_open(RENDERER_LIB_NAME, &error); 102 if (rendererLib == NULL) { 103 derror("Could not load OpenGLES emulation library: %s", error); 104 return -1; 105 } 106 107#ifndef CONFIG_STANDALONE_UI 108 android_init_opengles_pipes(); 109#endif 110 111 112 /* Resolve the functions */ 113 if (initOpenglesEmulationFuncs(rendererLib) < 0) { 114 derror("OpenGLES emulation library mismatch. Be sure to use the correct version!"); 115 goto BAD_EXIT; 116 } 117 118 if (!initLibrary()) { 119 derror("OpenGLES initialization failed!"); 120 goto BAD_EXIT; 121 } 122 123 if (android_gles_fast_pipes) { 124#ifdef _WIN32 125 /* XXX: NEED Win32 pipe implementation */ 126 setStreamMode(STREAM_MODE_TCP); 127#else 128 setStreamMode(STREAM_MODE_UNIX); 129#endif 130 } else { 131 setStreamMode(STREAM_MODE_TCP); 132 } 133 return 0; 134 135BAD_EXIT: 136 derror("OpenGLES emulation library could not be initialized!"); 137 adynamicLibrary_close(rendererLib); 138 rendererLib = NULL; 139 return -1; 140} 141 142int 143android_startOpenglesRenderer(int width, int height) 144{ 145 if (!rendererLib) { 146 D("Can't start OpenGLES renderer without support libraries"); 147 return -1; 148 } 149 150 if (!initOpenGLRenderer(width, height, ANDROID_OPENGLES_BASE_PORT)) { 151 D("Can't start OpenGLES renderer?"); 152 return -1; 153 } 154 return 0; 155} 156 157void 158android_setPostCallback(OnPostFunc onPost, void* onPostContext) 159{ 160 if (rendererLib) { 161 setPostCallback(onPost, onPostContext); 162 } 163} 164 165static void strncpy_safe(char* dst, const char* src, size_t n) 166{ 167 strncpy(dst, src, n); 168 dst[n-1] = '\0'; 169} 170 171static void extractBaseString(char* dst, const char* src, size_t dstSize) 172{ 173 size_t len = strlen(src); 174 const char* begin = strchr(src, '('); 175 const char* end = strrchr(src, ')'); 176 177 if (!begin || !end) { 178 strncpy_safe(dst, src, dstSize); 179 return; 180 } 181 begin += 1; 182 183 // "foo (bar)" 184 // ^ ^ 185 // b e 186 // = 5 8 187 // substring with NUL-terminator is end-begin+1 bytes 188 if (end - begin + 1 > dstSize) { 189 end = begin + dstSize - 1; 190 } 191 192 strncpy_safe(dst, begin, end - begin + 1); 193} 194 195void 196android_getOpenglesHardwareStrings(char* vendor, size_t vendorBufSize, 197 char* renderer, size_t rendererBufSize, 198 char* version, size_t versionBufSize) 199{ 200 const char *vendorSrc, *rendererSrc, *versionSrc; 201 202 getHardwareStrings(&vendorSrc, &rendererSrc, &versionSrc); 203 if (!vendorSrc) vendorSrc = ""; 204 if (!rendererSrc) rendererSrc = ""; 205 if (!versionSrc) versionSrc = ""; 206 207 /* Special case for the default ES to GL translators: extract the strings 208 * of the underlying OpenGL implementation. */ 209 if (strncmp(vendorSrc, "Google", 6) == 0 && 210 strncmp(rendererSrc, "Android Emulator OpenGL ES Translator", 37) == 0) { 211 extractBaseString(vendor, vendorSrc, vendorBufSize); 212 extractBaseString(renderer, rendererSrc, rendererBufSize); 213 extractBaseString(version, versionSrc, versionBufSize); 214 } else { 215 strncpy_safe(vendor, vendorSrc, vendorBufSize); 216 strncpy_safe(renderer, rendererSrc, rendererBufSize); 217 strncpy_safe(version, versionSrc, versionBufSize); 218 } 219} 220 221void 222android_stopOpenglesRenderer(void) 223{ 224 if (rendererLib) { 225 stopOpenGLRenderer(); 226 } 227} 228 229int 230android_showOpenglesWindow(void* window, int x, int y, int width, int height, float rotation) 231{ 232 if (rendererLib) { 233 int success = createOpenGLSubwindow((FBNativeWindowType)window, x, y, width, height, rotation); 234 return success ? 0 : -1; 235 } else { 236 return -1; 237 } 238} 239 240int 241android_hideOpenglesWindow(void) 242{ 243 if (rendererLib) { 244 int success = destroyOpenGLSubwindow(); 245 return success ? 0 : -1; 246 } else { 247 return -1; 248 } 249} 250 251void 252android_redrawOpenglesWindow(void) 253{ 254 if (rendererLib) { 255 repaintOpenGLDisplay(); 256 } 257} 258 259void 260android_gles_unix_path(char* buff, size_t buffsize, int port) 261{ 262 const char* user = getenv("USER"); 263 char *p = buff, *end = buff + buffsize; 264 265 /* The logic here must correspond to the one inside 266 * development/tools/emulator/opengl/shared/libOpenglCodecCommon/UnixStream.cpp */ 267 p = bufprint(p, end, "/tmp/"); 268 if (user && user[0]) { 269 p = bufprint(p, end, "android-%s/", user); 270 } 271 p = bufprint(p, end, "qemu-gles-%d", port); 272} 273 274#else // CONFIG_ANDROID_OPENGLES 275 276int android_initOpenglesEmulation(void) 277{ 278 return -1; 279} 280 281int android_startOpenglesRenderer(int width, int height) 282{ 283 return -1; 284} 285 286void android_getOpenglesHardwareStrings(char* vendor, size_t vendorBufSize, 287 char* renderer, size_t rendererBufSize, 288 char* version, size_t versionBufSize) 289{ 290 assert(vendorBufSize > 0 && rendererBufSize > 0 && versionBufSize > 0); 291 assert(vendor != NULL && renderer != NULL && version != NULL); 292 vendor[0] = renderer[0] = version[0] = 0; 293} 294 295void android_stopOpenglesRenderer(void) 296{} 297 298int android_showOpenglesWindow(void* window, int x, int y, int width, int height, float rotation) 299{ 300 return -1; 301} 302 303int android_hideOpenglesWindow(void) 304{ 305 return -1; 306} 307 308void android_redrawOpenglesWindow(void) 309{} 310 311void android_gles_unix_path(char* buff, size_t buffsize, int port) 312{ 313 buff[0] = '\0'; 314} 315 316#endif // !CONFIG_ANDROID_OPENGLES 317