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