Home | History | Annotate | Download | only in android
      1 /* 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"
     15 #include <assert.h>
     16 
     17 /* Declared in "android/globals.h" */
     18 int  android_gles_fast_pipes = 1;
     19 
     20 #include "android/globals.h"
     21 #include <android/utils/debug.h>
     22 #include <android/utils/path.h>
     23 #include <android/utils/bufprint.h>
     24 #include <android/utils/dll.h>
     25 
     26 // NOTE: The declarations below should be equivalent to those in
     27 // <libOpenglRender/render_api_platform_types.h>
     28 #ifdef _WIN32
     29 #include <windows.h>
     30 typedef HDC FBNativeDisplayType;
     31 typedef 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.
     35 typedef uint32_t FBNativeWindowType;
     36 #elif defined(__APPLE__)
     37 typedef 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), ()) \
     62 
     63 #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 */
     70 #if UINTPTR_MAX == UINT32_MAX
     71 #define RENDERER_LIB_NAME  "libOpenglRender"
     72 #elif UINTPTR_MAX == UINT64_MAX
     73 #define RENDERER_LIB_NAME  "lib64OpenglRender"
     74 #else
     75 #error Unknown UINTPTR_MAX
     76 #endif
     77 
     78 // 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;
     83 RENDERER_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.
     89 static int
     90 initOpenglesEmulationFuncs(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)
    105 RENDERER_FUNCTIONS_LIST
    106 #undef FUNCTION_VOID_
    107 #undef FUNCTION_
    108 
    109     return 0;
    110 }
    111 
    112 
    113 /* Defined in android/hw-pipe-net.c */
    114 extern int android_init_opengles_pipes(void);
    115 
    116 static ADynamicLibrary*  rendererLib;
    117 static int               rendererStarted;
    118 static char              rendererAddress[256];
    119 
    120 int
    121 android_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 
    136     android_init_opengles_pipes();
    137 
    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 
    149     if (android_gles_fast_pipes) {
    150 #ifdef _WIN32
    151         /* XXX: NEED Win32 pipe implementation */
    152         setStreamMode(STREAM_MODE_TCP);
    153 #else
    154 	    setStreamMode(STREAM_MODE_UNIX);
    155 #endif
    156     } else {
    157 	    setStreamMode(STREAM_MODE_TCP);
    158     }
    159     return 0;
    160 
    161 BAD_EXIT:
    162     derror("OpenGLES emulation library could not be initialized!");
    163     adynamicLibrary_close(rendererLib);
    164     rendererLib = NULL;
    165     return -1;
    166 }
    167 
    168 int
    169 android_startOpenglesRenderer(int width, int height)
    170 {
    171     if (!rendererLib) {
    172         D("Can't start OpenGLES renderer without support libraries");
    173         return -1;
    174     }
    175 
    176     if (rendererStarted) {
    177         return 0;
    178     }
    179 
    180     if (!initOpenGLRenderer(width, height, rendererAddress, sizeof(rendererAddress))) {
    181         D("Can't start OpenGLES renderer?");
    182         return -1;
    183     }
    184 
    185     rendererStarted = 1;
    186     return 0;
    187 }
    188 
    189 void
    190 android_setPostCallback(OnPostFunc onPost, void* onPostContext)
    191 {
    192     if (rendererLib) {
    193         setPostCallback(onPost, onPostContext);
    194     }
    195 }
    196 
    197 static void strncpy_safe(char* dst, const char* src, size_t n)
    198 {
    199     strncpy(dst, src, n);
    200     dst[n-1] = '\0';
    201 }
    202 
    203 static void extractBaseString(char* dst, const char* src, size_t dstSize)
    204 {
    205     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 
    226 void
    227 android_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 
    233     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");
    238         vendor[0] = renderer[0] = version[0] = '\0';
    239         return;
    240     }
    241 
    242     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 
    261 void
    262 android_stopOpenglesRenderer(void)
    263 {
    264     if (rendererStarted) {
    265         stopOpenGLRenderer();
    266         rendererStarted = 0;
    267     }
    268 }
    269 
    270 int
    271 android_showOpenglesWindow(void* window, int x, int y, int width, int height, float rotation)
    272 {
    273     if (rendererStarted) {
    274         int success = createOpenGLSubwindow((FBNativeWindowType)(uintptr_t)window, x, y, width, height, rotation);
    275         return success ? 0 : -1;
    276     } else {
    277         return -1;
    278     }
    279 }
    280 
    281 int
    282 android_hideOpenglesWindow(void)
    283 {
    284     if (rendererStarted) {
    285         int success = destroyOpenGLSubwindow();
    286         return success ? 0 : -1;
    287     } else {
    288         return -1;
    289     }
    290 }
    291 
    292 void
    293 android_redrawOpenglesWindow(void)
    294 {
    295     if (rendererStarted) {
    296         repaintOpenGLDisplay();
    297     }
    298 }
    299 
    300 void
    301 android_gles_server_path(char* buff, size_t buffsize)
    302 {
    303     strncpy_safe(buff, rendererAddress, buffsize);
    304 }
    305