blob: 1fa6421b9b9871e7e7c5ed870cbe05c1f7a96762 [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;
Jesse Hall23a322d2012-05-08 12:00:20 -070063static int rendererStarted;
Jesse Hall055adab2012-07-11 16:48:28 -070064static char rendererAddress[256];
David 'Digit' Turnercb88e792011-08-26 01:35:14 +020065
Jesse Hall6699b682012-04-18 10:28:46 -070066/* Define the function pointers */
67#define DYNLINK_FUNC(name) \
68 static name##Fn name = NULL;
David 'Digit' Turnercb88e792011-08-26 01:35:14 +020069DYNLINK_FUNCTIONS
David 'Digit' Turnercb88e792011-08-26 01:35:14 +020070#undef DYNLINK_FUNC
71
72static int
73initOpenglesEmulationFuncs(ADynamicLibrary* rendererLib)
74{
75 void* symbol;
76 char* error;
Jesse Hall6699b682012-04-18 10:28:46 -070077
78#define DYNLINK_FUNC(name) \
79 symbol = adynamicLibrary_findSymbol(rendererLib, #name, &error); \
David 'Digit' Turnercb88e792011-08-26 01:35:14 +020080 if (symbol != NULL) { \
Jesse Hall6699b682012-04-18 10:28:46 -070081 name = symbol; \
David 'Digit' Turnercb88e792011-08-26 01:35:14 +020082 } else { \
83 derror("GLES emulation: Could not find required symbol (%s): %s", #name, error); \
84 free(error); \
85 return -1; \
86 }
87DYNLINK_FUNCTIONS
88#undef DYNLINK_FUNC
Jesse Hall6699b682012-04-18 10:28:46 -070089
David 'Digit' Turnercb88e792011-08-26 01:35:14 +020090 return 0;
91}
92
93int
94android_initOpenglesEmulation(void)
95{
96 char* error = NULL;
97
98 if (rendererLib != NULL)
99 return 0;
100
101 D("Initializing hardware OpenGLES emulation support");
102
103 rendererLib = adynamicLibrary_open(RENDERER_LIB_NAME, &error);
104 if (rendererLib == NULL) {
105 derror("Could not load OpenGLES emulation library: %s", error);
106 return -1;
107 }
108
109#ifndef CONFIG_STANDALONE_UI
110 android_init_opengles_pipes();
111#endif
112
113
114 /* Resolve the functions */
115 if (initOpenglesEmulationFuncs(rendererLib) < 0) {
116 derror("OpenGLES emulation library mismatch. Be sure to use the correct version!");
117 goto BAD_EXIT;
118 }
119
120 if (!initLibrary()) {
121 derror("OpenGLES initialization failed!");
122 goto BAD_EXIT;
123 }
124
David Turner7b56a4a2011-09-12 18:21:58 +0200125 if (android_gles_fast_pipes) {
126#ifdef _WIN32
127 /* XXX: NEED Win32 pipe implementation */
128 setStreamMode(STREAM_MODE_TCP);
129#else
Jesse Hall6699b682012-04-18 10:28:46 -0700130 setStreamMode(STREAM_MODE_UNIX);
David Turner7b56a4a2011-09-12 18:21:58 +0200131#endif
132 } else {
Jesse Hall6699b682012-04-18 10:28:46 -0700133 setStreamMode(STREAM_MODE_TCP);
David Turner7b56a4a2011-09-12 18:21:58 +0200134 }
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200135 return 0;
136
137BAD_EXIT:
138 derror("OpenGLES emulation library could not be initialized!");
139 adynamicLibrary_close(rendererLib);
140 rendererLib = NULL;
141 return -1;
142}
143
144int
Jesse Hallba5c1f62012-05-08 15:44:35 -0700145android_startOpenglesRenderer(int width, int height)
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200146{
147 if (!rendererLib) {
148 D("Can't start OpenGLES renderer without support libraries");
149 return -1;
150 }
151
Jesse Hall23a322d2012-05-08 12:00:20 -0700152 if (rendererStarted) {
153 return 0;
154 }
155
Jesse Hall055adab2012-07-11 16:48:28 -0700156 if (!initOpenGLRenderer(width, height, rendererAddress, sizeof(rendererAddress))) {
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200157 D("Can't start OpenGLES renderer?");
158 return -1;
159 }
Jesse Hall23a322d2012-05-08 12:00:20 -0700160
161 rendererStarted = 1;
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200162 return 0;
163}
164
Jesse Hallba5c1f62012-05-08 15:44:35 -0700165void
166android_setPostCallback(OnPostFunc onPost, void* onPostContext)
167{
168 if (rendererLib) {
169 setPostCallback(onPost, onPostContext);
170 }
171}
172
Jesse Hall733fffa2012-04-26 11:07:32 -0700173static void strncpy_safe(char* dst, const char* src, size_t n)
174{
175 strncpy(dst, src, n);
176 dst[n-1] = '\0';
177}
178
179static void extractBaseString(char* dst, const char* src, size_t dstSize)
180{
Jesse Hall733fffa2012-04-26 11:07:32 -0700181 const char* begin = strchr(src, '(');
182 const char* end = strrchr(src, ')');
183
184 if (!begin || !end) {
185 strncpy_safe(dst, src, dstSize);
186 return;
187 }
188 begin += 1;
189
190 // "foo (bar)"
191 // ^ ^
192 // b e
193 // = 5 8
194 // substring with NUL-terminator is end-begin+1 bytes
195 if (end - begin + 1 > dstSize) {
196 end = begin + dstSize - 1;
197 }
198
199 strncpy_safe(dst, begin, end - begin + 1);
200}
201
202void
203android_getOpenglesHardwareStrings(char* vendor, size_t vendorBufSize,
204 char* renderer, size_t rendererBufSize,
205 char* version, size_t versionBufSize)
206{
207 const char *vendorSrc, *rendererSrc, *versionSrc;
208
Jesse Hall23a322d2012-05-08 12:00:20 -0700209 assert(vendorBufSize > 0 && rendererBufSize > 0 && versionBufSize > 0);
210 assert(vendor != NULL && renderer != NULL && version != NULL);
211
212 if (!rendererStarted) {
213 D("Can't get OpenGL ES hardware strings when renderer not started");
Jesse Hall055adab2012-07-11 16:48:28 -0700214 vendor[0] = renderer[0] = version[0] = '\0';
Jesse Hall23a322d2012-05-08 12:00:20 -0700215 return;
216 }
217
Jesse Hall733fffa2012-04-26 11:07:32 -0700218 getHardwareStrings(&vendorSrc, &rendererSrc, &versionSrc);
219 if (!vendorSrc) vendorSrc = "";
220 if (!rendererSrc) rendererSrc = "";
221 if (!versionSrc) versionSrc = "";
222
223 /* Special case for the default ES to GL translators: extract the strings
224 * of the underlying OpenGL implementation. */
225 if (strncmp(vendorSrc, "Google", 6) == 0 &&
226 strncmp(rendererSrc, "Android Emulator OpenGL ES Translator", 37) == 0) {
227 extractBaseString(vendor, vendorSrc, vendorBufSize);
228 extractBaseString(renderer, rendererSrc, rendererBufSize);
229 extractBaseString(version, versionSrc, versionBufSize);
230 } else {
231 strncpy_safe(vendor, vendorSrc, vendorBufSize);
232 strncpy_safe(renderer, rendererSrc, rendererBufSize);
233 strncpy_safe(version, versionSrc, versionBufSize);
234 }
235}
236
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200237void
238android_stopOpenglesRenderer(void)
239{
Jesse Hall23a322d2012-05-08 12:00:20 -0700240 if (rendererStarted) {
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200241 stopOpenGLRenderer();
Jesse Hall23a322d2012-05-08 12:00:20 -0700242 rendererStarted = 0;
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200243 }
244}
245
246int
247android_showOpenglesWindow(void* window, int x, int y, int width, int height, float rotation)
248{
Jesse Hall23a322d2012-05-08 12:00:20 -0700249 if (rendererStarted) {
Jesse Hall6699b682012-04-18 10:28:46 -0700250 int success = createOpenGLSubwindow((FBNativeWindowType)window, x, y, width, height, rotation);
251 return success ? 0 : -1;
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200252 } else {
253 return -1;
254 }
255}
256
257int
258android_hideOpenglesWindow(void)
259{
Jesse Hall23a322d2012-05-08 12:00:20 -0700260 if (rendererStarted) {
Jesse Hall6699b682012-04-18 10:28:46 -0700261 int success = destroyOpenGLSubwindow();
262 return success ? 0 : -1;
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200263 } else {
264 return -1;
265 }
266}
267
268void
269android_redrawOpenglesWindow(void)
270{
Jesse Hall23a322d2012-05-08 12:00:20 -0700271 if (rendererStarted) {
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200272 repaintOpenGLDisplay();
273 }
274}
David Turner7b56a4a2011-09-12 18:21:58 +0200275
276void
Jesse Hall055adab2012-07-11 16:48:28 -0700277android_gles_server_path(char* buff, size_t buffsize)
David Turner7b56a4a2011-09-12 18:21:58 +0200278{
Jesse Hall055adab2012-07-11 16:48:28 -0700279 strncpy_safe(buff, rendererAddress, buffsize);
David Turner7b56a4a2011-09-12 18:21:58 +0200280}
Jesse Hall183e9272012-04-26 15:13:27 -0700281
282#else // CONFIG_ANDROID_OPENGLES
283
284int android_initOpenglesEmulation(void)
285{
286 return -1;
287}
288
Vladimir Chtchetkine66744892012-05-11 05:47:46 -0700289int android_startOpenglesRenderer(int width, int height)
Jesse Hall183e9272012-04-26 15:13:27 -0700290{
291 return -1;
292}
293
Vladimir Chtchetkine2c4c30e2012-05-11 06:56:43 -0700294void
295android_setPostCallback(OnPostFunc onPost, void* onPostContext)
296{
297}
298
Andrew Hsiehafb01182012-05-04 11:55:11 +0800299void android_getOpenglesHardwareStrings(char* vendor, size_t vendorBufSize,
300 char* renderer, size_t rendererBufSize,
301 char* version, size_t versionBufSize)
302{
303 assert(vendorBufSize > 0 && rendererBufSize > 0 && versionBufSize > 0);
304 assert(vendor != NULL && renderer != NULL && version != NULL);
305 vendor[0] = renderer[0] = version[0] = 0;
306}
307
Jesse Hall183e9272012-04-26 15:13:27 -0700308void android_stopOpenglesRenderer(void)
309{}
310
311int android_showOpenglesWindow(void* window, int x, int y, int width, int height, float rotation)
312{
313 return -1;
314}
315
316int android_hideOpenglesWindow(void)
317{
318 return -1;
319}
320
321void android_redrawOpenglesWindow(void)
322{}
323
Jesse Hall055adab2012-07-11 16:48:28 -0700324void android_gles_server_path(char* buff, size_t buffsize)
Jesse Hall183e9272012-04-26 15:13:27 -0700325{
326 buff[0] = '\0';
327}
328
329#endif // !CONFIG_ANDROID_OPENGLES