blob: 521dc031840590462ac0c6688a010e334ca9d020 [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"
Jesse Hall183e9272012-04-26 15:13:27 -070015
16/* Declared in "android/globals.h" */
17int android_gles_fast_pipes = 1;
18
19#if CONFIG_ANDROID_OPENGLES
20
David Turner7b56a4a2011-09-12 18:21:58 +020021#include "android/globals.h"
David 'Digit' Turnercb88e792011-08-26 01:35:14 +020022#include <android/utils/debug.h>
23#include <android/utils/path.h>
24#include <android/utils/bufprint.h>
25#include <android/utils/dll.h>
Jesse Hall183e9272012-04-26 15:13:27 -070026
27#define RENDER_API_NO_PROTOTYPES 1
Jesse Hall6699b682012-04-18 10:28:46 -070028#include <libOpenglRender/render_api.h>
Jesse Hall183e9272012-04-26 15:13:27 -070029
David 'Digit' Turnercb88e792011-08-26 01:35:14 +020030#include <stdio.h>
31#include <stdlib.h>
32
33#define D(...) VERBOSE_PRINT(init,__VA_ARGS__)
34#define DD(...) VERBOSE_PRINT(gles,__VA_ARGS__)
35
36/* Name of the GLES rendering library we're going to use */
Andrew Hsiehc7389bd2012-03-13 02:13:40 -070037#if HOST_LONG_BITS == 32
David 'Digit' Turnercb88e792011-08-26 01:35:14 +020038#define RENDERER_LIB_NAME "libOpenglRender"
Andrew Hsiehc7389bd2012-03-13 02:13:40 -070039#elif HOST_LONG_BITS == 64
40#define RENDERER_LIB_NAME "lib64OpenglRender"
41#else
42#error Unknown HOST_LONG_BITS
43#endif
David 'Digit' Turnercb88e792011-08-26 01:35:14 +020044
David 'Digit' Turnercb88e792011-08-26 01:35:14 +020045#define DYNLINK_FUNCTIONS \
Jesse Hall6699b682012-04-18 10:28:46 -070046 DYNLINK_FUNC(initLibrary) \
47 DYNLINK_FUNC(setStreamMode) \
48 DYNLINK_FUNC(initOpenGLRenderer) \
Jesse Hall733fffa2012-04-26 11:07:32 -070049 DYNLINK_FUNC(getHardwareStrings) \
Jesse Hall6699b682012-04-18 10:28:46 -070050 DYNLINK_FUNC(createOpenGLSubwindow) \
51 DYNLINK_FUNC(destroyOpenGLSubwindow) \
52 DYNLINK_FUNC(repaintOpenGLDisplay) \
53 DYNLINK_FUNC(stopOpenGLRenderer)
David 'Digit' Turnercb88e792011-08-26 01:35:14 +020054
55#ifndef CONFIG_STANDALONE_UI
56/* Defined in android/hw-pipe-net.c */
57extern int android_init_opengles_pipes(void);
58#endif
59
60static ADynamicLibrary* rendererLib;
61
Jesse Hall6699b682012-04-18 10:28:46 -070062/* Define the function pointers */
63#define DYNLINK_FUNC(name) \
64 static name##Fn name = NULL;
David 'Digit' Turnercb88e792011-08-26 01:35:14 +020065DYNLINK_FUNCTIONS
David 'Digit' Turnercb88e792011-08-26 01:35:14 +020066#undef DYNLINK_FUNC
67
68static int
69initOpenglesEmulationFuncs(ADynamicLibrary* rendererLib)
70{
71 void* symbol;
72 char* error;
Jesse Hall6699b682012-04-18 10:28:46 -070073
74#define DYNLINK_FUNC(name) \
75 symbol = adynamicLibrary_findSymbol(rendererLib, #name, &error); \
David 'Digit' Turnercb88e792011-08-26 01:35:14 +020076 if (symbol != NULL) { \
Jesse Hall6699b682012-04-18 10:28:46 -070077 name = symbol; \
David 'Digit' Turnercb88e792011-08-26 01:35:14 +020078 } else { \
79 derror("GLES emulation: Could not find required symbol (%s): %s", #name, error); \
80 free(error); \
81 return -1; \
82 }
83DYNLINK_FUNCTIONS
84#undef DYNLINK_FUNC
Jesse Hall6699b682012-04-18 10:28:46 -070085
David 'Digit' Turnercb88e792011-08-26 01:35:14 +020086 return 0;
87}
88
89int
90android_initOpenglesEmulation(void)
91{
92 char* error = NULL;
93
94 if (rendererLib != NULL)
95 return 0;
96
97 D("Initializing hardware OpenGLES emulation support");
98
99 rendererLib = adynamicLibrary_open(RENDERER_LIB_NAME, &error);
100 if (rendererLib == NULL) {
101 derror("Could not load OpenGLES emulation library: %s", error);
102 return -1;
103 }
104
105#ifndef CONFIG_STANDALONE_UI
106 android_init_opengles_pipes();
107#endif
108
109
110 /* Resolve the functions */
111 if (initOpenglesEmulationFuncs(rendererLib) < 0) {
112 derror("OpenGLES emulation library mismatch. Be sure to use the correct version!");
113 goto BAD_EXIT;
114 }
115
116 if (!initLibrary()) {
117 derror("OpenGLES initialization failed!");
118 goto BAD_EXIT;
119 }
120
David Turner7b56a4a2011-09-12 18:21:58 +0200121 if (android_gles_fast_pipes) {
122#ifdef _WIN32
123 /* XXX: NEED Win32 pipe implementation */
124 setStreamMode(STREAM_MODE_TCP);
125#else
Jesse Hall6699b682012-04-18 10:28:46 -0700126 setStreamMode(STREAM_MODE_UNIX);
David Turner7b56a4a2011-09-12 18:21:58 +0200127#endif
128 } else {
Jesse Hall6699b682012-04-18 10:28:46 -0700129 setStreamMode(STREAM_MODE_TCP);
David Turner7b56a4a2011-09-12 18:21:58 +0200130 }
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200131 return 0;
132
133BAD_EXIT:
134 derror("OpenGLES emulation library could not be initialized!");
135 adynamicLibrary_close(rendererLib);
136 rendererLib = NULL;
137 return -1;
138}
139
140int
Jesse Hall07ca7c22012-04-25 22:05:07 -0700141android_startOpenglesRenderer(int width, int height, OnPostFunc onPost, void* onPostContext)
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200142{
143 if (!rendererLib) {
144 D("Can't start OpenGLES renderer without support libraries");
145 return -1;
146 }
147
Jesse Hall6699b682012-04-18 10:28:46 -0700148 if (!initOpenGLRenderer(width, height, ANDROID_OPENGLES_BASE_PORT, onPost, onPostContext)) {
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200149 D("Can't start OpenGLES renderer?");
150 return -1;
151 }
152 return 0;
153}
154
Jesse Hall733fffa2012-04-26 11:07:32 -0700155static void strncpy_safe(char* dst, const char* src, size_t n)
156{
157 strncpy(dst, src, n);
158 dst[n-1] = '\0';
159}
160
161static void extractBaseString(char* dst, const char* src, size_t dstSize)
162{
163 size_t len = strlen(src);
164 const char* begin = strchr(src, '(');
165 const char* end = strrchr(src, ')');
166
167 if (!begin || !end) {
168 strncpy_safe(dst, src, dstSize);
169 return;
170 }
171 begin += 1;
172
173 // "foo (bar)"
174 // ^ ^
175 // b e
176 // = 5 8
177 // substring with NUL-terminator is end-begin+1 bytes
178 if (end - begin + 1 > dstSize) {
179 end = begin + dstSize - 1;
180 }
181
182 strncpy_safe(dst, begin, end - begin + 1);
183}
184
185void
186android_getOpenglesHardwareStrings(char* vendor, size_t vendorBufSize,
187 char* renderer, size_t rendererBufSize,
188 char* version, size_t versionBufSize)
189{
190 const char *vendorSrc, *rendererSrc, *versionSrc;
191
192 getHardwareStrings(&vendorSrc, &rendererSrc, &versionSrc);
193 if (!vendorSrc) vendorSrc = "";
194 if (!rendererSrc) rendererSrc = "";
195 if (!versionSrc) versionSrc = "";
196
197 /* Special case for the default ES to GL translators: extract the strings
198 * of the underlying OpenGL implementation. */
199 if (strncmp(vendorSrc, "Google", 6) == 0 &&
200 strncmp(rendererSrc, "Android Emulator OpenGL ES Translator", 37) == 0) {
201 extractBaseString(vendor, vendorSrc, vendorBufSize);
202 extractBaseString(renderer, rendererSrc, rendererBufSize);
203 extractBaseString(version, versionSrc, versionBufSize);
204 } else {
205 strncpy_safe(vendor, vendorSrc, vendorBufSize);
206 strncpy_safe(renderer, rendererSrc, rendererBufSize);
207 strncpy_safe(version, versionSrc, versionBufSize);
208 }
209}
210
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200211void
212android_stopOpenglesRenderer(void)
213{
214 if (rendererLib) {
215 stopOpenGLRenderer();
216 }
217}
218
219int
220android_showOpenglesWindow(void* window, int x, int y, int width, int height, float rotation)
221{
222 if (rendererLib) {
Jesse Hall6699b682012-04-18 10:28:46 -0700223 int success = createOpenGLSubwindow((FBNativeWindowType)window, x, y, width, height, rotation);
224 return success ? 0 : -1;
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200225 } else {
226 return -1;
227 }
228}
229
230int
231android_hideOpenglesWindow(void)
232{
233 if (rendererLib) {
Jesse Hall6699b682012-04-18 10:28:46 -0700234 int success = destroyOpenGLSubwindow();
235 return success ? 0 : -1;
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200236 } else {
237 return -1;
238 }
239}
240
241void
242android_redrawOpenglesWindow(void)
243{
244 if (rendererLib) {
245 repaintOpenGLDisplay();
246 }
247}
David Turner7b56a4a2011-09-12 18:21:58 +0200248
249void
250android_gles_unix_path(char* buff, size_t buffsize, int port)
251{
252 const char* user = getenv("USER");
253 char *p = buff, *end = buff + buffsize;
254
255 /* The logic here must correspond to the one inside
256 * development/tools/emulator/opengl/shared/libOpenglCodecCommon/UnixStream.cpp */
257 p = bufprint(p, end, "/tmp/");
258 if (user && user[0]) {
259 p = bufprint(p, end, "android-%s/", user);
260 }
261 p = bufprint(p, end, "qemu-gles-%d", port);
262}
Jesse Hall183e9272012-04-26 15:13:27 -0700263
264#else // CONFIG_ANDROID_OPENGLES
265
266int android_initOpenglesEmulation(void)
267{
268 return -1;
269}
270
271int android_startOpenglesRenderer(int width, int height, OnPostFunc onPost, void* onPostContext)
272{
273 return -1;
274}
275
276void android_stopOpenglesRenderer(void)
277{}
278
279int android_showOpenglesWindow(void* window, int x, int y, int width, int height, float rotation)
280{
281 return -1;
282}
283
284int android_hideOpenglesWindow(void)
285{
286 return -1;
287}
288
289void android_redrawOpenglesWindow(void)
290{}
291
292void android_gles_unix_path(char* buff, size_t buffsize, int port)
293{
294 buff[0] = '\0';
295}
296
297#endif // !CONFIG_ANDROID_OPENGLES