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
28using 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
273extern "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
294extern "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
303const GLubyte * glGetString(GLenum name) {
304    const GLubyte * ret = egl_get_string_for_current_context(name);
305    if (ret == NULL) {
306        gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;
307        if(_c) ret = _c->glGetString(name);
308    }
309    return ret;
310}
311
312const GLubyte * glGetStringi(GLenum name, GLuint index) {
313    const GLubyte * ret = egl_get_string_for_current_context(name, index);
314    if (ret == NULL) {
315        gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;
316        if(_c) ret = _c->glGetStringi(name, index);
317    }
318    return ret;
319}
320
321void glGetBooleanv(GLenum pname, GLboolean * data) {
322    if (pname == GL_NUM_EXTENSIONS) {
323        int num_exts = egl_get_num_extensions_for_current_context();
324        if (num_exts >= 0) {
325            *data = num_exts > 0 ? GL_TRUE : GL_FALSE;
326            return;
327        }
328    }
329
330    gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;
331    if (_c) _c->glGetBooleanv(pname, data);
332}
333
334void glGetFloatv(GLenum pname, GLfloat * data) {
335    if (pname == GL_NUM_EXTENSIONS) {
336        int num_exts = egl_get_num_extensions_for_current_context();
337        if (num_exts >= 0) {
338            *data = (GLfloat)num_exts;
339            return;
340        }
341    }
342
343    gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;
344    if (_c) _c->glGetFloatv(pname, data);
345}
346
347void glGetIntegerv(GLenum pname, GLint * data) {
348    if (pname == GL_NUM_EXTENSIONS) {
349        int num_exts = egl_get_num_extensions_for_current_context();
350        if (num_exts >= 0) {
351            *data = (GLint)num_exts;
352            return;
353        }
354    }
355
356    gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;
357    if (_c) _c->glGetIntegerv(pname, data);
358}
359
360void glGetInteger64v(GLenum pname, GLint64 * data) {
361    if (pname == GL_NUM_EXTENSIONS) {
362        int num_exts = egl_get_num_extensions_for_current_context();
363        if (num_exts >= 0) {
364            *data = (GLint64)num_exts;
365            return;
366        }
367    }
368
369    gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;
370    if (_c) _c->glGetInteger64v(pname, data);
371}
372