blob: 25704299c716a0dd82fc6d54c88aa2c1f92c0c1e [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
David Turner7b56a4a2011-09-12 18:21:58 +020020#include "android/globals.h"
David 'Digit' Turnercb88e792011-08-26 01:35:14 +020021#include <android/utils/debug.h>
22#include <android/utils/path.h>
23#include <android/utils/bufprint.h>
24#include <android/utils/dll.h>
Jesse Hall183e9272012-04-26 15:13:27 -070025
David 'Digit' Turner6aff02b2014-02-18 12:45:57 +010026// NOTE: The declarations below should be equivalent to those in
27// <libOpenglRender/render_api_platform_types.h>
28#ifdef _WIN32
29#include <windows.h>
30typedef HDC FBNativeDisplayType;
31typedef 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.
35typedef uint32_t FBNativeWindowType;
36#elif defined(__APPLE__)
37typedef 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), ()) \
Jesse Hall183e9272012-04-26 15:13:27 -070062
David 'Digit' Turnercb88e792011-08-26 01:35:14 +020063#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 */
David 'Digit' Turner48fbbc02014-03-07 16:43:01 +010070#if UINTPTR_MAX == UINT32_MAX
David 'Digit' Turnercb88e792011-08-26 01:35:14 +020071#define RENDERER_LIB_NAME "libOpenglRender"
David 'Digit' Turner48fbbc02014-03-07 16:43:01 +010072#elif UINTPTR_MAX == UINT64_MAX
Andrew Hsiehc7389bd2012-03-13 02:13:40 -070073#define RENDERER_LIB_NAME "lib64OpenglRender"
74#else
David 'Digit' Turner48fbbc02014-03-07 16:43:01 +010075#error Unknown UINTPTR_MAX
Andrew Hsiehc7389bd2012-03-13 02:13:40 -070076#endif
David 'Digit' Turnercb88e792011-08-26 01:35:14 +020077
David 'Digit' Turner6aff02b2014-02-18 12:45:57 +010078// 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;
83RENDERER_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.
89static int
90initOpenglesEmulationFuncs(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)
105RENDERER_FUNCTIONS_LIST
106#undef FUNCTION_VOID_
107#undef FUNCTION_
108
109 return 0;
110}
111
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200112
113#ifndef CONFIG_STANDALONE_UI
114/* Defined in android/hw-pipe-net.c */
115extern int android_init_opengles_pipes(void);
116#endif
117
118static ADynamicLibrary* rendererLib;
Jesse Hall23a322d2012-05-08 12:00:20 -0700119static int rendererStarted;
Jesse Hall055adab2012-07-11 16:48:28 -0700120static char rendererAddress[256];
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200121
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200122int
123android_initOpenglesEmulation(void)
124{
125 char* error = NULL;
126
127 if (rendererLib != NULL)
128 return 0;
129
130 D("Initializing hardware OpenGLES emulation support");
131
132 rendererLib = adynamicLibrary_open(RENDERER_LIB_NAME, &error);
133 if (rendererLib == NULL) {
134 derror("Could not load OpenGLES emulation library: %s", error);
135 return -1;
136 }
137
138#ifndef CONFIG_STANDALONE_UI
139 android_init_opengles_pipes();
140#endif
141
142
143 /* Resolve the functions */
144 if (initOpenglesEmulationFuncs(rendererLib) < 0) {
145 derror("OpenGLES emulation library mismatch. Be sure to use the correct version!");
146 goto BAD_EXIT;
147 }
148
149 if (!initLibrary()) {
150 derror("OpenGLES initialization failed!");
151 goto BAD_EXIT;
152 }
153
David Turner7b56a4a2011-09-12 18:21:58 +0200154 if (android_gles_fast_pipes) {
155#ifdef _WIN32
156 /* XXX: NEED Win32 pipe implementation */
157 setStreamMode(STREAM_MODE_TCP);
158#else
Jesse Hall6699b682012-04-18 10:28:46 -0700159 setStreamMode(STREAM_MODE_UNIX);
David Turner7b56a4a2011-09-12 18:21:58 +0200160#endif
161 } else {
Jesse Hall6699b682012-04-18 10:28:46 -0700162 setStreamMode(STREAM_MODE_TCP);
David Turner7b56a4a2011-09-12 18:21:58 +0200163 }
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200164 return 0;
165
166BAD_EXIT:
167 derror("OpenGLES emulation library could not be initialized!");
168 adynamicLibrary_close(rendererLib);
169 rendererLib = NULL;
170 return -1;
171}
172
173int
Jesse Hallba5c1f62012-05-08 15:44:35 -0700174android_startOpenglesRenderer(int width, int height)
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200175{
176 if (!rendererLib) {
177 D("Can't start OpenGLES renderer without support libraries");
178 return -1;
179 }
180
Jesse Hall23a322d2012-05-08 12:00:20 -0700181 if (rendererStarted) {
182 return 0;
183 }
184
Jesse Hall055adab2012-07-11 16:48:28 -0700185 if (!initOpenGLRenderer(width, height, rendererAddress, sizeof(rendererAddress))) {
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200186 D("Can't start OpenGLES renderer?");
187 return -1;
188 }
Jesse Hall23a322d2012-05-08 12:00:20 -0700189
190 rendererStarted = 1;
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200191 return 0;
192}
193
Jesse Hallba5c1f62012-05-08 15:44:35 -0700194void
195android_setPostCallback(OnPostFunc onPost, void* onPostContext)
196{
197 if (rendererLib) {
198 setPostCallback(onPost, onPostContext);
199 }
200}
201
Jesse Hall733fffa2012-04-26 11:07:32 -0700202static void strncpy_safe(char* dst, const char* src, size_t n)
203{
204 strncpy(dst, src, n);
205 dst[n-1] = '\0';
206}
207
208static void extractBaseString(char* dst, const char* src, size_t dstSize)
209{
Jesse Hall733fffa2012-04-26 11:07:32 -0700210 const char* begin = strchr(src, '(');
211 const char* end = strrchr(src, ')');
212
213 if (!begin || !end) {
214 strncpy_safe(dst, src, dstSize);
215 return;
216 }
217 begin += 1;
218
219 // "foo (bar)"
220 // ^ ^
221 // b e
222 // = 5 8
223 // substring with NUL-terminator is end-begin+1 bytes
224 if (end - begin + 1 > dstSize) {
225 end = begin + dstSize - 1;
226 }
227
228 strncpy_safe(dst, begin, end - begin + 1);
229}
230
231void
232android_getOpenglesHardwareStrings(char* vendor, size_t vendorBufSize,
233 char* renderer, size_t rendererBufSize,
234 char* version, size_t versionBufSize)
235{
236 const char *vendorSrc, *rendererSrc, *versionSrc;
237
Jesse Hall23a322d2012-05-08 12:00:20 -0700238 assert(vendorBufSize > 0 && rendererBufSize > 0 && versionBufSize > 0);
239 assert(vendor != NULL && renderer != NULL && version != NULL);
240
241 if (!rendererStarted) {
242 D("Can't get OpenGL ES hardware strings when renderer not started");
Jesse Hall055adab2012-07-11 16:48:28 -0700243 vendor[0] = renderer[0] = version[0] = '\0';
Jesse Hall23a322d2012-05-08 12:00:20 -0700244 return;
245 }
246
Jesse Hall733fffa2012-04-26 11:07:32 -0700247 getHardwareStrings(&vendorSrc, &rendererSrc, &versionSrc);
248 if (!vendorSrc) vendorSrc = "";
249 if (!rendererSrc) rendererSrc = "";
250 if (!versionSrc) versionSrc = "";
251
252 /* Special case for the default ES to GL translators: extract the strings
253 * of the underlying OpenGL implementation. */
254 if (strncmp(vendorSrc, "Google", 6) == 0 &&
255 strncmp(rendererSrc, "Android Emulator OpenGL ES Translator", 37) == 0) {
256 extractBaseString(vendor, vendorSrc, vendorBufSize);
257 extractBaseString(renderer, rendererSrc, rendererBufSize);
258 extractBaseString(version, versionSrc, versionBufSize);
259 } else {
260 strncpy_safe(vendor, vendorSrc, vendorBufSize);
261 strncpy_safe(renderer, rendererSrc, rendererBufSize);
262 strncpy_safe(version, versionSrc, versionBufSize);
263 }
264}
265
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200266void
267android_stopOpenglesRenderer(void)
268{
Jesse Hall23a322d2012-05-08 12:00:20 -0700269 if (rendererStarted) {
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200270 stopOpenGLRenderer();
Jesse Hall23a322d2012-05-08 12:00:20 -0700271 rendererStarted = 0;
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200272 }
273}
274
275int
276android_showOpenglesWindow(void* window, int x, int y, int width, int height, float rotation)
277{
Jesse Hall23a322d2012-05-08 12:00:20 -0700278 if (rendererStarted) {
David 'Digit' Turner6aff02b2014-02-18 12:45:57 +0100279 int success = createOpenGLSubwindow((FBNativeWindowType)(uintptr_t)window, x, y, width, height, rotation);
Jesse Hall6699b682012-04-18 10:28:46 -0700280 return success ? 0 : -1;
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200281 } else {
282 return -1;
283 }
284}
285
286int
287android_hideOpenglesWindow(void)
288{
Jesse Hall23a322d2012-05-08 12:00:20 -0700289 if (rendererStarted) {
Jesse Hall6699b682012-04-18 10:28:46 -0700290 int success = destroyOpenGLSubwindow();
291 return success ? 0 : -1;
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200292 } else {
293 return -1;
294 }
295}
296
297void
298android_redrawOpenglesWindow(void)
299{
Jesse Hall23a322d2012-05-08 12:00:20 -0700300 if (rendererStarted) {
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200301 repaintOpenGLDisplay();
302 }
303}
David Turner7b56a4a2011-09-12 18:21:58 +0200304
305void
Jesse Hall055adab2012-07-11 16:48:28 -0700306android_gles_server_path(char* buff, size_t buffsize)
David Turner7b56a4a2011-09-12 18:21:58 +0200307{
Jesse Hall055adab2012-07-11 16:48:28 -0700308 strncpy_safe(buff, rendererAddress, buffsize);
David Turner7b56a4a2011-09-12 18:21:58 +0200309}