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 <GLES/gl.h>
26 #include <GLES/glext.h>
27 
28 #include "../hooks.h"
29 #include "../egl_impl.h"
30 
31 using namespace android;
32 
33 // ----------------------------------------------------------------------------
34 // extensions for the framework
35 // ----------------------------------------------------------------------------
36 
37 extern "C" {
38 GL_API void GL_APIENTRY glColorPointerBounds(GLint size, GLenum type, GLsizei stride,
39         const GLvoid *ptr, GLsizei count);
40 GL_API void GL_APIENTRY glNormalPointerBounds(GLenum type, GLsizei stride,
41         const GLvoid *pointer, GLsizei count);
42 GL_API void GL_APIENTRY glTexCoordPointerBounds(GLint size, GLenum type,
43         GLsizei stride, const GLvoid *pointer, GLsizei count);
44 GL_API void GL_APIENTRY glVertexPointerBounds(GLint size, GLenum type,
45         GLsizei stride, const GLvoid *pointer, GLsizei count);
46 GL_API void GL_APIENTRY glPointSizePointerOESBounds(GLenum type,
47         GLsizei stride, const GLvoid *pointer, GLsizei count);
48 GL_API void GL_APIENTRY glMatrixIndexPointerOESBounds(GLint size, GLenum type,
49         GLsizei stride, const GLvoid *pointer, GLsizei count);
50 GL_API void GL_APIENTRY glWeightPointerOESBounds(GLint size, GLenum type,
51         GLsizei stride, const GLvoid *pointer, GLsizei count);
52 }
53 
glColorPointerBounds(GLint size,GLenum type,GLsizei stride,const GLvoid * ptr,GLsizei)54 void glColorPointerBounds(GLint size, GLenum type, GLsizei stride,
55         const GLvoid *ptr, GLsizei /*count*/) {
56     glColorPointer(size, type, stride, ptr);
57 }
glNormalPointerBounds(GLenum type,GLsizei stride,const GLvoid * pointer,GLsizei)58 void glNormalPointerBounds(GLenum type, GLsizei stride,
59         const GLvoid *pointer, GLsizei /*count*/) {
60     glNormalPointer(type, stride, pointer);
61 }
glTexCoordPointerBounds(GLint size,GLenum type,GLsizei stride,const GLvoid * pointer,GLsizei)62 void glTexCoordPointerBounds(GLint size, GLenum type,
63         GLsizei stride, const GLvoid *pointer, GLsizei /*count*/) {
64     glTexCoordPointer(size, type, stride, pointer);
65 }
glVertexPointerBounds(GLint size,GLenum type,GLsizei stride,const GLvoid * pointer,GLsizei)66 void glVertexPointerBounds(GLint size, GLenum type,
67         GLsizei stride, const GLvoid *pointer, GLsizei /*count*/) {
68     glVertexPointer(size, type, stride, pointer);
69 }
70 
glPointSizePointerOESBounds(GLenum type,GLsizei stride,const GLvoid * pointer,GLsizei)71 void GL_APIENTRY glPointSizePointerOESBounds(GLenum type,
72         GLsizei stride, const GLvoid *pointer, GLsizei /*count*/) {
73     glPointSizePointerOES(type, stride, pointer);
74 }
75 
glMatrixIndexPointerOESBounds(GLint size,GLenum type,GLsizei stride,const GLvoid * pointer,GLsizei)76 GL_API void GL_APIENTRY glMatrixIndexPointerOESBounds(GLint size, GLenum type,
77         GLsizei stride, const GLvoid *pointer, GLsizei /*count*/) {
78     glMatrixIndexPointerOES(size, type, stride, pointer);
79 }
80 
glWeightPointerOESBounds(GLint size,GLenum type,GLsizei stride,const GLvoid * pointer,GLsizei)81 GL_API void GL_APIENTRY glWeightPointerOESBounds(GLint size, GLenum type,
82         GLsizei stride, const GLvoid *pointer, GLsizei /*count*/) {
83     glWeightPointerOES(size, type, stride, pointer);
84 }
85 
86 // ----------------------------------------------------------------------------
87 // Actual GL entry-points
88 // ----------------------------------------------------------------------------
89 
90 #undef API_ENTRY
91 #undef CALL_GL_API
92 #undef CALL_GL_API_INTERNAL_CALL
93 #undef CALL_GL_API_INTERNAL_SET_RETURN_VALUE
94 #undef CALL_GL_API_INTERNAL_DO_RETURN
95 #undef CALL_GL_API_RETURN
96 
97 #if USE_SLOW_BINDING
98 
99     #define API_ENTRY(_api) _api
100 
101     #define CALL_GL_API_INTERNAL_CALL(_api, ...)                         \
102         gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;  \
103         if (_c) return _c->_api(__VA_ARGS__);
104 
105     #define CALL_GL_API_INTERNAL_SET_RETURN_VALUE return 0;
106 
107     // This stays blank, since void functions will implicitly return, and
108     // all of the other functions will return 0 based on the previous macro.
109     #define CALL_GL_API_INTERNAL_DO_RETURN
110 
111 #elif defined(__arm__)
112 
113     #define GET_TLS(reg) "mrc p15, 0, " #reg ", c13, c0, 3 \n"
114 
115     #define API_ENTRY(_api) __attribute__((naked,noinline)) _api
116 
117     #define CALL_GL_API_INTERNAL_CALL(_api, ...)                 \
118         asm volatile(                                            \
119             GET_TLS(r12)                                         \
120             "ldr   r12, [r12, %[tls]] \n"                        \
121             "cmp   r12, #0            \n"                        \
122             "ldrne pc,  [r12, %[api]] \n"                        \
123             :                                                    \
124             : [tls] "J"(TLS_SLOT_OPENGL_API*4),                  \
125               [api] "J"(__builtin_offsetof(gl_hooks_t, gl._api)) \
126             : "r0", "r1", "r2", "r3", "r12"                      \
127         );
128 
129     #define CALL_GL_API_INTERNAL_SET_RETURN_VALUE \
130         asm volatile(                             \
131             "mov r0, #0 \n"                       \
132             :                                     \
133             :                                     \
134             : "r0"                                \
135         );
136 
137 
138     #define CALL_GL_API_INTERNAL_DO_RETURN \
139         asm volatile(                      \
140             "bx lr \n"                     \
141             :                              \
142             :                              \
143             : "r0"                         \
144         );
145 
146 #elif defined(__aarch64__)
147 
148     #define API_ENTRY(_api) __attribute__((naked,noinline)) _api
149 
150     #define CALL_GL_API_INTERNAL_CALL(_api, ...)                    \
151         asm volatile(                                               \
152             "mrs x16, tpidr_el0\n"                                  \
153             "ldr x16, [x16, %[tls]]\n"                              \
154             "cbz x16, 1f\n"                                         \
155             "ldr x16, [x16, %[api]]\n"                              \
156             "br  x16\n"                                             \
157             "1:\n"                                                  \
158             :                                                       \
159             : [tls] "i" (TLS_SLOT_OPENGL_API * sizeof(void*)),      \
160               [api] "i" (__builtin_offsetof(gl_hooks_t, gl._api))   \
161             : "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x16" \
162         );
163 
164     #define CALL_GL_API_INTERNAL_SET_RETURN_VALUE \
165         asm volatile(                             \
166             "mov w0, wzr \n"                      \
167             :                                     \
168             :                                     \
169             : "w0"                                \
170         );
171 
172     #define CALL_GL_API_INTERNAL_DO_RETURN \
173         asm volatile(                      \
174             "ret \n"                       \
175             :                              \
176             :                              \
177             :                              \
178         );
179 
180 #elif defined(__i386__)
181 
182     #define API_ENTRY(_api) __attribute__((naked,noinline)) _api
183 
184     #define CALL_GL_API_INTERNAL_CALL(_api, ...)                    \
185         __asm__ volatile(                                           \
186             "mov %%gs:0, %%eax\n"                                   \
187             "mov %P[tls](%%eax), %%eax\n"                           \
188             "test %%eax, %%eax\n"                                   \
189             "je 1f\n"                                               \
190             "jmp *%P[api](%%eax)\n"                                 \
191             "1:\n"                                                  \
192             :                                                       \
193             : [tls] "i" (TLS_SLOT_OPENGL_API*sizeof(void*)),        \
194               [api] "i" (__builtin_offsetof(gl_hooks_t, gl._api))   \
195             : "cc", "%eax"                                          \
196         );
197 
198     #define CALL_GL_API_INTERNAL_SET_RETURN_VALUE \
199         __asm__ volatile(                         \
200             "xor %%eax, %%eax\n"                  \
201             :                                     \
202             :                                     \
203             : "%eax"                              \
204         );
205 
206     #define CALL_GL_API_INTERNAL_DO_RETURN \
207         __asm__ volatile(                  \
208             "ret\n"                        \
209             :                              \
210             :                              \
211             :                              \
212         );
213 
214 #elif defined(__x86_64__)
215 
216     #define API_ENTRY(_api) __attribute__((naked,noinline)) _api
217 
218     #define CALL_GL_API_INTERNAL_CALL(_api, ...)                    \
219         __asm__ volatile(                                           \
220             "mov %%fs:0, %%rax\n"                                   \
221             "mov %P[tls](%%rax), %%rax\n"                           \
222             "test %%rax, %%rax\n"                                   \
223             "je 1f\n"                                               \
224             "jmp *%P[api](%%rax)\n"                                 \
225             "1:\n"                                                  \
226             :                                                       \
227             : [tls] "i" (TLS_SLOT_OPENGL_API*sizeof(void*)),        \
228               [api] "i" (__builtin_offsetof(gl_hooks_t, gl._api))   \
229             : "cc", "%rdi", "%rsi", "%rdx", "%rcx", "%r8", "%r9",   \
230               "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", \
231               "%xmm6", "%xmm7"                                      \
232         );
233 
234     #define CALL_GL_API_INTERNAL_SET_RETURN_VALUE \
235         __asm__ volatile(                         \
236             "xor %%eax, %%eax\n"                  \
237             :                                     \
238             :                                     \
239             : "%eax"                              \
240         );
241 
242     #define CALL_GL_API_INTERNAL_DO_RETURN \
243         __asm__ volatile(                  \
244             "retq\n"                       \
245             :                              \
246             :                              \
247             :                              \
248         );
249 
250 #elif defined(__mips64)
251 
252     #define API_ENTRY(_api) __attribute__((naked,noinline)) _api
253 
254     // t0:  $12
255     // fn:  $25
256     // tls: $3
257     // v0:  $2
258     #define CALL_GL_API_INTERNAL_CALL(_api, ...)                  \
259         asm volatile(                                             \
260             ".set  push\n\t"                                      \
261             ".set  noreorder\n\t"                                 \
262             "rdhwr $3, $29\n\t"                                   \
263             "ld    $12, %[OPENGL_API]($3)\n\t"                    \
264             "beqz  $12, 1f\n\t"                                   \
265             " move $25, $ra\n\t"                                  \
266             "ld    $12, %[API]($12)\n\t"                          \
267             "beqz  $12, 1f\n\t"                                   \
268             " nop\n\t"                                            \
269             "move  $25, $12\n\t"                                  \
270             "1:\n\t"                                              \
271             "jalr  $0, $25\n\t"                                   \
272             " move $2, $0\n\t"                                    \
273             ".set  pop\n\t"                                       \
274             :                                                     \
275             : [OPENGL_API] "I"(TLS_SLOT_OPENGL_API*sizeof(void*)),\
276               [API] "I"(__builtin_offsetof(gl_hooks_t, gl._api))  \
277             : "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9",     \
278               "$10", "$11", "$12", "$25"                          \
279         );
280 
281     #define CALL_GL_API_INTERNAL_SET_RETURN_VALUE
282     #define CALL_GL_API_INTERNAL_DO_RETURN
283 
284 #elif defined(__mips__)
285 
286     #define API_ENTRY(_api) __attribute__((naked,noinline)) _api
287 
288     // t0:  $8
289     // fn:  $25
290     // tls: $3
291     // v0:  $2
292     #define CALL_GL_API_INTERNAL_CALL(_api, ...)                 \
293         asm volatile(                                            \
294             ".set  push\n\t"                                     \
295             ".set  noreorder\n\t"                                \
296             ".set  mips32r2\n\t"                                 \
297             "rdhwr $3, $29\n\t"                                  \
298             "lw    $3, %[OPENGL_API]($3)\n\t"                    \
299             "beqz  $3, 1f\n\t"                                   \
300             " move $25,$ra\n\t"                                  \
301             "lw    $3, %[API]($3)\n\t"                           \
302             "beqz  $3, 1f\n\t"                                   \
303             " nop\n\t"                                           \
304             "move  $25, $3\n\t"                                  \
305             "1:\n\t"                                             \
306             "jalr  $0, $25\n\t"                                  \
307             " move $2, $0\n\t"                                   \
308             ".set  pop\n\t"                                      \
309             :                                                    \
310             : [OPENGL_API] "I"(TLS_SLOT_OPENGL_API*4),           \
311               [API] "I"(__builtin_offsetof(gl_hooks_t, gl._api)) \
312             : "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$25"    \
313         );
314 
315     #define CALL_GL_API_INTERNAL_SET_RETURN_VALUE
316     #define CALL_GL_API_INTERNAL_DO_RETURN
317 
318 #endif
319 
320 #define CALL_GL_API(_api, ...) \
321     CALL_GL_API_INTERNAL_CALL(_api, __VA_ARGS__) \
322     CALL_GL_API_INTERNAL_DO_RETURN
323 
324 #define CALL_GL_API_RETURN(_api, ...) \
325     CALL_GL_API_INTERNAL_CALL(_api, __VA_ARGS__) \
326     CALL_GL_API_INTERNAL_SET_RETURN_VALUE \
327     CALL_GL_API_INTERNAL_DO_RETURN
328 
329 extern "C" {
330 #pragma GCC diagnostic ignored "-Wunused-parameter"
331 #include "gl_api.in"
332 #include "glext_api.in"
333 #pragma GCC diagnostic warning "-Wunused-parameter"
334 }
335 
336 #undef API_ENTRY
337 #undef CALL_GL_API
338 #undef CALL_GL_API_INTERNAL_CALL
339 #undef CALL_GL_API_INTERNAL_SET_RETURN_VALUE
340 #undef CALL_GL_API_INTERNAL_DO_RETURN
341 #undef CALL_GL_API_RETURN
342 
343 /*
344  * glGetString() is special because we expose some extensions in the wrapper
345  */
346 
347 extern "C" const GLubyte * __glGetString(GLenum name);
348 
glGetString(GLenum name)349 const GLubyte * glGetString(GLenum name) {
350     const GLubyte * ret = egl_get_string_for_current_context(name);
351     if (ret == NULL) {
352         gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;
353         ret = _c->glGetString(name);
354     }
355     return ret;
356 }
357