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 #define RENDERER_LIB_NAME "libOpenglRender" 31 32 /* These definitions *must* match those under: 33 * development/tools/emulator/opengl/host/include/libOpenglRender/render_api.h 34 */ 35 #define DYNLINK_FUNCTIONS \ 36 DYNLINK_FUNC(int,initLibrary,(void),(),return) \ 37 DYNLINK_FUNC(int,setStreamMode,(int a),(a),return) \ 38 DYNLINK_FUNC(int,initOpenGLRenderer,(int width, int height, int port),(width,height,port),return) \ 39 DYNLINK_FUNC(int,createOpenGLSubwindow,(void* window, int x, int y, int width, int height, float zRot),(window,x,y,width,height,zRot),return)\ 40 DYNLINK_FUNC(int,destroyOpenGLSubwindow,(void),(),return)\ 41 DYNLINK_FUNC(void,repaintOpenGLDisplay,(void),(),)\ 42 DYNLINK_FUNC(void,stopOpenGLRenderer,(void),(),) 43 44 #define STREAM_MODE_DEFAULT 0 45 #define STREAM_MODE_TCP 1 46 #define STREAM_MODE_UNIX 2 47 #define STREAM_MODE_PIPE 3 48 49 #ifndef CONFIG_STANDALONE_UI 50 /* Defined in android/hw-pipe-net.c */ 51 extern int android_init_opengles_pipes(void); 52 #endif 53 54 static ADynamicLibrary* rendererLib; 55 56 /* Define the pointers and the wrapper functions to call them */ 57 #define DYNLINK_FUNC(result,name,sig,params,ret) \ 58 static result (*_ptr_##name) sig; \ 59 static result name sig { \ 60 ret (*_ptr_##name) params ; \ 61 } 62 63 DYNLINK_FUNCTIONS 64 65 #undef DYNLINK_FUNC 66 67 static int 68 initOpenglesEmulationFuncs(ADynamicLibrary* rendererLib) 69 { 70 void* symbol; 71 char* error; 72 #define DYNLINK_FUNC(result,name,sig,params,ret) \ 73 symbol = adynamicLibrary_findSymbol( rendererLib, #name, &error ); \ 74 if (symbol != NULL) { \ 75 _ptr_##name = symbol; \ 76 } else { \ 77 derror("GLES emulation: Could not find required symbol (%s): %s", #name, error); \ 78 free(error); \ 79 return -1; \ 80 } 81 DYNLINK_FUNCTIONS 82 #undef DYNLINK_FUNC 83 return 0; 84 } 85 86 int 87 android_initOpenglesEmulation(void) 88 { 89 char* error = NULL; 90 91 if (rendererLib != NULL) 92 return 0; 93 94 D("Initializing hardware OpenGLES emulation support"); 95 96 rendererLib = adynamicLibrary_open(RENDERER_LIB_NAME, &error); 97 if (rendererLib == NULL) { 98 derror("Could not load OpenGLES emulation library: %s", error); 99 return -1; 100 } 101 102 #ifndef CONFIG_STANDALONE_UI 103 android_init_opengles_pipes(); 104 #endif 105 106 107 /* Resolve the functions */ 108 if (initOpenglesEmulationFuncs(rendererLib) < 0) { 109 derror("OpenGLES emulation library mismatch. Be sure to use the correct version!"); 110 goto BAD_EXIT; 111 } 112 113 if (!initLibrary()) { 114 derror("OpenGLES initialization failed!"); 115 goto BAD_EXIT; 116 } 117 118 if (android_gles_fast_pipes) { 119 #ifdef _WIN32 120 /* XXX: NEED Win32 pipe implementation */ 121 setStreamMode(STREAM_MODE_TCP); 122 #else 123 setStreamMode(STREAM_MODE_UNIX); 124 #endif 125 } else { 126 setStreamMode(STREAM_MODE_TCP); 127 } 128 return 0; 129 130 BAD_EXIT: 131 derror("OpenGLES emulation library could not be initialized!"); 132 adynamicLibrary_close(rendererLib); 133 rendererLib = NULL; 134 return -1; 135 } 136 137 int 138 android_startOpenglesRenderer(int width, int height) 139 { 140 if (!rendererLib) { 141 D("Can't start OpenGLES renderer without support libraries"); 142 return -1; 143 } 144 145 if (initOpenGLRenderer(width, height,ANDROID_OPENGLES_BASE_PORT) != 0) { 146 D("Can't start OpenGLES renderer?"); 147 return -1; 148 } 149 return 0; 150 } 151 152 void 153 android_stopOpenglesRenderer(void) 154 { 155 if (rendererLib) { 156 stopOpenGLRenderer(); 157 } 158 } 159 160 int 161 android_showOpenglesWindow(void* window, int x, int y, int width, int height, float rotation) 162 { 163 if (rendererLib) { 164 return createOpenGLSubwindow(window, x, y, width, height, rotation); 165 } else { 166 return -1; 167 } 168 } 169 170 int 171 android_hideOpenglesWindow(void) 172 { 173 if (rendererLib) { 174 return destroyOpenGLSubwindow(); 175 } else { 176 return -1; 177 } 178 } 179 180 void 181 android_redrawOpenglesWindow(void) 182 { 183 if (rendererLib) { 184 repaintOpenGLDisplay(); 185 } 186 } 187 188 void 189 android_gles_unix_path(char* buff, size_t buffsize, int port) 190 { 191 const char* user = getenv("USER"); 192 char *p = buff, *end = buff + buffsize; 193 194 /* The logic here must correspond to the one inside 195 * development/tools/emulator/opengl/shared/libOpenglCodecCommon/UnixStream.cpp */ 196 p = bufprint(p, end, "/tmp/"); 197 if (user && user[0]) { 198 p = bufprint(p, end, "android-%s/", user); 199 } 200 p = bufprint(p, end, "qemu-gles-%d", port); 201 } 202