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(__mips64)
195 
196     #define API_ENTRY(_api) __attribute__((naked,noinline)) _api
197 
198     // t0:  $12
199     // fn:  $25
200     // tls: $3
201     // v0:  $2
202     #define CALL_GL_API_INTERNAL_CALL(_api, ...)                  \
203         asm volatile(                                             \
204             ".set  push\n\t"                                      \
205             ".set  noreorder\n\t"                                 \
206             "rdhwr $3, $29\n\t"                                   \
207             "ld    $12, %[OPENGL_API]($3)\n\t"                    \
208             "beqz  $12, 1f\n\t"                                   \
209             " move $25, $ra\n\t"                                  \
210             "ld    $12, %[API]($12)\n\t"                          \
211             "beqz  $12, 1f\n\t"                                   \
212             " nop\n\t"                                            \
213             "move  $25, $12\n\t"                                  \
214             "1:\n\t"                                              \
215             "jalr  $0, $25\n\t"                                   \
216             " move $2, $0\n\t"                                    \
217             ".set  pop\n\t"                                       \
218             :                                                     \
219             : [OPENGL_API] "I"(TLS_SLOT_OPENGL_API*sizeof(void*)),\
220               [API] "I"(__builtin_offsetof(gl_hooks_t, gl._api))  \
221             : "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9",     \
222               "$10", "$11", "$12", "$25"                          \
223         );
224 
225     #define CALL_GL_API_INTERNAL_SET_RETURN_VALUE
226     #define CALL_GL_API_INTERNAL_DO_RETURN
227 
228 #elif defined(__mips__)
229 
230     #define API_ENTRY(_api) __attribute__((naked,noinline)) _api
231 
232     // t0:  $8
233     // fn:  $25
234     // tls: $3
235     // v0:  $2
236     #define CALL_GL_API_INTERNAL_CALL(_api, ...)                 \
237         asm volatile(                                            \
238             ".set  push\n\t"                                     \
239             ".set  noreorder\n\t"                                \
240             ".set  mips32r2\n\t"                                 \
241             "rdhwr $3, $29\n\t"                                  \
242             "lw    $3, %[OPENGL_API]($3)\n\t"                    \
243             "beqz  $3, 1f\n\t"                                   \
244             " move $25,$ra\n\t"                                  \
245             "lw    $3, %[API]($3)\n\t"                           \
246             "beqz  $3, 1f\n\t"                                   \
247             " nop\n\t"                                           \
248             "move  $25, $3\n\t"                                  \
249             "1:\n\t"                                             \
250             "jalr  $0, $25\n\t"                                  \
251             " move $2, $0\n\t"                                   \
252             ".set  pop\n\t"                                      \
253             :                                                    \
254             : [OPENGL_API] "I"(TLS_SLOT_OPENGL_API*4),           \
255               [API] "I"(__builtin_offsetof(gl_hooks_t, gl._api)) \
256             : "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$25"    \
257         );
258 
259     #define CALL_GL_API_INTERNAL_SET_RETURN_VALUE
260     #define CALL_GL_API_INTERNAL_DO_RETURN
261 
262 #endif
263 
264 #define CALL_GL_API(_api, ...) \
265     CALL_GL_API_INTERNAL_CALL(_api, __VA_ARGS__) \
266     CALL_GL_API_INTERNAL_DO_RETURN
267 
268 #define CALL_GL_API_RETURN(_api, ...) \
269     CALL_GL_API_INTERNAL_CALL(_api, __VA_ARGS__) \
270     CALL_GL_API_INTERNAL_SET_RETURN_VALUE \
271     CALL_GL_API_INTERNAL_DO_RETURN
272 
273 extern "C" {
274 #pragma GCC diagnostic ignored "-Wunused-parameter"
275 #include "gl2_api.in"
276 #include "gl2ext_api.in"
277 #pragma GCC diagnostic warning "-Wunused-parameter"
278 }
279 
280 #undef API_ENTRY
281 #undef CALL_GL_API
282 #undef CALL_GL_API_INTERNAL_CALL
283 #undef CALL_GL_API_INTERNAL_SET_RETURN_VALUE
284 #undef CALL_GL_API_INTERNAL_DO_RETURN
285 #undef CALL_GL_API_RETURN
286 
287 /*
288  * glGetString() and glGetStringi() are special because we expose some
289  * extensions in the wrapper. Also, wrapping glGetXXX() is required because
290  * the value returned for GL_NUM_EXTENSIONS may have been altered by the
291  * injection of the additional extensions.
292  */
293 
294 extern "C" {
295     const GLubyte * __glGetString(GLenum name);
296     const GLubyte * __glGetStringi(GLenum name, GLuint index);
297     void __glGetBooleanv(GLenum pname, GLboolean * data);
298     void __glGetFloatv(GLenum pname, GLfloat * data);
299     void __glGetIntegerv(GLenum pname, GLint * data);
300     void __glGetInteger64v(GLenum pname, GLint64 * data);
301 }
302 
glGetString(GLenum name)303 const GLubyte * glGetString(GLenum name) {
304     egl_connection_t* const cnx = egl_get_connection();
305     return cnx->platform.glGetString(name);
306 }
307 
glGetStringi(GLenum name,GLuint index)308 const GLubyte * glGetStringi(GLenum name, GLuint index) {
309     egl_connection_t* const cnx = egl_get_connection();
310     return cnx->platform.glGetStringi(name, index);
311 }
312 
glGetBooleanv(GLenum pname,GLboolean * data)313 void glGetBooleanv(GLenum pname, GLboolean * data) {
314     egl_connection_t* const cnx = egl_get_connection();
315     return cnx->platform.glGetBooleanv(pname, data);
316 }
317 
glGetFloatv(GLenum pname,GLfloat * data)318 void glGetFloatv(GLenum pname, GLfloat * data) {
319     egl_connection_t* const cnx = egl_get_connection();
320     return cnx->platform.glGetFloatv(pname, data);
321 }
322 
glGetIntegerv(GLenum pname,GLint * data)323 void glGetIntegerv(GLenum pname, GLint * data) {
324     egl_connection_t* const cnx = egl_get_connection();
325     return cnx->platform.glGetIntegerv(pname, data);
326 }
327 
glGetInteger64v(GLenum pname,GLint64 * data)328 void glGetInteger64v(GLenum pname, GLint64 * data) {
329     egl_connection_t* const cnx = egl_get_connection();
330     return cnx->platform.glGetInteger64v(pname, data);
331 }
332