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
initOpenglesEmulationFuncs(ADynamicLibrary * rendererLib)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
android_initOpenglesEmulation(void)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
android_startOpenglesRenderer(int width,int height,OnPostFn onPost,void * onPostContext)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
android_stopOpenglesRenderer(void)159 android_stopOpenglesRenderer(void)
160 {
161 if (rendererLib) {
162 stopOpenGLRenderer();
163 }
164 }
165
166 int
android_showOpenglesWindow(void * window,int x,int y,int width,int height,float rotation)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
android_hideOpenglesWindow(void)177 android_hideOpenglesWindow(void)
178 {
179 if (rendererLib) {
180 return destroyOpenGLSubwindow();
181 } else {
182 return -1;
183 }
184 }
185
186 void
android_redrawOpenglesWindow(void)187 android_redrawOpenglesWindow(void)
188 {
189 if (rendererLib) {
190 repaintOpenGLDisplay();
191 }
192 }
193
194 void
android_gles_unix_path(char * buff,size_t buffsize,int port)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