blob: 70e3f8cb541e47debc0ab2e47c672851ac063b04 [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 Hall733fffa2012-04-26 11:07:32 -070050 DYNLINK_FUNC(getHardwareStrings) \
Jesse Hall6699b682012-04-18 10:28:46 -070051 DYNLINK_FUNC(createOpenGLSubwindow) \
52 DYNLINK_FUNC(destroyOpenGLSubwindow) \
53 DYNLINK_FUNC(repaintOpenGLDisplay) \
54 DYNLINK_FUNC(stopOpenGLRenderer)
David 'Digit' Turnercb88e792011-08-26 01:35:14 +020055
56#ifndef CONFIG_STANDALONE_UI
57/* Defined in android/hw-pipe-net.c */
58extern int android_init_opengles_pipes(void);
59#endif
60
61static ADynamicLibrary* rendererLib;
62
Jesse Hall6699b682012-04-18 10:28:46 -070063/* Define the function pointers */
64#define DYNLINK_FUNC(name) \
65 static name##Fn name = NULL;
David 'Digit' Turnercb88e792011-08-26 01:35:14 +020066DYNLINK_FUNCTIONS
David 'Digit' Turnercb88e792011-08-26 01:35:14 +020067#undef DYNLINK_FUNC
68
69static int
70initOpenglesEmulationFuncs(ADynamicLibrary* rendererLib)
71{
72 void* symbol;
73 char* error;
Jesse Hall6699b682012-04-18 10:28:46 -070074
75#define DYNLINK_FUNC(name) \
76 symbol = adynamicLibrary_findSymbol(rendererLib, #name, &error); \
David 'Digit' Turnercb88e792011-08-26 01:35:14 +020077 if (symbol != NULL) { \
Jesse Hall6699b682012-04-18 10:28:46 -070078 name = symbol; \
David 'Digit' Turnercb88e792011-08-26 01:35:14 +020079 } else { \
80 derror("GLES emulation: Could not find required symbol (%s): %s", #name, error); \
81 free(error); \
82 return -1; \
83 }
84DYNLINK_FUNCTIONS
85#undef DYNLINK_FUNC
Jesse Hall6699b682012-04-18 10:28:46 -070086
David 'Digit' Turnercb88e792011-08-26 01:35:14 +020087 return 0;
88}
89
90int
91android_initOpenglesEmulation(void)
92{
93 char* error = NULL;
94
95 if (rendererLib != NULL)
96 return 0;
97
98 D("Initializing hardware OpenGLES emulation support");
99
100 rendererLib = adynamicLibrary_open(RENDERER_LIB_NAME, &error);
101 if (rendererLib == NULL) {
102 derror("Could not load OpenGLES emulation library: %s", error);
103 return -1;
104 }
105
106#ifndef CONFIG_STANDALONE_UI
107 android_init_opengles_pipes();
108#endif
109
110
111 /* Resolve the functions */
112 if (initOpenglesEmulationFuncs(rendererLib) < 0) {
113 derror("OpenGLES emulation library mismatch. Be sure to use the correct version!");
114 goto BAD_EXIT;
115 }
116
117 if (!initLibrary()) {
118 derror("OpenGLES initialization failed!");
119 goto BAD_EXIT;
120 }
121
David Turner7b56a4a2011-09-12 18:21:58 +0200122 if (android_gles_fast_pipes) {
123#ifdef _WIN32
124 /* XXX: NEED Win32 pipe implementation */
125 setStreamMode(STREAM_MODE_TCP);
126#else
Jesse Hall6699b682012-04-18 10:28:46 -0700127 setStreamMode(STREAM_MODE_UNIX);
David Turner7b56a4a2011-09-12 18:21:58 +0200128#endif
129 } else {
Jesse Hall6699b682012-04-18 10:28:46 -0700130 setStreamMode(STREAM_MODE_TCP);
David Turner7b56a4a2011-09-12 18:21:58 +0200131 }
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200132 return 0;
133
134BAD_EXIT:
135 derror("OpenGLES emulation library could not be initialized!");
136 adynamicLibrary_close(rendererLib);
137 rendererLib = NULL;
138 return -1;
139}
140
141int
Jesse Hall07ca7c22012-04-25 22:05:07 -0700142android_startOpenglesRenderer(int width, int height, OnPostFunc onPost, void* onPostContext)
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200143{
144 if (!rendererLib) {
145 D("Can't start OpenGLES renderer without support libraries");
146 return -1;
147 }
148
Jesse Hall6699b682012-04-18 10:28:46 -0700149 if (!initOpenGLRenderer(width, height, ANDROID_OPENGLES_BASE_PORT, onPost, onPostContext)) {
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200150 D("Can't start OpenGLES renderer?");
151 return -1;
152 }
153 return 0;
154}
155
Jesse Hall733fffa2012-04-26 11:07:32 -0700156static void strncpy_safe(char* dst, const char* src, size_t n)
157{
158 strncpy(dst, src, n);
159 dst[n-1] = '\0';
160}
161
162static void extractBaseString(char* dst, const char* src, size_t dstSize)
163{
164 size_t len = strlen(src);
165 const char* begin = strchr(src, '(');
166 const char* end = strrchr(src, ')');
167
168 if (!begin || !end) {
169 strncpy_safe(dst, src, dstSize);
170 return;
171 }
172 begin += 1;
173
174 // "foo (bar)"
175 // ^ ^
176 // b e
177 // = 5 8
178 // substring with NUL-terminator is end-begin+1 bytes
179 if (end - begin + 1 > dstSize) {
180 end = begin + dstSize - 1;
181 }
182
183 strncpy_safe(dst, begin, end - begin + 1);
184}
185
186void
187android_getOpenglesHardwareStrings(char* vendor, size_t vendorBufSize,
188 char* renderer, size_t rendererBufSize,
189 char* version, size_t versionBufSize)
190{
191 const char *vendorSrc, *rendererSrc, *versionSrc;
192
193 getHardwareStrings(&vendorSrc, &rendererSrc, &versionSrc);
194 if (!vendorSrc) vendorSrc = "";
195 if (!rendererSrc) rendererSrc = "";
196 if (!versionSrc) versionSrc = "";
197
198 /* Special case for the default ES to GL translators: extract the strings
199 * of the underlying OpenGL implementation. */
200 if (strncmp(vendorSrc, "Google", 6) == 0 &&
201 strncmp(rendererSrc, "Android Emulator OpenGL ES Translator", 37) == 0) {
202 extractBaseString(vendor, vendorSrc, vendorBufSize);
203 extractBaseString(renderer, rendererSrc, rendererBufSize);
204 extractBaseString(version, versionSrc, versionBufSize);
205 } else {
206 strncpy_safe(vendor, vendorSrc, vendorBufSize);
207 strncpy_safe(renderer, rendererSrc, rendererBufSize);
208 strncpy_safe(version, versionSrc, versionBufSize);
209 }
210}
211
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200212void
213android_stopOpenglesRenderer(void)
214{
215 if (rendererLib) {
216 stopOpenGLRenderer();
217 }
218}
219
220int
221android_showOpenglesWindow(void* window, int x, int y, int width, int height, float rotation)
222{
223 if (rendererLib) {
Jesse Hall6699b682012-04-18 10:28:46 -0700224 int success = createOpenGLSubwindow((FBNativeWindowType)window, x, y, width, height, rotation);
225 return success ? 0 : -1;
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200226 } else {
227 return -1;
228 }
229}
230
231int
232android_hideOpenglesWindow(void)
233{
234 if (rendererLib) {
Jesse Hall6699b682012-04-18 10:28:46 -0700235 int success = destroyOpenGLSubwindow();
236 return success ? 0 : -1;
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200237 } else {
238 return -1;
239 }
240}
241
242void
243android_redrawOpenglesWindow(void)
244{
245 if (rendererLib) {
246 repaintOpenGLDisplay();
247 }
248}
David Turner7b56a4a2011-09-12 18:21:58 +0200249
250void
251android_gles_unix_path(char* buff, size_t buffsize, int port)
252{
253 const char* user = getenv("USER");
254 char *p = buff, *end = buff + buffsize;
255
256 /* The logic here must correspond to the one inside
257 * development/tools/emulator/opengl/shared/libOpenglCodecCommon/UnixStream.cpp */
258 p = bufprint(p, end, "/tmp/");
259 if (user && user[0]) {
260 p = bufprint(p, end, "android-%s/", user);
261 }
262 p = bufprint(p, end, "qemu-gles-%d", port);
263}
Jesse Hall183e9272012-04-26 15:13:27 -0700264
265#else // CONFIG_ANDROID_OPENGLES
266
267int android_initOpenglesEmulation(void)
268{
269 return -1;
270}
271
272int android_startOpenglesRenderer(int width, int height, OnPostFunc onPost, void* onPostContext)
273{
274 return -1;
275}
276
Andrew Hsiehafb01182012-05-04 11:55:11 +0800277void android_getOpenglesHardwareStrings(char* vendor, size_t vendorBufSize,
278 char* renderer, size_t rendererBufSize,
279 char* version, size_t versionBufSize)
280{
281 assert(vendorBufSize > 0 && rendererBufSize > 0 && versionBufSize > 0);
282 assert(vendor != NULL && renderer != NULL && version != NULL);
283 vendor[0] = renderer[0] = version[0] = 0;
284}
285
Jesse Hall183e9272012-04-26 15:13:27 -0700286void android_stopOpenglesRenderer(void)
287{}
288
289int android_showOpenglesWindow(void* window, int x, int y, int width, int height, float rotation)
290{
291 return -1;
292}
293
294int android_hideOpenglesWindow(void)
295{
296 return -1;
297}
298
299void android_redrawOpenglesWindow(void)
300{}
301
302void android_gles_unix_path(char* buff, size_t buffsize, int port)
303{
304 buff[0] = '\0';
305}
306
307#endif // !CONFIG_ANDROID_OPENGLES