1cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner/* Copyright (C) 2011 The Android Open Source Project
2cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner**
3cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner** This software is licensed under the terms of the GNU General Public
4cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner** License version 2, as published by the Free Software Foundation, and
5cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner** may be copied, distributed, and modified under those terms.
6cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner**
7cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner** This program is distributed in the hope that it will be useful,
8cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner** but WITHOUT ANY WARRANTY; without even the implied warranty of
9cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner** GNU General Public License for more details.
11cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner*/
12cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner
13cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner#include "config-host.h"
14cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner#include "android/opengles.h"
15afb0118a8be2a3fd271b2af51ccc13a2429a5078Andrew Hsieh#include <assert.h>
16183e927350a14945e13ab217e16ab5dce20349f3Jesse Hall
17183e927350a14945e13ab217e16ab5dce20349f3Jesse Hall/* Declared in "android/globals.h" */
18183e927350a14945e13ab217e16ab5dce20349f3Jesse Hallint  android_gles_fast_pipes = 1;
19183e927350a14945e13ab217e16ab5dce20349f3Jesse Hall
207b56a4a9a250573d5bdb8d04a2d8a64937432832David Turner#include "android/globals.h"
21cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner#include <android/utils/debug.h>
22cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner#include <android/utils/path.h>
23cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner#include <android/utils/bufprint.h>
24cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner#include <android/utils/dll.h>
25183e927350a14945e13ab217e16ab5dce20349f3Jesse Hall
266aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner// NOTE: The declarations below should be equivalent to those in
276aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner// <libOpenglRender/render_api_platform_types.h>
286aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner#ifdef _WIN32
296aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner#include <windows.h>
306aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turnertypedef HDC FBNativeDisplayType;
316aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turnertypedef HWND FBNativeWindowType;
326aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner#elif defined(__linux__)
336aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner// Really a Window, which is defined as 32-bit unsigned long on all platforms
346aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner// but we don't want to include the X11 headers here.
356aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turnertypedef uint32_t FBNativeWindowType;
366aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner#elif defined(__APPLE__)
376aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turnertypedef void* FBNativeWindowType;
386aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner#else
396aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner#warning "unsupported platform"
406aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner#endif
416aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner
426aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner// NOTE: The declarations below should be equivalent to those in
436aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner// <libOpenglRender/render_api.h>
446aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner
456aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner/* list of constants to be passed to setStreamMode */
466aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner#define STREAM_MODE_DEFAULT   0
476aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner#define STREAM_MODE_TCP       1
486aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner#define STREAM_MODE_UNIX      2
496aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner#define STREAM_MODE_PIPE      3
506aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner
516aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner#define RENDERER_FUNCTIONS_LIST \
526aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner  FUNCTION_(int, initLibrary, (void), ()) \
536aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner  FUNCTION_(int, setStreamMode, (int mode), (mode)) \
546aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner  FUNCTION_(int, initOpenGLRenderer, (int width, int height, char* addr, size_t addrLen), (width, height, addr, addrLen)) \
556aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner  FUNCTION_VOID_(getHardwareStrings, (const char** vendors, const char** renderer, const char** version), (vendors, renderer, version)) \
566aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner  FUNCTION_VOID_(setPostCallback, (OnPostFunc onPost, void* onPostContext), (onPost, onPostContext)) \
576aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner  FUNCTION_(int, createOpenGLSubwindow, (FBNativeWindowType window, int x, int y, int width, int height, float zRot), (window, x, y, width, height, zRot)) \
586aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner  FUNCTION_(int, destroyOpenGLSubwindow, (void), ()) \
596aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner  FUNCTION_VOID_(setOpenGLDisplayRotation, (float zRot), (zRot)) \
606aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner  FUNCTION_VOID_(repaintOpenGLDisplay, (void), ()) \
616aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner  FUNCTION_(int, stopOpenGLRenderer, (void), ()) \
62183e927350a14945e13ab217e16ab5dce20349f3Jesse Hall
63cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner#include <stdio.h>
64cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner#include <stdlib.h>
65cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner
66cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner#define D(...)  VERBOSE_PRINT(init,__VA_ARGS__)
67cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner#define DD(...) VERBOSE_PRINT(gles,__VA_ARGS__)
68cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner
69cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner/* Name of the GLES rendering library we're going to use */
7048fbbc097293db01bdfb3be6511a8a40451b4db0David 'Digit' Turner#if UINTPTR_MAX == UINT32_MAX
71cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner#define RENDERER_LIB_NAME  "libOpenglRender"
7248fbbc097293db01bdfb3be6511a8a40451b4db0David 'Digit' Turner#elif UINTPTR_MAX == UINT64_MAX
73c7389bd69e570a2c8432b37399aff1976b021f0fAndrew Hsieh#define RENDERER_LIB_NAME  "lib64OpenglRender"
74c7389bd69e570a2c8432b37399aff1976b021f0fAndrew Hsieh#else
7548fbbc097293db01bdfb3be6511a8a40451b4db0David 'Digit' Turner#error Unknown UINTPTR_MAX
76c7389bd69e570a2c8432b37399aff1976b021f0fAndrew Hsieh#endif
77cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner
786aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner// Define the corresponding function pointers.
796aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner#define FUNCTION_(ret, name, sig, params) \
806aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner        static ret (*name) sig = NULL;
816aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner#define FUNCTION_VOID_(name, sig, params) \
826aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner        static void (*name) sig = NULL;
836aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' TurnerRENDERER_FUNCTIONS_LIST
846aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner#undef FUNCTION_
856aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner#undef FUNCTION_VOID_
866aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner
876aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner// Define a function that initializes the function pointers by looking up
886aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner// the symbols from the shared library.
89cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turnerstatic int
90cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' TurnerinitOpenglesEmulationFuncs(ADynamicLibrary* rendererLib)
91cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner{
92cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner    void*  symbol;
93cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner    char*  error;
946699b688d7dbd7ad4a07ca1c1f77db864012010aJesse Hall
956aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner#define FUNCTION_(ret, name, sig, params) \
966699b688d7dbd7ad4a07ca1c1f77db864012010aJesse Hall    symbol = adynamicLibrary_findSymbol(rendererLib, #name, &error); \
97cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner    if (symbol != NULL) { \
986699b688d7dbd7ad4a07ca1c1f77db864012010aJesse Hall        name = symbol; \
99cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner    } else { \
100cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner        derror("GLES emulation: Could not find required symbol (%s): %s", #name, error); \
101cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner        free(error); \
102cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner        return -1; \
103cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner    }
1046aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner#define FUNCTION_VOID_(name, sig, params) FUNCTION_(void, name, sig, params)
1056aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' TurnerRENDERER_FUNCTIONS_LIST
1066aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner#undef FUNCTION_VOID_
1076aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner#undef FUNCTION_
1086699b688d7dbd7ad4a07ca1c1f77db864012010aJesse Hall
109cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner    return 0;
110cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner}
111cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner
1126aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner
1136aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner/* Defined in android/hw-pipe-net.c */
1146aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turnerextern int android_init_opengles_pipes(void);
1156aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner
1166aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turnerstatic ADynamicLibrary*  rendererLib;
1176aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turnerstatic int               rendererStarted;
1186aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turnerstatic char              rendererAddress[256];
1196aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner
120cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turnerint
121cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turnerandroid_initOpenglesEmulation(void)
122cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner{
123cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner    char* error = NULL;
124cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner
125cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner    if (rendererLib != NULL)
126cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner        return 0;
127cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner
128cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner    D("Initializing hardware OpenGLES emulation support");
129cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner
130cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner    rendererLib = adynamicLibrary_open(RENDERER_LIB_NAME, &error);
131cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner    if (rendererLib == NULL) {
132cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner        derror("Could not load OpenGLES emulation library: %s", error);
133cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner        return -1;
134cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner    }
135cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner
136cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner    android_init_opengles_pipes();
137cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner
138cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner    /* Resolve the functions */
139cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner    if (initOpenglesEmulationFuncs(rendererLib) < 0) {
140cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner        derror("OpenGLES emulation library mismatch. Be sure to use the correct version!");
141cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner        goto BAD_EXIT;
142cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner    }
143cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner
144cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner    if (!initLibrary()) {
145cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner        derror("OpenGLES initialization failed!");
146cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner        goto BAD_EXIT;
147cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner    }
148cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner
1497b56a4a9a250573d5bdb8d04a2d8a64937432832David Turner    if (android_gles_fast_pipes) {
1507b56a4a9a250573d5bdb8d04a2d8a64937432832David Turner#ifdef _WIN32
1517b56a4a9a250573d5bdb8d04a2d8a64937432832David Turner        /* XXX: NEED Win32 pipe implementation */
1527b56a4a9a250573d5bdb8d04a2d8a64937432832David Turner        setStreamMode(STREAM_MODE_TCP);
1537b56a4a9a250573d5bdb8d04a2d8a64937432832David Turner#else
1546699b688d7dbd7ad4a07ca1c1f77db864012010aJesse Hall	    setStreamMode(STREAM_MODE_UNIX);
1557b56a4a9a250573d5bdb8d04a2d8a64937432832David Turner#endif
1567b56a4a9a250573d5bdb8d04a2d8a64937432832David Turner    } else {
1576699b688d7dbd7ad4a07ca1c1f77db864012010aJesse Hall	    setStreamMode(STREAM_MODE_TCP);
1587b56a4a9a250573d5bdb8d04a2d8a64937432832David Turner    }
159cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner    return 0;
160cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner
161cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' TurnerBAD_EXIT:
162cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner    derror("OpenGLES emulation library could not be initialized!");
163cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner    adynamicLibrary_close(rendererLib);
164cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner    rendererLib = NULL;
165cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner    return -1;
166cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner}
167cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner
168cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turnerint
169ba5c1f674511aff458dae69927a1c61d60e66aa1Jesse Hallandroid_startOpenglesRenderer(int width, int height)
170cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner{
171cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner    if (!rendererLib) {
172cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner        D("Can't start OpenGLES renderer without support libraries");
173cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner        return -1;
174cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner    }
175cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner
17623a322d55622b2045eaeb94ebcf5b26e8ef51369Jesse Hall    if (rendererStarted) {
17723a322d55622b2045eaeb94ebcf5b26e8ef51369Jesse Hall        return 0;
17823a322d55622b2045eaeb94ebcf5b26e8ef51369Jesse Hall    }
17923a322d55622b2045eaeb94ebcf5b26e8ef51369Jesse Hall
180055adab0b70c70890634649a27c12b2c25afcacaJesse Hall    if (!initOpenGLRenderer(width, height, rendererAddress, sizeof(rendererAddress))) {
181cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner        D("Can't start OpenGLES renderer?");
182cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner        return -1;
183cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner    }
18423a322d55622b2045eaeb94ebcf5b26e8ef51369Jesse Hall
18523a322d55622b2045eaeb94ebcf5b26e8ef51369Jesse Hall    rendererStarted = 1;
186cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner    return 0;
187cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner}
188cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner
189ba5c1f674511aff458dae69927a1c61d60e66aa1Jesse Hallvoid
190ba5c1f674511aff458dae69927a1c61d60e66aa1Jesse Hallandroid_setPostCallback(OnPostFunc onPost, void* onPostContext)
191ba5c1f674511aff458dae69927a1c61d60e66aa1Jesse Hall{
192ba5c1f674511aff458dae69927a1c61d60e66aa1Jesse Hall    if (rendererLib) {
193ba5c1f674511aff458dae69927a1c61d60e66aa1Jesse Hall        setPostCallback(onPost, onPostContext);
194ba5c1f674511aff458dae69927a1c61d60e66aa1Jesse Hall    }
195ba5c1f674511aff458dae69927a1c61d60e66aa1Jesse Hall}
196ba5c1f674511aff458dae69927a1c61d60e66aa1Jesse Hall
197733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hallstatic void strncpy_safe(char* dst, const char* src, size_t n)
198733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall{
199733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall    strncpy(dst, src, n);
200733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall    dst[n-1] = '\0';
201733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall}
202733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall
203733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hallstatic void extractBaseString(char* dst, const char* src, size_t dstSize)
204733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall{
205733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall    const char* begin = strchr(src, '(');
206733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall    const char* end = strrchr(src, ')');
207733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall
208733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall    if (!begin || !end) {
209733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall        strncpy_safe(dst, src, dstSize);
210733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall        return;
211733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall    }
212733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall    begin += 1;
213733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall
214733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall    // "foo (bar)"
215733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall    //       ^  ^
216733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall    //       b  e
217733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall    //     = 5  8
218733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall    // substring with NUL-terminator is end-begin+1 bytes
219733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall    if (end - begin + 1 > dstSize) {
220733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall        end = begin + dstSize - 1;
221733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall    }
222733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall
223733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall    strncpy_safe(dst, begin, end - begin + 1);
224733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall}
225733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall
226733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hallvoid
227733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hallandroid_getOpenglesHardwareStrings(char* vendor, size_t vendorBufSize,
228733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall                                   char* renderer, size_t rendererBufSize,
229733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall                                   char* version, size_t versionBufSize)
230733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall{
231733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall    const char *vendorSrc, *rendererSrc, *versionSrc;
232733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall
23323a322d55622b2045eaeb94ebcf5b26e8ef51369Jesse Hall    assert(vendorBufSize > 0 && rendererBufSize > 0 && versionBufSize > 0);
23423a322d55622b2045eaeb94ebcf5b26e8ef51369Jesse Hall    assert(vendor != NULL && renderer != NULL && version != NULL);
23523a322d55622b2045eaeb94ebcf5b26e8ef51369Jesse Hall
23623a322d55622b2045eaeb94ebcf5b26e8ef51369Jesse Hall    if (!rendererStarted) {
23723a322d55622b2045eaeb94ebcf5b26e8ef51369Jesse Hall        D("Can't get OpenGL ES hardware strings when renderer not started");
238055adab0b70c70890634649a27c12b2c25afcacaJesse Hall        vendor[0] = renderer[0] = version[0] = '\0';
23923a322d55622b2045eaeb94ebcf5b26e8ef51369Jesse Hall        return;
24023a322d55622b2045eaeb94ebcf5b26e8ef51369Jesse Hall    }
24123a322d55622b2045eaeb94ebcf5b26e8ef51369Jesse Hall
242733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall    getHardwareStrings(&vendorSrc, &rendererSrc, &versionSrc);
243733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall    if (!vendorSrc) vendorSrc = "";
244733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall    if (!rendererSrc) rendererSrc = "";
245733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall    if (!versionSrc) versionSrc = "";
246733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall
247733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall    /* Special case for the default ES to GL translators: extract the strings
248733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall     * of the underlying OpenGL implementation. */
249733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall    if (strncmp(vendorSrc, "Google", 6) == 0 &&
250733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall            strncmp(rendererSrc, "Android Emulator OpenGL ES Translator", 37) == 0) {
251733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall        extractBaseString(vendor, vendorSrc, vendorBufSize);
252733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall        extractBaseString(renderer, rendererSrc, rendererBufSize);
253733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall        extractBaseString(version, versionSrc, versionBufSize);
254733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall    } else {
255733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall        strncpy_safe(vendor, vendorSrc, vendorBufSize);
256733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall        strncpy_safe(renderer, rendererSrc, rendererBufSize);
257733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall        strncpy_safe(version, versionSrc, versionBufSize);
258733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall    }
259733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall}
260733fffaac9ccebfc424fccf9467b22475f71a2f8Jesse Hall
261cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turnervoid
262cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turnerandroid_stopOpenglesRenderer(void)
263cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner{
26423a322d55622b2045eaeb94ebcf5b26e8ef51369Jesse Hall    if (rendererStarted) {
265cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner        stopOpenGLRenderer();
26623a322d55622b2045eaeb94ebcf5b26e8ef51369Jesse Hall        rendererStarted = 0;
267cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner    }
268cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner}
269cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner
270cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turnerint
271cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turnerandroid_showOpenglesWindow(void* window, int x, int y, int width, int height, float rotation)
272cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner{
27323a322d55622b2045eaeb94ebcf5b26e8ef51369Jesse Hall    if (rendererStarted) {
2746aff02b9b67f734329c58db3c2da6304aeb770bfDavid 'Digit' Turner        int success = createOpenGLSubwindow((FBNativeWindowType)(uintptr_t)window, x, y, width, height, rotation);
2756699b688d7dbd7ad4a07ca1c1f77db864012010aJesse Hall        return success ? 0 : -1;
276cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner    } else {
277cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner        return -1;
278cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner    }
279cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner}
280cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner
281cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turnerint
282cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turnerandroid_hideOpenglesWindow(void)
283cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner{
28423a322d55622b2045eaeb94ebcf5b26e8ef51369Jesse Hall    if (rendererStarted) {
2856699b688d7dbd7ad4a07ca1c1f77db864012010aJesse Hall        int success = destroyOpenGLSubwindow();
2866699b688d7dbd7ad4a07ca1c1f77db864012010aJesse Hall        return success ? 0 : -1;
287cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner    } else {
288cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner        return -1;
289cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner    }
290cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner}
291cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner
292cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turnervoid
293cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turnerandroid_redrawOpenglesWindow(void)
294cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner{
29523a322d55622b2045eaeb94ebcf5b26e8ef51369Jesse Hall    if (rendererStarted) {
296cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner        repaintOpenGLDisplay();
297cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner    }
298cb88e79ecbd16dea5f2201fd12320db5945db83eDavid 'Digit' Turner}
2997b56a4a9a250573d5bdb8d04a2d8a64937432832David Turner
3007b56a4a9a250573d5bdb8d04a2d8a64937432832David Turnervoid
301055adab0b70c70890634649a27c12b2c25afcacaJesse Hallandroid_gles_server_path(char* buff, size_t buffsize)
3027b56a4a9a250573d5bdb8d04a2d8a64937432832David Turner{
303055adab0b70c70890634649a27c12b2c25afcacaJesse Hall    strncpy_safe(buff, rendererAddress, buffsize);
3047b56a4a9a250573d5bdb8d04a2d8a64937432832David Turner}
305