1 /*
2 ** Copyright 2007, The Android Open Source Project
3 **
4 ** Licensed under the Apache License, Version 2.0 (the "License");
5 ** you may not use this file except in compliance with the License.
6 ** You may obtain a copy of the License at
7 **
8 ** http://www.apache.org/licenses/LICENSE-2.0
9 **
10 ** Unless required by applicable law or agreed to in writing, software
11 ** distributed under the License is distributed on an "AS IS" BASIS,
12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 ** See the License for the specific language governing permissions and
14 ** limitations under the License.
15 */
16
17 #include <ctype.h>
18 #include <errno.h>
19 #include <string.h>
20 #include <sys/ioctl.h>
21
22 #include <log/log.h>
23 #include <cutils/properties.h>
24
25 #include "../hooks.h"
26 #include "../egl_impl.h"
27
28 using namespace android;
29
30 // ----------------------------------------------------------------------------
31 // Actual GL entry-points
32 // ----------------------------------------------------------------------------
33
34 #undef API_ENTRY
35 #undef CALL_GL_API
36 #undef CALL_GL_API_INTERNAL_CALL
37 #undef CALL_GL_API_INTERNAL_SET_RETURN_VALUE
38 #undef CALL_GL_API_INTERNAL_DO_RETURN
39 #undef CALL_GL_API_RETURN
40
41 #if USE_SLOW_BINDING
42
43 #define API_ENTRY(_api) _api
44
45 #define CALL_GL_API_INTERNAL_CALL(_api, ...) \
46 gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl; \
47 if (_c) return _c->_api(__VA_ARGS__);
48
49 #define CALL_GL_API_INTERNAL_SET_RETURN_VALUE return 0;
50
51 // This stays blank, since void functions will implicitly return, and
52 // all of the other functions will return 0 based on the previous macro.
53 #define CALL_GL_API_INTERNAL_DO_RETURN
54
55 #elif defined(__arm__)
56
57 #define GET_TLS(reg) "mrc p15, 0, " #reg ", c13, c0, 3 \n"
58
59 #define API_ENTRY(_api) __attribute__((naked,noinline)) _api
60
61 #define CALL_GL_API_INTERNAL_CALL(_api, ...) \
62 asm volatile( \
63 GET_TLS(r12) \
64 "ldr r12, [r12, %[tls]] \n" \
65 "cmp r12, #0 \n" \
66 "ldrne pc, [r12, %[api]] \n" \
67 : \
68 : [tls] "J"(TLS_SLOT_OPENGL_API*4), \
69 [api] "J"(__builtin_offsetof(gl_hooks_t, gl._api)) \
70 : "r0", "r1", "r2", "r3", "r12" \
71 );
72
73 #define CALL_GL_API_INTERNAL_SET_RETURN_VALUE \
74 asm volatile( \
75 "mov r0, #0 \n" \
76 : \
77 : \
78 : "r0" \
79 );
80
81
82 #define CALL_GL_API_INTERNAL_DO_RETURN \
83 asm volatile( \
84 "bx lr \n" \
85 : \
86 : \
87 : "r0" \
88 );
89
90 #elif defined(__aarch64__)
91
92 #define API_ENTRY(_api) __attribute__((naked,noinline)) _api
93
94 #define CALL_GL_API_INTERNAL_CALL(_api, ...) \
95 asm volatile( \
96 "mrs x16, tpidr_el0\n" \
97 "ldr x16, [x16, %[tls]]\n" \
98 "cbz x16, 1f\n" \
99 "ldr x16, [x16, %[api]]\n" \
100 "br x16\n" \
101 "1:\n" \
102 : \
103 : [tls] "i" (TLS_SLOT_OPENGL_API * sizeof(void*)), \
104 [api] "i" (__builtin_offsetof(gl_hooks_t, gl._api)) \
105 : "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x16" \
106 );
107
108 #define CALL_GL_API_INTERNAL_SET_RETURN_VALUE \
109 asm volatile( \
110 "mov w0, wzr \n" \
111 : \
112 : \
113 : "w0" \
114 );
115
116 #define CALL_GL_API_INTERNAL_DO_RETURN \
117 asm volatile( \
118 "ret \n" \
119 : \
120 : \
121 : \
122 );
123
124 #elif defined(__i386__)
125
126 #define API_ENTRY(_api) __attribute__((naked,noinline)) _api
127
128 #define CALL_GL_API_INTERNAL_CALL(_api, ...) \
129 __asm__ volatile( \
130 "mov %%gs:0, %%eax\n" \
131 "mov %P[tls](%%eax), %%eax\n" \
132 "test %%eax, %%eax\n" \
133 "je 1f\n" \
134 "jmp *%P[api](%%eax)\n" \
135 "1:\n" \
136 : \
137 : [tls] "i" (TLS_SLOT_OPENGL_API*sizeof(void*)), \
138 [api] "i" (__builtin_offsetof(gl_hooks_t, gl._api)) \
139 : "cc", "%eax" \
140 );
141
142 #define CALL_GL_API_INTERNAL_SET_RETURN_VALUE \
143 __asm__ volatile( \
144 "xor %%eax, %%eax\n" \
145 : \
146 : \
147 : "%eax" \
148 );
149
150 #define CALL_GL_API_INTERNAL_DO_RETURN \
151 __asm__ volatile( \
152 "ret\n" \
153 : \
154 : \
155 : \
156 );
157
158 #elif defined(__x86_64__)
159
160 #define API_ENTRY(_api) __attribute__((naked,noinline)) _api
161
162 #define CALL_GL_API_INTERNAL_CALL(_api, ...) \
163 __asm__ volatile( \
164 "mov %%fs:0, %%rax\n" \
165 "mov %P[tls](%%rax), %%rax\n" \
166 "test %%rax, %%rax\n" \
167 "je 1f\n" \
168 "jmp *%P[api](%%rax)\n" \
169 "1:\n" \
170 : \
171 : [tls] "i" (TLS_SLOT_OPENGL_API*sizeof(void*)), \
172 [api] "i" (__builtin_offsetof(gl_hooks_t, gl._api)) \
173 : "cc", "%rdi", "%rsi", "%rdx", "%rcx", "%r8", "%r9", \
174 "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", \
175 "%xmm6", "%xmm7" \
176 );
177
178 #define CALL_GL_API_INTERNAL_SET_RETURN_VALUE \
179 __asm__ volatile( \
180 "xor %%eax, %%eax\n" \
181 : \
182 : \
183 : "%eax" \
184 );
185
186 #define CALL_GL_API_INTERNAL_DO_RETURN \
187 __asm__ volatile( \
188 "retq\n" \
189 : \
190 : \
191 : \
192 );
193
194 #elif defined(__riscv)
195
196 #define API_ENTRY(_api) __attribute__((naked,noinline)) _api
197
198 #define CALL_GL_API_INTERNAL_CALL(_api, ...) \
199 asm volatile( \
200 "mv t0, tp\n" \
201 "li t1, %[tls]\n" \
202 "add t0, t0, t1\n" \
203 "ld t0, 0(t0)\n" \
204 "beqz t0, 1f\n" \
205 "li t1, %[api]\n" \
206 "add t0, t0, t1\n" \
207 "ld t0, 0(t0)\n" \
208 "jalr x0, t0\n" \
209 "1:\n" \
210 : \
211 : [tls] "i"(TLS_SLOT_OPENGL_API*sizeof(void *)), \
212 [api] "i"(__builtin_offsetof(gl_hooks_t, gl._api)) \
213 : "t0", "t1", "t2", "a0", "a1", "a2", "a3", "a4", \
214 "a5", "t6", "t3", "t4", "t5", "t6" \
215 );
216
217 #define CALL_GL_API_INTERNAL_SET_RETURN_VALUE \
218 asm volatile( \
219 "li a0, 0\n" \
220 : \
221 : \
222 : "a0" \
223 );
224
225 #define CALL_GL_API_INTERNAL_DO_RETURN \
226 asm volatile( \
227 "ret\n" \
228 : \
229 : \
230 : \
231 );
232
233 #endif
234
235 #define CALL_GL_API(_api, ...) \
236 CALL_GL_API_INTERNAL_CALL(_api, __VA_ARGS__) \
237 CALL_GL_API_INTERNAL_DO_RETURN
238
239 #define CALL_GL_API_RETURN(_api, ...) \
240 CALL_GL_API_INTERNAL_CALL(_api, __VA_ARGS__) \
241 CALL_GL_API_INTERNAL_SET_RETURN_VALUE \
242 CALL_GL_API_INTERNAL_DO_RETURN
243
244 extern "C" {
245 #pragma GCC diagnostic ignored "-Wunused-parameter"
246 #include "gl2_api.in"
247 #include "gl2ext_api.in"
248 #pragma GCC diagnostic warning "-Wunused-parameter"
249 }
250
251 #undef API_ENTRY
252 #undef CALL_GL_API
253 #undef CALL_GL_API_INTERNAL_CALL
254 #undef CALL_GL_API_INTERNAL_SET_RETURN_VALUE
255 #undef CALL_GL_API_INTERNAL_DO_RETURN
256 #undef CALL_GL_API_RETURN
257
258 /*
259 * glGetString() and glGetStringi() are special because we expose some
260 * extensions in the wrapper. Also, wrapping glGetXXX() is required because
261 * the value returned for GL_NUM_EXTENSIONS may have been altered by the
262 * injection of the additional extensions.
263 */
264
265 extern "C" {
266 const GLubyte * __glGetString(GLenum name);
267 const GLubyte * __glGetStringi(GLenum name, GLuint index);
268 void __glGetBooleanv(GLenum pname, GLboolean * data);
269 void __glGetFloatv(GLenum pname, GLfloat * data);
270 void __glGetIntegerv(GLenum pname, GLint * data);
271 void __glGetInteger64v(GLenum pname, GLint64 * data);
272 }
273
glGetString(GLenum name)274 const GLubyte * glGetString(GLenum name) {
275 egl_connection_t* const cnx = egl_get_connection();
276 return cnx->platform.glGetString(name);
277 }
278
glGetStringi(GLenum name,GLuint index)279 const GLubyte * glGetStringi(GLenum name, GLuint index) {
280 egl_connection_t* const cnx = egl_get_connection();
281 return cnx->platform.glGetStringi(name, index);
282 }
283
glGetBooleanv(GLenum pname,GLboolean * data)284 void glGetBooleanv(GLenum pname, GLboolean * data) {
285 egl_connection_t* const cnx = egl_get_connection();
286 return cnx->platform.glGetBooleanv(pname, data);
287 }
288
glGetFloatv(GLenum pname,GLfloat * data)289 void glGetFloatv(GLenum pname, GLfloat * data) {
290 egl_connection_t* const cnx = egl_get_connection();
291 return cnx->platform.glGetFloatv(pname, data);
292 }
293
glGetIntegerv(GLenum pname,GLint * data)294 void glGetIntegerv(GLenum pname, GLint * data) {
295 egl_connection_t* const cnx = egl_get_connection();
296 return cnx->platform.glGetIntegerv(pname, data);
297 }
298
glGetInteger64v(GLenum pname,GLint64 * data)299 void glGetInteger64v(GLenum pname, GLint64 * data) {
300 egl_connection_t* const cnx = egl_get_connection();
301 return cnx->platform.glGetInteger64v(pname, data);
302 }
303