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 #if CONFIG_ANDROID_OPENGLES
     21 
     22 #include "android/globals.h"
     23 #include <android/utils/debug.h>
     24 #include <android/utils/path.h>
     25 #include <android/utils/bufprint.h>
     26 #include <android/utils/dll.h>
     27 
     28 #define RENDER_API_NO_PROTOTYPES 1
     29 #include <libOpenglRender/render_api.h>
     30 
     31 #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 */
     38 #if HOST_LONG_BITS == 32
     39 #define RENDERER_LIB_NAME  "libOpenglRender"
     40 #elif HOST_LONG_BITS == 64
     41 #define RENDERER_LIB_NAME  "lib64OpenglRender"
     42 #else
     43 #error Unknown HOST_LONG_BITS
     44 #endif
     45 
     46 #define DYNLINK_FUNCTIONS  \
     47   DYNLINK_FUNC(initLibrary) \
     48   DYNLINK_FUNC(setStreamMode) \
     49   DYNLINK_FUNC(initOpenGLRenderer) \
     50   DYNLINK_FUNC(setPostCallback) \
     51   DYNLINK_FUNC(getHardwareStrings) \
     52   DYNLINK_FUNC(createOpenGLSubwindow) \
     53   DYNLINK_FUNC(destroyOpenGLSubwindow) \
     54   DYNLINK_FUNC(repaintOpenGLDisplay) \
     55   DYNLINK_FUNC(stopOpenGLRenderer)
     56 
     57 #ifndef CONFIG_STANDALONE_UI
     58 /* Defined in android/hw-pipe-net.c */
     59 extern int android_init_opengles_pipes(void);
     60 #endif
     61 
     62 static ADynamicLibrary*  rendererLib;
     63 static int               rendererStarted;
     64 static char              rendererAddress[256];
     65 
     66 /* Define the function pointers */
     67 #define DYNLINK_FUNC(name) \
     68     static name##Fn name = NULL;
     69 DYNLINK_FUNCTIONS
     70 #undef DYNLINK_FUNC
     71 
     72 static int
     73 initOpenglesEmulationFuncs(ADynamicLibrary* rendererLib)
     74 {
     75     void*  symbol;
     76     char*  error;
     77 
     78 #define DYNLINK_FUNC(name) \
     79     symbol = adynamicLibrary_findSymbol(rendererLib, #name, &error); \
     80     if (symbol != NULL) { \
     81         name = symbol; \
     82     } else { \
     83         derror("GLES emulation: Could not find required symbol (%s): %s", #name, error); \
     84         free(error); \
     85         return -1; \
     86     }
     87 DYNLINK_FUNCTIONS
     88 #undef DYNLINK_FUNC
     89 
     90     return 0;
     91 }
     92 
     93 int
     94 android_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 
    125     if (android_gles_fast_pipes) {
    126 #ifdef _WIN32
    127         /* XXX: NEED Win32 pipe implementation */
    128         setStreamMode(STREAM_MODE_TCP);
    129 #else
    130 	    setStreamMode(STREAM_MODE_UNIX);
    131 #endif
    132     } else {
    133 	    setStreamMode(STREAM_MODE_TCP);
    134     }
    135     return 0;
    136 
    137 BAD_EXIT:
    138     derror("OpenGLES emulation library could not be initialized!");
    139     adynamicLibrary_close(rendererLib);
    140     rendererLib = NULL;
    141     return -1;
    142 }
    143 
    144 int
    145 android_startOpenglesRenderer(int width, int height)
    146 {
    147     if (!rendererLib) {
    148         D("Can't start OpenGLES renderer without support libraries");
    149         return -1;
    150     }
    151 
    152     if (rendererStarted) {
    153         return 0;
    154     }
    155 
    156     if (!initOpenGLRenderer(width, height, rendererAddress, sizeof(rendererAddress))) {
    157         D("Can't start OpenGLES renderer?");
    158         return -1;
    159     }
    160 
    161     rendererStarted = 1;
    162     return 0;
    163 }
    164 
    165 void
    166 android_setPostCallback(OnPostFunc onPost, void* onPostContext)
    167 {
    168     if (rendererLib) {
    169         setPostCallback(onPost, onPostContext);
    170     }
    171 }
    172 
    173 static void strncpy_safe(char* dst, const char* src, size_t n)
    174 {
    175     strncpy(dst, src, n);
    176     dst[n-1] = '\0';
    177 }
    178 
    179 static void extractBaseString(char* dst, const char* src, size_t dstSize)
    180 {
    181     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 
    202 void
    203 android_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 
    209     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");
    214         vendor[0] = renderer[0] = version[0] = '\0';
    215         return;
    216     }
    217 
    218     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 
    237 void
    238 android_stopOpenglesRenderer(void)
    239 {
    240     if (rendererStarted) {
    241         stopOpenGLRenderer();
    242         rendererStarted = 0;
    243     }
    244 }
    245 
    246 int
    247 android_showOpenglesWindow(void* window, int x, int y, int width, int height, float rotation)
    248 {
    249     if (rendererStarted) {
    250         int success = createOpenGLSubwindow((FBNativeWindowType)window, x, y, width, height, rotation);
    251         return success ? 0 : -1;
    252     } else {
    253         return -1;
    254     }
    255 }
    256 
    257 int
    258 android_hideOpenglesWindow(void)
    259 {
    260     if (rendererStarted) {
    261         int success = destroyOpenGLSubwindow();
    262         return success ? 0 : -1;
    263     } else {
    264         return -1;
    265     }
    266 }
    267 
    268 void
    269 android_redrawOpenglesWindow(void)
    270 {
    271     if (rendererStarted) {
    272         repaintOpenGLDisplay();
    273     }
    274 }
    275 
    276 void
    277 android_gles_server_path(char* buff, size_t buffsize)
    278 {
    279     strncpy_safe(buff, rendererAddress, buffsize);
    280 }
    281 
    282 #else // CONFIG_ANDROID_OPENGLES
    283 
    284 int android_initOpenglesEmulation(void)
    285 {
    286     return -1;
    287 }
    288 
    289 int android_startOpenglesRenderer(int width, int height)
    290 {
    291     return -1;
    292 }
    293 
    294 void
    295 android_setPostCallback(OnPostFunc onPost, void* onPostContext)
    296 {
    297 }
    298 
    299 void 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 
    308 void android_stopOpenglesRenderer(void)
    309 {}
    310 
    311 int android_showOpenglesWindow(void* window, int x, int y, int width, int height, float rotation)
    312 {
    313     return -1;
    314 }
    315 
    316 int android_hideOpenglesWindow(void)
    317 {
    318     return -1;
    319 }
    320 
    321 void android_redrawOpenglesWindow(void)
    322 {}
    323 
    324 void android_gles_server_path(char* buff, size_t buffsize)
    325 {
    326     buff[0] = '\0';
    327 }
    328 
    329 #endif // !CONFIG_ANDROID_OPENGLES
    330