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