blob: 0d7855ca0147464dd0208216573ffb8b844bff42 [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
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200113/* Defined in android/hw-pipe-net.c */
114extern int android_init_opengles_pipes(void);
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200115
116static ADynamicLibrary* rendererLib;
Jesse Hall23a322d2012-05-08 12:00:20 -0700117static int rendererStarted;
Jesse Hall055adab2012-07-11 16:48:28 -0700118static char rendererAddress[256];
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200119
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200120int
121android_initOpenglesEmulation(void)
122{
123 char* error = NULL;
124
125 if (rendererLib != NULL)
126 return 0;
127
128 D("Initializing hardware OpenGLES emulation support");
129
130 rendererLib = adynamicLibrary_open(RENDERER_LIB_NAME, &error);
131 if (rendererLib == NULL) {
132 derror("Could not load OpenGLES emulation library: %s", error);
133 return -1;
134 }
135
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200136 android_init_opengles_pipes();
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200137
138 /* Resolve the functions */
139 if (initOpenglesEmulationFuncs(rendererLib) < 0) {
140 derror("OpenGLES emulation library mismatch. Be sure to use the correct version!");
141 goto BAD_EXIT;
142 }
143
144 if (!initLibrary()) {
145 derror("OpenGLES initialization failed!");
146 goto BAD_EXIT;
147 }
148
David Turner7b56a4a2011-09-12 18:21:58 +0200149 if (android_gles_fast_pipes) {
150#ifdef _WIN32
151 /* XXX: NEED Win32 pipe implementation */
152 setStreamMode(STREAM_MODE_TCP);
153#else
Jesse Hall6699b682012-04-18 10:28:46 -0700154 setStreamMode(STREAM_MODE_UNIX);
David Turner7b56a4a2011-09-12 18:21:58 +0200155#endif
156 } else {
Jesse Hall6699b682012-04-18 10:28:46 -0700157 setStreamMode(STREAM_MODE_TCP);
David Turner7b56a4a2011-09-12 18:21:58 +0200158 }
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200159 return 0;
160
161BAD_EXIT:
162 derror("OpenGLES emulation library could not be initialized!");
163 adynamicLibrary_close(rendererLib);
164 rendererLib = NULL;
165 return -1;
166}
167
168int
Jesse Hallba5c1f62012-05-08 15:44:35 -0700169android_startOpenglesRenderer(int width, int height)
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200170{
171 if (!rendererLib) {
172 D("Can't start OpenGLES renderer without support libraries");
173 return -1;
174 }
175
Jesse Hall23a322d2012-05-08 12:00:20 -0700176 if (rendererStarted) {
177 return 0;
178 }
179
Jesse Hall055adab2012-07-11 16:48:28 -0700180 if (!initOpenGLRenderer(width, height, rendererAddress, sizeof(rendererAddress))) {
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200181 D("Can't start OpenGLES renderer?");
182 return -1;
183 }
Jesse Hall23a322d2012-05-08 12:00:20 -0700184
185 rendererStarted = 1;
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200186 return 0;
187}
188
Jesse Hallba5c1f62012-05-08 15:44:35 -0700189void
190android_setPostCallback(OnPostFunc onPost, void* onPostContext)
191{
192 if (rendererLib) {
193 setPostCallback(onPost, onPostContext);
194 }
195}
196
Jesse Hall733fffa2012-04-26 11:07:32 -0700197static void strncpy_safe(char* dst, const char* src, size_t n)
198{
199 strncpy(dst, src, n);
200 dst[n-1] = '\0';
201}
202
203static void extractBaseString(char* dst, const char* src, size_t dstSize)
204{
Jesse Hall733fffa2012-04-26 11:07:32 -0700205 const char* begin = strchr(src, '(');
206 const char* end = strrchr(src, ')');
207
208 if (!begin || !end) {
209 strncpy_safe(dst, src, dstSize);
210 return;
211 }
212 begin += 1;
213
214 // "foo (bar)"
215 // ^ ^
216 // b e
217 // = 5 8
218 // substring with NUL-terminator is end-begin+1 bytes
219 if (end - begin + 1 > dstSize) {
220 end = begin + dstSize - 1;
221 }
222
223 strncpy_safe(dst, begin, end - begin + 1);
224}
225
226void
227android_getOpenglesHardwareStrings(char* vendor, size_t vendorBufSize,
228 char* renderer, size_t rendererBufSize,
229 char* version, size_t versionBufSize)
230{
231 const char *vendorSrc, *rendererSrc, *versionSrc;
232
Jesse Hall23a322d2012-05-08 12:00:20 -0700233 assert(vendorBufSize > 0 && rendererBufSize > 0 && versionBufSize > 0);
234 assert(vendor != NULL && renderer != NULL && version != NULL);
235
236 if (!rendererStarted) {
237 D("Can't get OpenGL ES hardware strings when renderer not started");
Jesse Hall055adab2012-07-11 16:48:28 -0700238 vendor[0] = renderer[0] = version[0] = '\0';
Jesse Hall23a322d2012-05-08 12:00:20 -0700239 return;
240 }
241
Jesse Hall733fffa2012-04-26 11:07:32 -0700242 getHardwareStrings(&vendorSrc, &rendererSrc, &versionSrc);
243 if (!vendorSrc) vendorSrc = "";
244 if (!rendererSrc) rendererSrc = "";
245 if (!versionSrc) versionSrc = "";
246
247 /* Special case for the default ES to GL translators: extract the strings
248 * of the underlying OpenGL implementation. */
249 if (strncmp(vendorSrc, "Google", 6) == 0 &&
250 strncmp(rendererSrc, "Android Emulator OpenGL ES Translator", 37) == 0) {
251 extractBaseString(vendor, vendorSrc, vendorBufSize);
252 extractBaseString(renderer, rendererSrc, rendererBufSize);
253 extractBaseString(version, versionSrc, versionBufSize);
254 } else {
255 strncpy_safe(vendor, vendorSrc, vendorBufSize);
256 strncpy_safe(renderer, rendererSrc, rendererBufSize);
257 strncpy_safe(version, versionSrc, versionBufSize);
258 }
259}
260
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200261void
262android_stopOpenglesRenderer(void)
263{
Jesse Hall23a322d2012-05-08 12:00:20 -0700264 if (rendererStarted) {
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200265 stopOpenGLRenderer();
Jesse Hall23a322d2012-05-08 12:00:20 -0700266 rendererStarted = 0;
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200267 }
268}
269
270int
271android_showOpenglesWindow(void* window, int x, int y, int width, int height, float rotation)
272{
Jesse Hall23a322d2012-05-08 12:00:20 -0700273 if (rendererStarted) {
David 'Digit' Turner6aff02b2014-02-18 12:45:57 +0100274 int success = createOpenGLSubwindow((FBNativeWindowType)(uintptr_t)window, x, y, width, height, rotation);
Jesse Hall6699b682012-04-18 10:28:46 -0700275 return success ? 0 : -1;
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200276 } else {
277 return -1;
278 }
279}
280
281int
282android_hideOpenglesWindow(void)
283{
Jesse Hall23a322d2012-05-08 12:00:20 -0700284 if (rendererStarted) {
Jesse Hall6699b682012-04-18 10:28:46 -0700285 int success = destroyOpenGLSubwindow();
286 return success ? 0 : -1;
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200287 } else {
288 return -1;
289 }
290}
291
292void
293android_redrawOpenglesWindow(void)
294{
Jesse Hall23a322d2012-05-08 12:00:20 -0700295 if (rendererStarted) {
David 'Digit' Turnercb88e792011-08-26 01:35:14 +0200296 repaintOpenGLDisplay();
297 }
298}
David Turner7b56a4a2011-09-12 18:21:58 +0200299
300void
Jesse Hall055adab2012-07-11 16:48:28 -0700301android_gles_server_path(char* buff, size_t buffsize)
David Turner7b56a4a2011-09-12 18:21:58 +0200302{
Jesse Hall055adab2012-07-11 16:48:28 -0700303 strncpy_safe(buff, rendererAddress, buffsize);
David Turner7b56a4a2011-09-12 18:21:58 +0200304}