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 <string.h>
19 #include <errno.h>
20 
21 #include <sys/ioctl.h>
22 
23 #include <GLES/gl.h>
24 #include <GLES/glext.h>
25 
26 #include <cutils/log.h>
27 #include <cutils/properties.h>
28 
29 #include "../hooks.h"
30 #include "../egl_impl.h"
31 
32 using namespace android;
33 
34 // ----------------------------------------------------------------------------
35 // extensions for the framework
36 // ----------------------------------------------------------------------------
37 
38 extern "C" {
39 GL_API void GL_APIENTRY glColorPointerBounds(GLint size, GLenum type, GLsizei stride,
40         const GLvoid *ptr, GLsizei count);
41 GL_API void GL_APIENTRY glNormalPointerBounds(GLenum type, GLsizei stride,
42         const GLvoid *pointer, GLsizei count);
43 GL_API void GL_APIENTRY glTexCoordPointerBounds(GLint size, GLenum type,
44         GLsizei stride, const GLvoid *pointer, GLsizei count);
45 GL_API void GL_APIENTRY glVertexPointerBounds(GLint size, GLenum type,
46         GLsizei stride, const GLvoid *pointer, GLsizei count);
47 GL_API void GL_APIENTRY glPointSizePointerOESBounds(GLenum type,
48         GLsizei stride, const GLvoid *pointer, GLsizei count);
49 GL_API void GL_APIENTRY glMatrixIndexPointerOESBounds(GLint size, GLenum type,
50         GLsizei stride, const GLvoid *pointer, GLsizei count);
51 GL_API void GL_APIENTRY glWeightPointerOESBounds(GLint size, GLenum type,
52         GLsizei stride, const GLvoid *pointer, GLsizei count);
53 }
54 
glColorPointerBounds(GLint size,GLenum type,GLsizei stride,const GLvoid * ptr,GLsizei)55 void glColorPointerBounds(GLint size, GLenum type, GLsizei stride,
56         const GLvoid *ptr, GLsizei /*count*/) {
57     glColorPointer(size, type, stride, ptr);
58 }
glNormalPointerBounds(GLenum type,GLsizei stride,const GLvoid * pointer,GLsizei)59 void glNormalPointerBounds(GLenum type, GLsizei stride,
60         const GLvoid *pointer, GLsizei /*count*/) {
61     glNormalPointer(type, stride, pointer);
62 }
glTexCoordPointerBounds(GLint size,GLenum type,GLsizei stride,const GLvoid * pointer,GLsizei)63 void glTexCoordPointerBounds(GLint size, GLenum type,
64         GLsizei stride, const GLvoid *pointer, GLsizei /*count*/) {
65     glTexCoordPointer(size, type, stride, pointer);
66 }
glVertexPointerBounds(GLint size,GLenum type,GLsizei stride,const GLvoid * pointer,GLsizei)67 void glVertexPointerBounds(GLint size, GLenum type,
68         GLsizei stride, const GLvoid *pointer, GLsizei /*count*/) {
69     glVertexPointer(size, type, stride, pointer);
70 }
71 
glPointSizePointerOESBounds(GLenum type,GLsizei stride,const GLvoid * pointer,GLsizei)72 void GL_APIENTRY glPointSizePointerOESBounds(GLenum type,
73         GLsizei stride, const GLvoid *pointer, GLsizei /*count*/) {
74     glPointSizePointerOES(type, stride, pointer);
75 }
76 
glMatrixIndexPointerOESBounds(GLint size,GLenum type,GLsizei stride,const GLvoid * pointer,GLsizei)77 GL_API void GL_APIENTRY glMatrixIndexPointerOESBounds(GLint size, GLenum type,
78         GLsizei stride, const GLvoid *pointer, GLsizei /*count*/) {
79     glMatrixIndexPointerOES(size, type, stride, pointer);
80 }
81 
glWeightPointerOESBounds(GLint size,GLenum type,GLsizei stride,const GLvoid * pointer,GLsizei)82 GL_API void GL_APIENTRY glWeightPointerOESBounds(GLint size, GLenum type,
83         GLsizei stride, const GLvoid *pointer, GLsizei /*count*/) {
84     glWeightPointerOES(size, type, stride, pointer);
85 }
86 
87 // ----------------------------------------------------------------------------
88 // Actual GL entry-points
89 // ----------------------------------------------------------------------------
90 
91 #undef API_ENTRY
92 #undef CALL_GL_API
93 #undef CALL_GL_API_RETURN
94 
95 #if USE_SLOW_BINDING
96 
97     #define API_ENTRY(_api) _api
98 
99     #define CALL_GL_API(_api, ...)                                       \
100         gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;  \
101         if (_c) return _c->_api(__VA_ARGS__);
102 
103 #elif defined(__arm__)
104 
105     #define GET_TLS(reg) "mrc p15, 0, " #reg ", c13, c0, 3 \n"
106 
107     #define API_ENTRY(_api) __attribute__((noinline)) _api
108 
109     #define CALL_GL_API(_api, ...)                              \
110          asm volatile(                                          \
111             GET_TLS(r12)                                        \
112             "ldr   r12, [r12, %[tls]] \n"                       \
113             "cmp   r12, #0            \n"                       \
114             "ldrne pc,  [r12, %[api]] \n"                       \
115             :                                                   \
116             : [tls] "J"(TLS_SLOT_OPENGL_API*4),                 \
117               [api] "J"(__builtin_offsetof(gl_hooks_t, gl._api))    \
118             : "r12"                                             \
119             );
120 
121 #elif defined(__aarch64__)
122 
123     #define API_ENTRY(_api) __attribute__((noinline)) _api
124 
125     #define CALL_GL_API(_api, ...)                                  \
126         asm volatile(                                               \
127             "mrs x16, tpidr_el0\n"                                  \
128             "ldr x16, [x16, %[tls]]\n"                              \
129             "cbz x16, 1f\n"                                         \
130             "ldr x16, [x16, %[api]]\n"                              \
131             "br  x16\n"                                             \
132             "1:\n"                                                  \
133             :                                                       \
134             : [tls] "i" (TLS_SLOT_OPENGL_API * sizeof(void*)),      \
135               [api] "i" (__builtin_offsetof(gl_hooks_t, gl._api))   \
136             : "x16"                                                 \
137         );
138 
139 #elif defined(__i386__)
140 
141     #define API_ENTRY(_api) __attribute__((noinline,optimize("omit-frame-pointer"))) _api
142 
143     #define CALL_GL_API(_api, ...)                                  \
144         register void* fn;                                          \
145         __asm__ volatile(                                           \
146             "mov %%gs:0, %[fn]\n"                                   \
147             "mov %P[tls](%[fn]), %[fn]\n"                           \
148             "test %[fn], %[fn]\n"                                   \
149             "je 1f\n"                                               \
150             "jmp *%P[api](%[fn])\n"                                 \
151             "1:\n"                                                  \
152             : [fn] "=r" (fn)                                        \
153             : [tls] "i" (TLS_SLOT_OPENGL_API*sizeof(void*)),        \
154               [api] "i" (__builtin_offsetof(gl_hooks_t, gl._api))   \
155             : "cc"                                                  \
156             );
157 
158 #elif defined(__x86_64__)
159 
160     #define API_ENTRY(_api) __attribute__((noinline,optimize("omit-frame-pointer"))) _api
161 
162     #define CALL_GL_API(_api, ...)                                  \
163          register void** fn;                                        \
164          __asm__ volatile(                                          \
165             "mov %%fs:0, %[fn]\n"                                   \
166             "mov %P[tls](%[fn]), %[fn]\n"                           \
167             "test %[fn], %[fn]\n"                                   \
168             "je 1f\n"                                               \
169             "jmp *%P[api](%[fn])\n"                                 \
170             "1:\n"                                                  \
171             : [fn] "=r" (fn)                                        \
172             : [tls] "i" (TLS_SLOT_OPENGL_API*sizeof(void*)),        \
173               [api] "i" (__builtin_offsetof(gl_hooks_t, gl._api))   \
174             : "cc"                                                  \
175             );
176 
177 #elif defined(__mips64)
178 
179     #define API_ENTRY(_api) __attribute__((noinline)) _api
180 
181     #define CALL_GL_API(_api, ...)                            \
182     register unsigned long _t0 asm("$12");                    \
183     register unsigned long _fn asm("$25");                    \
184     register unsigned long _tls asm("$3");                    \
185     register unsigned long _v0 asm("$2");                     \
186     asm volatile(                                             \
187         ".set  push\n\t"                                      \
188         ".set  noreorder\n\t"                                 \
189         "rdhwr %[tls], $29\n\t"                               \
190         "ld    %[t0], %[OPENGL_API](%[tls])\n\t"              \
191         "beqz  %[t0], 1f\n\t"                                 \
192         " move %[fn], $ra\n\t"                                \
193         "ld    %[t0], %[API](%[t0])\n\t"                      \
194         "beqz  %[t0], 1f\n\t"                                 \
195         " nop\n\t"                                            \
196         "move  %[fn], %[t0]\n\t"                              \
197         "1:\n\t"                                              \
198         "jalr  $0, %[fn]\n\t"                                 \
199         " move %[v0], $0\n\t"                                 \
200         ".set  pop\n\t"                                       \
201         : [fn] "=c"(_fn),                                     \
202           [tls] "=&r"(_tls),                                  \
203           [t0] "=&r"(_t0),                                    \
204           [v0] "=&r"(_v0)                                     \
205         : [OPENGL_API] "I"(TLS_SLOT_OPENGL_API*sizeof(void*)),\
206           [API] "I"(__builtin_offsetof(gl_hooks_t, gl._api))  \
207         :                                                     \
208         );
209 
210 #elif defined(__mips__)
211 
212     #define API_ENTRY(_api) __attribute__((noinline)) _api
213 
214     #define CALL_GL_API(_api, ...)                               \
215         register unsigned int _t0 asm("$8");                     \
216         register unsigned int _fn asm("$25");                    \
217         register unsigned int _tls asm("$3");                    \
218         register unsigned int _v0 asm("$2");                     \
219         asm volatile(                                            \
220             ".set  push\n\t"                                     \
221             ".set  noreorder\n\t"                                \
222             ".set  mips32r2\n\t"                                 \
223             "rdhwr %[tls], $29\n\t"                              \
224             "lw    %[t0], %[OPENGL_API](%[tls])\n\t"             \
225             "beqz  %[t0], 1f\n\t"                                \
226             " move %[fn], $ra\n\t"                               \
227             "lw    %[t0], %[API](%[t0])\n\t"                     \
228             "beqz  %[t0], 1f\n\t"                                \
229             " nop\n\t"                                           \
230             "move  %[fn], %[t0]\n\t"                             \
231             "1:\n\t"                                             \
232             "jalr  $0, %[fn]\n\t"                                \
233             " move %[v0], $0\n\t"                                \
234             ".set  pop\n\t"                                      \
235             : [fn] "=c"(_fn),                                    \
236               [tls] "=&r"(_tls),                                 \
237               [t0] "=&r"(_t0),                                   \
238               [v0] "=&r"(_v0)                                    \
239             : [OPENGL_API] "I"(TLS_SLOT_OPENGL_API*4),           \
240               [API] "I"(__builtin_offsetof(gl_hooks_t, gl._api)) \
241             :                                                    \
242             );
243 
244 #endif
245 
246 #define CALL_GL_API_RETURN(_api, ...) \
247     CALL_GL_API(_api, __VA_ARGS__) \
248     return 0;
249 
250 
251 extern "C" {
252 #pragma GCC diagnostic ignored "-Wunused-parameter"
253 #include "gl_api.in"
254 #include "glext_api.in"
255 #pragma GCC diagnostic warning "-Wunused-parameter"
256 }
257 
258 #undef API_ENTRY
259 #undef CALL_GL_API
260 #undef CALL_GL_API_RETURN
261 
262 /*
263  * glGetString() is special because we expose some extensions in the wrapper
264  */
265 
266 extern "C" const GLubyte * __glGetString(GLenum name);
267 
glGetString(GLenum name)268 const GLubyte * glGetString(GLenum name) {
269     const GLubyte * ret = egl_get_string_for_current_context(name);
270     if (ret == NULL) {
271         gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;
272         ret = _c->glGetString(name);
273     }
274     return ret;
275 }
276