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 32using namespace android; 33 34// ---------------------------------------------------------------------------- 35// extensions for the framework 36// ---------------------------------------------------------------------------- 37 38extern "C" { 39GL_API void GL_APIENTRY glColorPointerBounds(GLint size, GLenum type, GLsizei stride, 40 const GLvoid *ptr, GLsizei count); 41GL_API void GL_APIENTRY glNormalPointerBounds(GLenum type, GLsizei stride, 42 const GLvoid *pointer, GLsizei count); 43GL_API void GL_APIENTRY glTexCoordPointerBounds(GLint size, GLenum type, 44 GLsizei stride, const GLvoid *pointer, GLsizei count); 45GL_API void GL_APIENTRY glVertexPointerBounds(GLint size, GLenum type, 46 GLsizei stride, const GLvoid *pointer, GLsizei count); 47GL_API void GL_APIENTRY glPointSizePointerOESBounds(GLenum type, 48 GLsizei stride, const GLvoid *pointer, GLsizei count); 49GL_API void GL_APIENTRY glMatrixIndexPointerOESBounds(GLint size, GLenum type, 50 GLsizei stride, const GLvoid *pointer, GLsizei count); 51GL_API void GL_APIENTRY glWeightPointerOESBounds(GLint size, GLenum type, 52 GLsizei stride, const GLvoid *pointer, GLsizei count); 53} 54 55void glColorPointerBounds(GLint size, GLenum type, GLsizei stride, 56 const GLvoid *ptr, GLsizei /*count*/) { 57 glColorPointer(size, type, stride, ptr); 58} 59void glNormalPointerBounds(GLenum type, GLsizei stride, 60 const GLvoid *pointer, GLsizei /*count*/) { 61 glNormalPointer(type, stride, pointer); 62} 63void glTexCoordPointerBounds(GLint size, GLenum type, 64 GLsizei stride, const GLvoid *pointer, GLsizei /*count*/) { 65 glTexCoordPointer(size, type, stride, pointer); 66} 67void glVertexPointerBounds(GLint size, GLenum type, 68 GLsizei stride, const GLvoid *pointer, GLsizei /*count*/) { 69 glVertexPointer(size, type, stride, pointer); 70} 71 72void GL_APIENTRY glPointSizePointerOESBounds(GLenum type, 73 GLsizei stride, const GLvoid *pointer, GLsizei /*count*/) { 74 glPointSizePointerOES(type, stride, pointer); 75} 76 77GL_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 82GL_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 251extern "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 266extern "C" const GLubyte * __glGetString(GLenum name); 267 268const 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