blob: 6dd87c28e45c01eb926c51c95e42d524a79859ef [file] [log] [blame]
Jesse Hall47743382013-02-08 11:13:46 -08001/*
Mathias Agopianb1a39d62009-05-27 20:38:06 -07002 ** Copyright 2007, The Android Open Source Project
3 **
Jesse Hall47743382013-02-08 11:13:46 -08004 ** 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
Mathias Agopianb1a39d62009-05-27 20:38:06 -07007 **
Jesse Hall47743382013-02-08 11:13:46 -08008 ** http://www.apache.org/licenses/LICENSE-2.0
Mathias Agopianb1a39d62009-05-27 20:38:06 -07009 **
Jesse Hall47743382013-02-08 11:13:46 -080010 ** 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
Mathias Agopianb1a39d62009-05-27 20:38:06 -070014 ** 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
Mathias Agopianb1a39d62009-05-27 20:38:06 -070023#include <cutils/log.h>
24#include <cutils/properties.h>
25
Mathias Agopian39c24a22013-04-04 23:17:56 -070026#include "../hooks.h"
27#include "../egl_impl.h"
Mathias Agopianb1a39d62009-05-27 20:38:06 -070028
29using namespace android;
30
31// ----------------------------------------------------------------------------
32// Actual GL entry-points
33// ----------------------------------------------------------------------------
34
35#undef API_ENTRY
36#undef CALL_GL_API
Stephen Hines3e8fce42016-03-22 23:35:27 -070037#undef CALL_GL_API_INTERNAL_CALL
38#undef CALL_GL_API_INTERNAL_SET_RETURN_VALUE
39#undef CALL_GL_API_INTERNAL_DO_RETURN
Mathias Agopianb1a39d62009-05-27 20:38:06 -070040#undef CALL_GL_API_RETURN
41
Jesse Hall30a41aa2014-05-30 23:32:12 -070042#if USE_SLOW_BINDING
43
44 #define API_ENTRY(_api) _api
45
Stephen Hines3e8fce42016-03-22 23:35:27 -070046 #define CALL_GL_API_INTERNAL_CALL(_api, ...) \
Jesse Hall30a41aa2014-05-30 23:32:12 -070047 gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl; \
48 if (_c) return _c->_api(__VA_ARGS__);
49
Stephen Hines3e8fce42016-03-22 23:35:27 -070050 #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
Jesse Hall30a41aa2014-05-30 23:32:12 -070056#elif defined(__arm__)
Duane Sand46b42532013-03-27 10:58:06 -070057
Elliott Hughes288870e2013-02-13 17:30:54 -080058 #define GET_TLS(reg) "mrc p15, 0, " #reg ", c13, c0, 3 \n"
Mathias Agopian673d2db2009-10-14 02:39:53 -070059
Stephen Hines3e8fce42016-03-22 23:35:27 -070060 #define API_ENTRY(_api) __attribute__((naked,noinline)) _api
Mathias Agopianb1a39d62009-05-27 20:38:06 -070061
Stephen Hines3e8fce42016-03-22 23:35:27 -070062 #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 );
Mathias Agopian673d2db2009-10-14 02:39:53 -070090
Jesse Hall30a41aa2014-05-30 23:32:12 -070091#elif defined(__aarch64__)
92
Stephen Hines3e8fce42016-03-22 23:35:27 -070093 #define API_ENTRY(_api) __attribute__((naked,noinline)) _api
Jesse Hall30a41aa2014-05-30 23:32:12 -070094
Stephen Hines3e8fce42016-03-22 23:35:27 -070095 #define CALL_GL_API_INTERNAL_CALL(_api, ...) \
Jesse Hall30a41aa2014-05-30 23:32:12 -070096 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)) \
Stephen Hines3e8fce42016-03-22 23:35:27 -0700106 : "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 : \
Jesse Hall30a41aa2014-05-30 23:32:12 -0700123 );
124
125#elif defined(__i386__)
mwajdeczc80aafa2014-05-26 13:56:37 +0200126
Stephen Hines3e8fce42016-03-22 23:35:27 -0700127 #define API_ENTRY(_api) __attribute__((naked,noinline)) _api
mwajdeczc80aafa2014-05-26 13:56:37 +0200128
Stephen Hines3e8fce42016-03-22 23:35:27 -0700129 #define CALL_GL_API_INTERNAL_CALL(_api, ...) \
mwajdeczc80aafa2014-05-26 13:56:37 +0200130 __asm__ volatile( \
Stephen Hines3e8fce42016-03-22 23:35:27 -0700131 "mov %%gs:0, %%eax\n" \
132 "mov %P[tls](%%eax), %%eax\n" \
133 "test %%eax, %%eax\n" \
mwajdeczc80aafa2014-05-26 13:56:37 +0200134 "je 1f\n" \
Stephen Hines3e8fce42016-03-22 23:35:27 -0700135 "jmp *%P[api](%%eax)\n" \
mwajdeczc80aafa2014-05-26 13:56:37 +0200136 "1:\n" \
Stephen Hines3e8fce42016-03-22 23:35:27 -0700137 : \
mwajdeczc80aafa2014-05-26 13:56:37 +0200138 : [tls] "i" (TLS_SLOT_OPENGL_API*sizeof(void*)), \
139 [api] "i" (__builtin_offsetof(gl_hooks_t, gl._api)) \
Stephen Hines3e8fce42016-03-22 23:35:27 -0700140 : "cc", "%eax" \
mwajdeczc80aafa2014-05-26 13:56:37 +0200141 );
142
Stephen Hines3e8fce42016-03-22 23:35:27 -0700143 #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
Jesse Hall30a41aa2014-05-30 23:32:12 -0700159#elif defined(__x86_64__)
mwajdeczc80aafa2014-05-26 13:56:37 +0200160
Stephen Hines3e8fce42016-03-22 23:35:27 -0700161 #define API_ENTRY(_api) __attribute__((naked,noinline)) _api
mwajdeczc80aafa2014-05-26 13:56:37 +0200162
Stephen Hines3e8fce42016-03-22 23:35:27 -0700163 #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" \
mwajdeczc80aafa2014-05-26 13:56:37 +0200168 "je 1f\n" \
Stephen Hines3e8fce42016-03-22 23:35:27 -0700169 "jmp *%P[api](%%rax)\n" \
mwajdeczc80aafa2014-05-26 13:56:37 +0200170 "1:\n" \
Stephen Hines3e8fce42016-03-22 23:35:27 -0700171 : \
mwajdeczc80aafa2014-05-26 13:56:37 +0200172 : [tls] "i" (TLS_SLOT_OPENGL_API*sizeof(void*)), \
173 [api] "i" (__builtin_offsetof(gl_hooks_t, gl._api)) \
Stephen Hines3e8fce42016-03-22 23:35:27 -0700174 : "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 );
mwajdeczc80aafa2014-05-26 13:56:37 +0200194
Duane Sand6701fbe2014-11-26 13:17:40 -0800195#elif defined(__mips64)
196
Stephen Hines3e8fce42016-03-22 23:35:27 -0700197 #define API_ENTRY(_api) __attribute__((naked,noinline)) _api
Duane Sand6701fbe2014-11-26 13:17:40 -0800198
Stephen Hines3e8fce42016-03-22 23:35:27 -0700199 // 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" \
Duane Sand6701fbe2014-11-26 13:17:40 -0800224 );
225
Stephen Hines3e8fce42016-03-22 23:35:27 -0700226 #define CALL_GL_API_INTERNAL_SET_RETURN_VALUE
227 #define CALL_GL_API_INTERNAL_DO_RETURN
228
Jesse Hall30a41aa2014-05-30 23:32:12 -0700229#elif defined(__mips__)
Duane Sand46b42532013-03-27 10:58:06 -0700230
Stephen Hines3e8fce42016-03-22 23:35:27 -0700231 #define API_ENTRY(_api) __attribute__((naked,noinline)) _api
Duane Sand46b42532013-03-27 10:58:06 -0700232
Stephen Hines3e8fce42016-03-22 23:35:27 -0700233 // t0: $8
234 // fn: $25
235 // tls: $3
236 // v0: $2
237 #define CALL_GL_API_INTERNAL_CALL(_api, ...) \
Duane Sand46b42532013-03-27 10:58:06 -0700238 asm volatile( \
239 ".set push\n\t" \
240 ".set noreorder\n\t" \
Duane Sandecacc3f2015-02-02 16:54:15 -0800241 ".set mips32r2\n\t" \
Stephen Hines3e8fce42016-03-22 23:35:27 -0700242 "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" \
Duane Sand6701fbe2014-11-26 13:17:40 -0800248 " nop\n\t" \
Stephen Hines3e8fce42016-03-22 23:35:27 -0700249 "move $25, $3\n\t" \
Duane Sand46b42532013-03-27 10:58:06 -0700250 "1:\n\t" \
Stephen Hines3e8fce42016-03-22 23:35:27 -0700251 "jalr $0, $25\n\t" \
252 " move $2, $0\n\t" \
Duane Sand46b42532013-03-27 10:58:06 -0700253 ".set pop\n\t" \
Stephen Hines3e8fce42016-03-22 23:35:27 -0700254 : \
Duane Sand46b42532013-03-27 10:58:06 -0700255 : [OPENGL_API] "I"(TLS_SLOT_OPENGL_API*4), \
256 [API] "I"(__builtin_offsetof(gl_hooks_t, gl._api)) \
Stephen Hines3e8fce42016-03-22 23:35:27 -0700257 : "$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
Duane Sand46b42532013-03-27 10:58:06 -0700262
Mathias Agopianb1a39d62009-05-27 20:38:06 -0700263#endif
264
Stephen Hines3e8fce42016-03-22 23:35:27 -0700265#define CALL_GL_API(_api, ...) \
266 CALL_GL_API_INTERNAL_CALL(_api, __VA_ARGS__) \
267 CALL_GL_API_INTERNAL_DO_RETURN
268
Mathias Agopiane0ea89c2013-06-14 19:08:36 -0700269#define CALL_GL_API_RETURN(_api, ...) \
Stephen Hines3e8fce42016-03-22 23:35:27 -0700270 CALL_GL_API_INTERNAL_CALL(_api, __VA_ARGS__) \
271 CALL_GL_API_INTERNAL_SET_RETURN_VALUE \
272 CALL_GL_API_INTERNAL_DO_RETURN
Mathias Agopianb1a39d62009-05-27 20:38:06 -0700273
274extern "C" {
Jesse Hallbbbddb82014-05-13 21:13:14 -0700275#pragma GCC diagnostic ignored "-Wunused-parameter"
Jesse Hall4c0596f2014-05-13 16:48:35 -0700276#include "gl2_api.in"
Mathias Agopianb1a39d62009-05-27 20:38:06 -0700277#include "gl2ext_api.in"
Jesse Hallbbbddb82014-05-13 21:13:14 -0700278#pragma GCC diagnostic warning "-Wunused-parameter"
Mathias Agopianb1a39d62009-05-27 20:38:06 -0700279}
280
281#undef API_ENTRY
282#undef CALL_GL_API
Stephen Hines3e8fce42016-03-22 23:35:27 -0700283#undef CALL_GL_API_INTERNAL_CALL
284#undef CALL_GL_API_INTERNAL_SET_RETURN_VALUE
285#undef CALL_GL_API_INTERNAL_DO_RETURN
Mathias Agopianb1a39d62009-05-27 20:38:06 -0700286#undef CALL_GL_API_RETURN
287
Mathias Agopian48d438d2012-01-28 21:44:00 -0800288/*
Alistair Strachanedfe72e2015-05-22 14:10:09 -0700289 * 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.
Mathias Agopian48d438d2012-01-28 21:44:00 -0800293 */
294
Alistair Strachanedfe72e2015-05-22 14:10:09 -0700295extern "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}
Mathias Agopian48d438d2012-01-28 21:44:00 -0800303
Alistair Strachanedfe72e2015-05-22 14:10:09 -0700304const GLubyte * glGetString(GLenum name) {
Mathias Agopian48d438d2012-01-28 21:44:00 -0800305 const GLubyte * ret = egl_get_string_for_current_context(name);
306 if (ret == NULL) {
Mathias Agopiane0ea89c2013-06-14 19:08:36 -0700307 gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;
Anshuman Dani06270712013-11-05 21:04:00 +0530308 if(_c) ret = _c->glGetString(name);
Mathias Agopian48d438d2012-01-28 21:44:00 -0800309 }
310 return ret;
311}
Alistair Strachanedfe72e2015-05-22 14:10:09 -0700312
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}