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