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 "android/globals.h"
     16 #include <android/utils/debug.h>
     17 #include <android/utils/path.h>
     18 #include <android/utils/bufprint.h>
     19 #include <android/utils/dll.h>
     20 #include <stdio.h>
     21 #include <stdlib.h>
     22 
     23 #define D(...)  VERBOSE_PRINT(init,__VA_ARGS__)
     24 #define DD(...) VERBOSE_PRINT(gles,__VA_ARGS__)
     25 
     26 /* Declared in "android/globals.h" */
     27 int  android_gles_fast_pipes = 1;
     28 
     29 /* Name of the GLES rendering library we're going to use */
     30 #if HOST_LONG_BITS == 32
     31 #define RENDERER_LIB_NAME  "libOpenglRender"
     32 #elif HOST_LONG_BITS == 64
     33 #define RENDERER_LIB_NAME  "lib64OpenglRender"
     34 #else
     35 #error Unknown HOST_LONG_BITS
     36 #endif
     37 
     38 /* These definitions *must* match those under:
     39  * development/tools/emulator/opengl/host/include/libOpenglRender/render_api.h
     40  */
     41 #define DYNLINK_FUNCTIONS  \
     42   DYNLINK_FUNC(int,initLibrary,(void),(),return) \
     43   DYNLINK_FUNC(int,setStreamMode,(int a),(a),return) \
     44   DYNLINK_FUNC(int,initOpenGLRenderer,(int width, int height, int port, OnPostFn onPost, void* onPostContext),(width,height,port,onPost,onPostContext),return) \
     45   DYNLINK_FUNC(int,createOpenGLSubwindow,(void* window, int x, int y, int width, int height, float zRot),(window,x,y,width,height,zRot),return)\
     46   DYNLINK_FUNC(int,destroyOpenGLSubwindow,(void),(),return)\
     47   DYNLINK_FUNC(void,repaintOpenGLDisplay,(void),(),)\
     48   DYNLINK_FUNC(void,stopOpenGLRenderer,(void),(),)
     49 
     50 #define STREAM_MODE_DEFAULT  0
     51 #define STREAM_MODE_TCP      1
     52 #define STREAM_MODE_UNIX     2
     53 #define STREAM_MODE_PIPE     3
     54 
     55 #ifndef CONFIG_STANDALONE_UI
     56 /* Defined in android/hw-pipe-net.c */
     57 extern int android_init_opengles_pipes(void);
     58 #endif
     59 
     60 static ADynamicLibrary*  rendererLib;
     61 
     62 /* Define the pointers and the wrapper functions to call them */
     63 #define DYNLINK_FUNC(result,name,sig,params,ret) \
     64     static result (*_ptr_##name) sig; \
     65     static result name sig { \
     66         ret (*_ptr_##name) params ; \
     67     }
     68 
     69 DYNLINK_FUNCTIONS
     70 
     71 #undef DYNLINK_FUNC
     72 
     73 static int
     74 initOpenglesEmulationFuncs(ADynamicLibrary* rendererLib)
     75 {
     76     void*  symbol;
     77     char*  error;
     78 #define DYNLINK_FUNC(result,name,sig,params,ret) \
     79     symbol = adynamicLibrary_findSymbol( rendererLib, #name, &error ); \
     80     if (symbol != NULL) { \
     81         _ptr_##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     return 0;
     90 }
     91 
     92 int
     93 android_initOpenglesEmulation(void)
     94 {
     95     char* error = NULL;
     96 
     97     if (rendererLib != NULL)
     98         return 0;
     99 
    100     D("Initializing hardware OpenGLES emulation support");
    101 
    102     rendererLib = adynamicLibrary_open(RENDERER_LIB_NAME, &error);
    103     if (rendererLib == NULL) {
    104         derror("Could not load OpenGLES emulation library: %s", error);
    105         return -1;
    106     }
    107 
    108 #ifndef CONFIG_STANDALONE_UI
    109     android_init_opengles_pipes();
    110 #endif
    111 
    112 
    113     /* Resolve the functions */
    114     if (initOpenglesEmulationFuncs(rendererLib) < 0) {
    115         derror("OpenGLES emulation library mismatch. Be sure to use the correct version!");
    116         goto BAD_EXIT;
    117     }
    118 
    119     if (!initLibrary()) {
    120         derror("OpenGLES initialization failed!");
    121         goto BAD_EXIT;
    122     }
    123 
    124     if (android_gles_fast_pipes) {
    125 #ifdef _WIN32
    126         /* XXX: NEED Win32 pipe implementation */
    127         setStreamMode(STREAM_MODE_TCP);
    128 #else
    129 	setStreamMode(STREAM_MODE_UNIX);
    130 #endif
    131     } else {
    132 	setStreamMode(STREAM_MODE_TCP);
    133     }
    134     return 0;
    135 
    136 BAD_EXIT:
    137     derror("OpenGLES emulation library could not be initialized!");
    138     adynamicLibrary_close(rendererLib);
    139     rendererLib = NULL;
    140     return -1;
    141 }
    142 
    143 int
    144 android_startOpenglesRenderer(int width, int height, OnPostFn onPost, void* onPostContext)
    145 {
    146     if (!rendererLib) {
    147         D("Can't start OpenGLES renderer without support libraries");
    148         return -1;
    149     }
    150 
    151     if (initOpenGLRenderer(width, height, ANDROID_OPENGLES_BASE_PORT, onPost, onPostContext) != 0) {
    152         D("Can't start OpenGLES renderer?");
    153         return -1;
    154     }
    155     return 0;
    156 }
    157 
    158 void
    159 android_stopOpenglesRenderer(void)
    160 {
    161     if (rendererLib) {
    162         stopOpenGLRenderer();
    163     }
    164 }
    165 
    166 int
    167 android_showOpenglesWindow(void* window, int x, int y, int width, int height, float rotation)
    168 {
    169     if (rendererLib) {
    170         return createOpenGLSubwindow(window, x, y, width, height, rotation);
    171     } else {
    172         return -1;
    173     }
    174 }
    175 
    176 int
    177 android_hideOpenglesWindow(void)
    178 {
    179     if (rendererLib) {
    180         return destroyOpenGLSubwindow();
    181     } else {
    182         return -1;
    183     }
    184 }
    185 
    186 void
    187 android_redrawOpenglesWindow(void)
    188 {
    189     if (rendererLib) {
    190         repaintOpenGLDisplay();
    191     }
    192 }
    193 
    194 void
    195 android_gles_unix_path(char* buff, size_t buffsize, int port)
    196 {
    197     const char* user = getenv("USER");
    198     char *p = buff, *end = buff + buffsize;
    199 
    200     /* The logic here must correspond to the one inside
    201      * development/tools/emulator/opengl/shared/libOpenglCodecCommon/UnixStream.cpp */
    202     p = bufprint(p, end, "/tmp/");
    203     if (user && user[0]) {
    204         p = bufprint(p, end, "android-%s/", user);
    205     }
    206     p = bufprint(p, end, "qemu-gles-%d", port);
    207 }
    208