• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
initOpenglesEmulationFuncs(ADynamicLibrary * rendererLib)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
android_initOpenglesEmulation(void)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
android_startOpenglesRenderer(int width,int height)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
android_setPostCallback(OnPostFunc onPost,void * onPostContext)166 android_setPostCallback(OnPostFunc onPost, void* onPostContext)
167 {
168     if (rendererLib) {
169         setPostCallback(onPost, onPostContext);
170     }
171 }
172 
strncpy_safe(char * dst,const char * src,size_t n)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 
extractBaseString(char * dst,const char * src,size_t dstSize)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
android_getOpenglesHardwareStrings(char * vendor,size_t vendorBufSize,char * renderer,size_t rendererBufSize,char * version,size_t versionBufSize)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
android_stopOpenglesRenderer(void)238 android_stopOpenglesRenderer(void)
239 {
240     if (rendererStarted) {
241         stopOpenGLRenderer();
242         rendererStarted = 0;
243     }
244 }
245 
246 int
android_showOpenglesWindow(void * window,int x,int y,int width,int height,float rotation)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
android_hideOpenglesWindow(void)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
android_redrawOpenglesWindow(void)269 android_redrawOpenglesWindow(void)
270 {
271     if (rendererStarted) {
272         repaintOpenGLDisplay();
273     }
274 }
275 
276 void
android_gles_server_path(char * buff,size_t buffsize)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 
android_initOpenglesEmulation(void)284 int android_initOpenglesEmulation(void)
285 {
286     return -1;
287 }
288 
android_startOpenglesRenderer(int width,int height)289 int android_startOpenglesRenderer(int width, int height)
290 {
291     return -1;
292 }
293 
294 void
android_setPostCallback(OnPostFunc onPost,void * onPostContext)295 android_setPostCallback(OnPostFunc onPost, void* onPostContext)
296 {
297 }
298 
android_getOpenglesHardwareStrings(char * vendor,size_t vendorBufSize,char * renderer,size_t rendererBufSize,char * version,size_t versionBufSize)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 
android_stopOpenglesRenderer(void)308 void android_stopOpenglesRenderer(void)
309 {}
310 
android_showOpenglesWindow(void * window,int x,int y,int width,int height,float rotation)311 int android_showOpenglesWindow(void* window, int x, int y, int width, int height, float rotation)
312 {
313     return -1;
314 }
315 
android_hideOpenglesWindow(void)316 int android_hideOpenglesWindow(void)
317 {
318     return -1;
319 }
320 
android_redrawOpenglesWindow(void)321 void android_redrawOpenglesWindow(void)
322 {}
323 
android_gles_server_path(char * buff,size_t buffsize)324 void android_gles_server_path(char* buff, size_t buffsize)
325 {
326     buff[0] = '\0';
327 }
328 
329 #endif // !CONFIG_ANDROID_OPENGLES
330