• 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 #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
initOpenglesEmulationFuncs(ADynamicLibrary * rendererLib)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
android_initOpenglesEmulation(void)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
android_startOpenglesRenderer(int width,int height)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
android_setPostCallback(OnPostFunc onPost,void * onPostContext)190 android_setPostCallback(OnPostFunc onPost, void* onPostContext)
191 {
192     if (rendererLib) {
193         setPostCallback(onPost, onPostContext);
194     }
195 }
196 
strncpy_safe(char * dst,const char * src,size_t n)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 
extractBaseString(char * dst,const char * src,size_t dstSize)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
android_getOpenglesHardwareStrings(char * vendor,size_t vendorBufSize,char * renderer,size_t rendererBufSize,char * version,size_t versionBufSize)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
android_stopOpenglesRenderer(void)262 android_stopOpenglesRenderer(void)
263 {
264     if (rendererStarted) {
265         stopOpenGLRenderer();
266         rendererStarted = 0;
267     }
268 }
269 
270 int
android_showOpenglesWindow(void * window,int x,int y,int width,int height,float rotation)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
android_hideOpenglesWindow(void)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
android_redrawOpenglesWindow(void)293 android_redrawOpenglesWindow(void)
294 {
295     if (rendererStarted) {
296         repaintOpenGLDisplay();
297     }
298 }
299 
300 void
android_gles_server_path(char * buff,size_t buffsize)301 android_gles_server_path(char* buff, size_t buffsize)
302 {
303     strncpy_safe(buff, rendererAddress, buffsize);
304 }
305