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 54 void glColorPointerBounds(GLint size, GLenum type, GLsizei stride, 55 const GLvoid *ptr, GLsizei /*count*/) { 56 glColorPointer(size, type, stride, ptr); 57 } 58 void glNormalPointerBounds(GLenum type, GLsizei stride, 59 const GLvoid *pointer, GLsizei /*count*/) { 60 glNormalPointer(type, stride, pointer); 61 } 62 void glTexCoordPointerBounds(GLint size, GLenum type, 63 GLsizei stride, const GLvoid *pointer, GLsizei /*count*/) { 64 glTexCoordPointer(size, type, stride, pointer); 65 } 66 void glVertexPointerBounds(GLint size, GLenum type, 67 GLsizei stride, const GLvoid *pointer, GLsizei /*count*/) { 68 glVertexPointer(size, type, stride, pointer); 69 } 70 71 void GL_APIENTRY glPointSizePointerOESBounds(GLenum type, 72 GLsizei stride, const GLvoid *pointer, GLsizei /*count*/) { 73 glPointSizePointerOES(type, stride, pointer); 74 } 75 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 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 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