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