blob: 6f0556f068a328a8d6fe89f7c241c0e61f5acb20 [file] [log] [blame]
David 'Digit' Turnercb88e792011-08-26 01:35:14 +02001/* 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"
Andrew Hsiehafb01182012-05-04 11:55:11 +080015#include <assert.h>
Jesse Hall183e9272012-04-26 15:13:27 -070016
17/* Declared in "android/globals.h" */
18int android_gles_fast_pipes = 1;
19
20#if CONFIG_ANDROID_OPENGLES
21
David Turner7b56a4a2011-09-12 18:21:58 +020022#include "android/globals.h"
David 'Digit' Turnercb88e792011-08-26 01:35:14 +020023#include <android/utils/debug.h>
24#include <android/utils/path.h>
25#include <android/utils/bufprint.h>
26#include <android/utils/dll.h>
Jesse Hall183e9272012-04-26 15:13:27 -070027
28#define RENDER_API_NO_PROTOTYPES 1
Jesse Hall6699b682012-04-18 10:28:46 -070029#include <libOpenglRender/render_api.h>
Jesse Hall183e9272012-04-26 15:13:27 -070030
David 'Digit' Turnercb88e792011-08-26 01:35:14 +020031#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 */
Andrew Hsiehc7389bd2012-03-13 02:13:40 -070038#if HOST_LONG_BITS == 32
David 'Digit' Turnercb88e792011-08-26 01:35:14 +020039#define RENDERER_LIB_NAME "libOpenglRender"
Andrew Hsiehc7389bd2012-03-13 02:13:40 -070040#elif HOST_LONG_BITS == 64
41#define RENDERER_LIB_NAME "lib64OpenglRender"
42#else
43#error Unknown HOST_LONG_BITS
44#endif
David 'Digit' Turnercb88e792011-08-26 01:35:14 +020045
David 'Digit' Turnercb88e792011-08-26 01:35:14 +020046#define DYNLINK_FUNCTIONS \
Jesse Hall6699b682012-04-18 10:28:46 -070047 DYNLINK_FUNC(initLibrary) \
48 DYNLINK_FUNC(setStreamMode) \
49 DYNLINK_FUNC(initOpenGLRenderer) \
Jesse Hallba5c1f62012-05-08 15:44:35 -070050 DYNLINK_FUNC(setPostCallback) \
Jesse Hall733fffa2012-04-26 11:07:32 -070051 DYNLINK_FUNC(getHardwareStrings) \
Jesse Hall6699b682012-04-18 10:28:46 -070052 DYNLINK_FUNC(createOpenGLSubwindow) \
53 DYNLINK_FUNC(destroyOpenGLSubwindow) \
54 DYNLINK_FUNC(repaintOpenGLDisplay) \
55 DYNLINK_FUNC(stopOpenGLRenderer)
David 'Digit' Turnercb88e792011-08-26 01:35:14 +020056
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
Jesse Hall6699b682012-04-18 10:28:46 -070064/* Define the function pointers */
65#define DYNLINK_FUNC(name) \
66 static name##Fn name = NULL;
David 'Digit' Turnercb88e792011-08-26 01:35:14 +020067DYNLINK_FUNCTIONS
David 'Digit' Turnercb88e792011-08-26 01:35:14 +020068#undef DYNLINK_FUNC
69
70static int
71initOpenglesEmulationFuncs(ADynamicLibrary* rendererLib)
72{
73 void* symbol;
74 char* error;
Jesse Hall6699b682012-04-18 10:28:46 -070075
76#define DYNLINK_FUNC(name) \
77 symbol = adynamicLibrary_findSymbol(rendererLib, #name, &error); \
David 'Digit' Turnercb88e792011-08-26 01:35:14 +020078 if (symbol != NULL) { \
Jesse Hall6699b682012-04-18 10:28:46 -070079 name = symbol; \
David 'Digit' Turnercb88e792011-08-26 01:35:14 +020080 } 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
Jesse Hall6699b682012-04-18 10:28:46 -070087
David 'Digit' Turnercb88e792011-08-26 01:35:14 +020088 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
David Turner7b56a4a2011-09-12 18:21:58 +0200123 if (android_gles_fast_pipes) {
124#ifdef _WIN32
125 /* XXX: NEED Win32 pipe implementation */
126 setStreamMode(STREAM_MODE_TCP);
127#else
Jesse Hall6699b682012-04-18 10:28:46 -0700128 setStreamMode(STREAM_MODE_UNIX);
David Turner7b56a4a2011-09-12 18:21:58 +0200129#endif
130 } else {
Jesse Hall6699b682012-04-18 10:28:46 -0700131 setStreamMode(STREAM_MODE_TCP);
David Turner7b56a4a2011-09-12 18:21:58 +0200132 }
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200133 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
Jesse Hallba5c1f62012-05-08 15:44:35 -0700143android_startOpenglesRenderer(int width, int height)
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200144{
145 if (!rendererLib) {
146 D("Can't start OpenGLES renderer without support libraries");
147 return -1;
148 }
149
Jesse Hallba5c1f62012-05-08 15:44:35 -0700150 if (!initOpenGLRenderer(width, height, ANDROID_OPENGLES_BASE_PORT)) {
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200151 D("Can't start OpenGLES renderer?");
152 return -1;
153 }
154 return 0;
155}
156
Jesse Hallba5c1f62012-05-08 15:44:35 -0700157void
158android_setPostCallback(OnPostFunc onPost, void* onPostContext)
159{
160 if (rendererLib) {
161 setPostCallback(onPost, onPostContext);
162 }
163}
164
Jesse Hall733fffa2012-04-26 11:07:32 -0700165static 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
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200221void
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) {
Jesse Hall6699b682012-04-18 10:28:46 -0700233 int success = createOpenGLSubwindow((FBNativeWindowType)window, x, y, width, height, rotation);
234 return success ? 0 : -1;
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200235 } else {
236 return -1;
237 }
238}
239
240int
241android_hideOpenglesWindow(void)
242{
243 if (rendererLib) {
Jesse Hall6699b682012-04-18 10:28:46 -0700244 int success = destroyOpenGLSubwindow();
245 return success ? 0 : -1;
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200246 } else {
247 return -1;
248 }
249}
250
251void
252android_redrawOpenglesWindow(void)
253{
254 if (rendererLib) {
255 repaintOpenGLDisplay();
256 }
257}
David Turner7b56a4a2011-09-12 18:21:58 +0200258
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}
Jesse Hall183e9272012-04-26 15:13:27 -0700273
274#else // CONFIG_ANDROID_OPENGLES
275
276int android_initOpenglesEmulation(void)
277{
278 return -1;
279}
280
281int android_startOpenglesRenderer(int width, int height, OnPostFunc onPost, void* onPostContext)
282{
283 return -1;
284}
285
Andrew Hsiehafb01182012-05-04 11:55:11 +0800286void 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
Jesse Hall183e9272012-04-26 15:13:27 -0700295void 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