matrix.cpp revision 7c1b96a165f970a09ed239bb4fb3f1b0d8f2a407
1/* libs/opengles/matrix.cpp 2** 3** Copyright 2006, The Android Open Source Project 4** 5** Licensed under the Apache License, Version 2.0 (the "License"); 6** you may not use this file except in compliance with the License. 7** You may obtain a copy of the License at 8** 9** http://www.apache.org/licenses/LICENSE-2.0 10** 11** Unless required by applicable law or agreed to in writing, software 12** distributed under the License is distributed on an "AS IS" BASIS, 13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14** See the License for the specific language governing permissions and 15** limitations under the License. 16*/ 17 18#include <stdlib.h> 19#include <stdio.h> 20 21#include "context.h" 22#include "fp.h" 23#include "state.h" 24#include "matrix.h" 25#include "vertex.h" 26#include "light.h" 27 28#if defined(__arm__) && defined(__thumb__) 29#warning "matrix.cpp should not be compiled in thumb on ARM." 30#endif 31 32#define I(_i, _j) ((_j)+ 4*(_i)) 33 34namespace android { 35 36// ---------------------------------------------------------------------------- 37 38static const GLfloat gIdentityf[16] = { 1,0,0,0, 39 0,1,0,0, 40 0,0,1,0, 41 0,0,0,1 }; 42 43static const matrixx_t gIdentityx = { 44 { 0x10000,0,0,0, 45 0,0x10000,0,0, 46 0,0,0x10000,0, 47 0,0,0,0x10000 48 } 49 }; 50 51static void point2__nop(transform_t const*, vec4_t* c, vec4_t const* o); 52static void point3__nop(transform_t const*, vec4_t* c, vec4_t const* o); 53static void point4__nop(transform_t const*, vec4_t* c, vec4_t const* o); 54static void normal__nop(transform_t const*, vec4_t* c, vec4_t const* o); 55static void point2__generic(transform_t const*, vec4_t* c, vec4_t const* o); 56static void point3__generic(transform_t const*, vec4_t* c, vec4_t const* o); 57static void point4__generic(transform_t const*, vec4_t* c, vec4_t const* o); 58static void normal__generic(transform_t const*, vec4_t* c, vec4_t const* o); 59 60// ---------------------------------------------------------------------------- 61#if 0 62#pragma mark - 63#endif 64 65void ogles_init_matrix(ogles_context_t* c) 66{ 67 c->transforms.modelview.init(OGLES_MODELVIEW_STACK_DEPTH); 68 c->transforms.projection.init(OGLES_PROJECTION_STACK_DEPTH); 69 for (int i=0; i<GGL_TEXTURE_UNIT_COUNT ; i++) 70 c->transforms.texture[i].init(OGLES_TEXTURE_STACK_DEPTH); 71 72 c->transforms.current = &c->transforms.modelview; 73 c->transforms.matrixMode = GL_MODELVIEW; 74 c->transforms.dirty = transform_state_t::VIEWPORT | 75 transform_state_t::MVUI | 76 transform_state_t::MVIT | 77 transform_state_t::MVP; 78 c->transforms.mvp.loadIdentity(); 79 c->transforms.mvp4.loadIdentity(); 80 c->transforms.mvit4.loadIdentity(); 81 c->transforms.mvui.loadIdentity(); 82 c->transforms.vpt.loadIdentity(); 83 c->transforms.vpt.zNear = 0.0f; 84 c->transforms.vpt.zFar = 1.0f; 85} 86 87void ogles_uninit_matrix(ogles_context_t* c) 88{ 89 c->transforms.modelview.uninit(); 90 c->transforms.projection.uninit(); 91 for (int i=0; i<GGL_TEXTURE_UNIT_COUNT ; i++) 92 c->transforms.texture[i].uninit(); 93} 94 95static void validate_perspective(ogles_context_t* c, vertex_t* v) 96{ 97 const uint32_t enables = c->rasterizer.state.enables; 98 c->arrays.perspective = (c->clipPlanes.enable) ? 99 ogles_vertex_clipAllPerspective3D : ogles_vertex_perspective3D; 100 if (enables & (GGL_ENABLE_DEPTH_TEST|GGL_ENABLE_FOG)) { 101 c->arrays.perspective = (c->clipPlanes.enable) ? 102 ogles_vertex_clipAllPerspective3DZ : ogles_vertex_perspective3DZ; 103 } 104 if ((c->arrays.vertex.size != 4) && 105 (c->transforms.mvp4.flags & transform_t::FLAGS_2D_PROJECTION)) { 106 c->arrays.perspective = ogles_vertex_perspective2D; 107 } 108 c->arrays.perspective(c, v); 109} 110 111void ogles_invalidate_perspective(ogles_context_t* c) 112{ 113 c->arrays.perspective = validate_perspective; 114} 115 116void ogles_validate_transform_impl(ogles_context_t* c, uint32_t want) 117{ 118 int dirty = c->transforms.dirty & want; 119 120 // Validate the modelview 121 if (dirty & transform_state_t::MODELVIEW) { 122 c->transforms.modelview.validate(); 123 } 124 125 // Validate the projection stack (in fact, it's never needed) 126 if (dirty & transform_state_t::PROJECTION) { 127 c->transforms.projection.validate(); 128 } 129 130 // Validate the viewport transformation 131 if (dirty & transform_state_t::VIEWPORT) { 132 vp_transform_t& vpt = c->transforms.vpt; 133 vpt.transform.matrix.load(vpt.matrix); 134 vpt.transform.picker(); 135 } 136 137 // We need to update the mvp (used to transform each vertex) 138 if (dirty & transform_state_t::MVP) { 139 c->transforms.update_mvp(); 140 // invalidate perspective (divide by W) and view volume clipping 141 ogles_invalidate_perspective(c); 142 } 143 144 // Validate the mvui (for normal transformation) 145 if (dirty & transform_state_t::MVUI) { 146 c->transforms.update_mvui(); 147 ogles_invalidate_lighting_mvui(c); 148 } 149 150 // Validate the texture stack 151 if (dirty & transform_state_t::TEXTURE) { 152 for (int i=0; i<GGL_TEXTURE_UNIT_COUNT ; i++) 153 c->transforms.texture[i].validate(); 154 } 155 156 // Validate the mvit4 (user-clip planes) 157 if (dirty & transform_state_t::MVIT) { 158 c->transforms.update_mvit(); 159 } 160 161 c->transforms.dirty &= ~want; 162} 163 164// ---------------------------------------------------------------------------- 165#if 0 166#pragma mark - 167#pragma mark transform_t 168#endif 169 170void transform_t::loadIdentity() { 171 matrix = gIdentityx; 172 flags = 0; 173 ops = OP_IDENTITY; 174 point2 = point2__nop; 175 point3 = point3__nop; 176 point4 = point4__nop; 177} 178 179 180static inline 181int notZero(GLfixed v) { 182 return abs(v) & ~0x3; 183} 184 185static inline 186int notOne(GLfixed v) { 187 return notZero(v - 0x10000); 188} 189 190void transform_t::picker() 191{ 192 const GLfixed* const m = matrix.m; 193 194 // XXX: picker needs to be smarter 195 flags = 0; 196 ops = OP_ALL; 197 point2 = point2__generic; 198 point3 = point3__generic; 199 point4 = point4__generic; 200 201 // find out if this is a 2D projection 202 if (!(notZero(m[3]) | notZero(m[7]) | notZero(m[11]) | notOne(m[15]))) { 203 flags |= FLAGS_2D_PROJECTION; 204 } 205} 206 207void mvui_transform_t::picker() 208{ 209 flags = 0; 210 ops = OP_ALL; 211 point3 = normal__generic; 212} 213 214void transform_t::dump(const char* what) 215{ 216 GLfixed const * const m = matrix.m; 217 LOGD("%s:", what); 218 for (int i=0 ; i<4 ; i++) 219 LOGD("[%08x %08x %08x %08x] [%f %f %f %f]\n", 220 m[I(0,i)], m[I(1,i)], m[I(2,i)], m[I(3,i)], 221 fixedToFloat(m[I(0,i)]), 222 fixedToFloat(m[I(1,i)]), 223 fixedToFloat(m[I(2,i)]), 224 fixedToFloat(m[I(3,i)])); 225} 226 227// ---------------------------------------------------------------------------- 228#if 0 229#pragma mark - 230#pragma mark matrixx_t 231#endif 232 233void matrixx_t::load(const matrixf_t& rhs) { 234 GLfixed* xp = m; 235 GLfloat const* fp = rhs.elements(); 236 unsigned int i = 16; 237 do { 238 const GLfloat f = *fp++; 239 *xp++ = isZerof(f) ? 0 : gglFloatToFixed(f); 240 } while (--i); 241} 242 243// ---------------------------------------------------------------------------- 244#if 0 245#pragma mark - 246#pragma mark matrixf_t 247#endif 248 249void matrixf_t::multiply(matrixf_t& r, const matrixf_t& lhs, const matrixf_t& rhs) 250{ 251 GLfloat const* const m = lhs.m; 252 for (int i=0 ; i<4 ; i++) { 253 register const float rhs_i0 = rhs.m[ I(i,0) ]; 254 register float ri0 = m[ I(0,0) ] * rhs_i0; 255 register float ri1 = m[ I(0,1) ] * rhs_i0; 256 register float ri2 = m[ I(0,2) ] * rhs_i0; 257 register float ri3 = m[ I(0,3) ] * rhs_i0; 258 for (int j=1 ; j<4 ; j++) { 259 register const float rhs_ij = rhs.m[ I(i,j) ]; 260 ri0 += m[ I(j,0) ] * rhs_ij; 261 ri1 += m[ I(j,1) ] * rhs_ij; 262 ri2 += m[ I(j,2) ] * rhs_ij; 263 ri3 += m[ I(j,3) ] * rhs_ij; 264 } 265 r.m[ I(i,0) ] = ri0; 266 r.m[ I(i,1) ] = ri1; 267 r.m[ I(i,2) ] = ri2; 268 r.m[ I(i,3) ] = ri3; 269 } 270} 271 272void matrixf_t::dump(const char* what) { 273 LOGD("%s", what); 274 LOGD("[ %9f %9f %9f %9f ]", m[I(0,0)], m[I(1,0)], m[I(2,0)], m[I(3,0)]); 275 LOGD("[ %9f %9f %9f %9f ]", m[I(0,1)], m[I(1,1)], m[I(2,1)], m[I(3,1)]); 276 LOGD("[ %9f %9f %9f %9f ]", m[I(0,2)], m[I(1,2)], m[I(2,2)], m[I(3,2)]); 277 LOGD("[ %9f %9f %9f %9f ]", m[I(0,3)], m[I(1,3)], m[I(2,3)], m[I(3,3)]); 278} 279 280void matrixf_t::loadIdentity() { 281 memcpy(m, gIdentityf, sizeof(m)); 282} 283 284void matrixf_t::set(const GLfixed* rhs) { 285 load(rhs); 286} 287 288void matrixf_t::set(const GLfloat* rhs) { 289 load(rhs); 290} 291 292void matrixf_t::load(const GLfixed* rhs) { 293 GLfloat* fp = m; 294 unsigned int i = 16; 295 do { 296 *fp++ = fixedToFloat(*rhs++); 297 } while (--i); 298} 299 300void matrixf_t::load(const GLfloat* rhs) { 301 memcpy(m, rhs, sizeof(m)); 302} 303 304void matrixf_t::load(const matrixf_t& rhs) { 305 operator = (rhs); 306} 307 308void matrixf_t::multiply(const matrixf_t& rhs) { 309 matrixf_t r; 310 multiply(r, *this, rhs); 311 operator = (r); 312} 313 314void matrixf_t::translate(GLfloat x, GLfloat y, GLfloat z) { 315 for (int i=0 ; i<4 ; i++) { 316 m[12+i] += m[i]*x + m[4+i]*y + m[8+i]*z; 317 } 318} 319 320void matrixf_t::scale(GLfloat x, GLfloat y, GLfloat z) { 321 for (int i=0 ; i<4 ; i++) { 322 m[ i] *= x; 323 m[4+i] *= y; 324 m[8+i] *= z; 325 } 326} 327 328void matrixf_t::rotate(GLfloat a, GLfloat x, GLfloat y, GLfloat z) 329{ 330 matrixf_t rotation; 331 GLfloat* r = rotation.m; 332 GLfloat c, s; 333 r[3] = 0; r[7] = 0; r[11]= 0; 334 r[12]= 0; r[13]= 0; r[14]= 0; r[15]= 1; 335 a *= GLfloat(M_PI / 180.0f); 336 sincosf(a, &s, &c); 337 if (isOnef(x) && isZerof(y) && isZerof(z)) { 338 r[5] = c; r[10]= c; 339 r[6] = s; r[9] = -s; 340 r[1] = 0; r[2] = 0; 341 r[4] = 0; r[8] = 0; 342 r[0] = 1; 343 } else if (isZerof(x) && isOnef(y) && isZerof(z)) { 344 r[0] = c; r[10]= c; 345 r[8] = s; r[2] = -s; 346 r[1] = 0; r[4] = 0; 347 r[6] = 0; r[9] = 0; 348 r[5] = 1; 349 } else if (isZerof(x) && isZerof(y) && isOnef(z)) { 350 r[0] = c; r[5] = c; 351 r[1] = s; r[4] = -s; 352 r[2] = 0; r[6] = 0; 353 r[8] = 0; r[9] = 0; 354 r[10]= 1; 355 } else { 356 const GLfloat len = sqrtf(x*x + y*y + z*z); 357 if (!isOnef(len)) { 358 const GLfloat recipLen = reciprocalf(len); 359 x *= recipLen; 360 y *= recipLen; 361 z *= recipLen; 362 } 363 const GLfloat nc = 1.0f - c; 364 const GLfloat xy = x * y; 365 const GLfloat yz = y * z; 366 const GLfloat zx = z * x; 367 const GLfloat xs = x * s; 368 const GLfloat ys = y * s; 369 const GLfloat zs = z * s; 370 r[ 0] = x*x*nc + c; r[ 4] = xy*nc - zs; r[ 8] = zx*nc + ys; 371 r[ 1] = xy*nc + zs; r[ 5] = y*y*nc + c; r[ 9] = yz*nc - xs; 372 r[ 2] = zx*nc - ys; r[ 6] = yz*nc + xs; r[10] = z*z*nc + c; 373 } 374 multiply(rotation); 375} 376 377// ---------------------------------------------------------------------------- 378#if 0 379#pragma mark - 380#pragma mark matrix_stack_t 381#endif 382 383void matrix_stack_t::init(int depth) { 384 stack = new matrixf_t[depth]; 385 ops = new uint8_t[depth]; 386 maxDepth = depth; 387 depth = 0; 388 dirty = 0; 389 loadIdentity(); 390} 391 392void matrix_stack_t::uninit() { 393 delete [] stack; 394 delete [] ops; 395} 396 397void matrix_stack_t::loadIdentity() { 398 transform.loadIdentity(); 399 stack[depth].loadIdentity(); 400 ops[depth] = OP_IDENTITY; 401} 402 403void matrix_stack_t::load(const GLfixed* rhs) 404{ 405 memcpy(transform.matrix.m, rhs, sizeof(transform.matrix.m)); 406 stack[depth].load(rhs); 407 ops[depth] = OP_ALL; // TODO: we should look at the matrix 408} 409 410void matrix_stack_t::load(const GLfloat* rhs) 411{ 412 stack[depth].load(rhs); 413 ops[depth] = OP_ALL; // TODO: we should look at the matrix 414} 415 416void matrix_stack_t::multiply(const matrixf_t& rhs) 417{ 418 stack[depth].multiply(rhs); 419 ops[depth] = OP_ALL; // TODO: we should look at the matrix 420} 421 422void matrix_stack_t::translate(GLfloat x, GLfloat y, GLfloat z) 423{ 424 stack[depth].translate(x,y,z); 425 ops[depth] |= OP_TRANSLATE; 426} 427 428void matrix_stack_t::scale(GLfloat x, GLfloat y, GLfloat z) 429{ 430 stack[depth].scale(x,y,z); 431 if (x==y && y==z) { 432 ops[depth] |= OP_UNIFORM_SCALE; 433 } else { 434 ops[depth] |= OP_SCALE; 435 } 436} 437 438void matrix_stack_t::rotate(GLfloat a, GLfloat x, GLfloat y, GLfloat z) 439{ 440 stack[depth].rotate(a,x,y,z); 441 ops[depth] |= OP_ROTATE; 442} 443 444void matrix_stack_t::validate() 445{ 446 if (dirty & DO_FLOAT_TO_FIXED) { 447 transform.matrix.load(top()); 448 } 449 if (dirty & DO_PICKER) { 450 transform.picker(); 451 } 452 dirty = 0; 453} 454 455GLint matrix_stack_t::push() 456{ 457 if (depth >= (maxDepth-1)) { 458 return GL_STACK_OVERFLOW; 459 } 460 stack[depth+1] = stack[depth]; 461 ops[depth+1] = ops[depth]; 462 depth++; 463 return 0; 464} 465 466GLint matrix_stack_t::pop() 467{ 468 if (depth == 0) { 469 return GL_STACK_UNDERFLOW; 470 } 471 depth--; 472 return 0; 473} 474 475// ---------------------------------------------------------------------------- 476#if 0 477#pragma mark - 478#pragma mark vp_transform_t 479#endif 480 481void vp_transform_t::loadIdentity() { 482 transform.loadIdentity(); 483 matrix.loadIdentity(); 484} 485 486// ---------------------------------------------------------------------------- 487#if 0 488#pragma mark - 489#pragma mark transform_state_t 490#endif 491 492void transform_state_t::invalidate() 493{ 494 switch (matrixMode) { 495 case GL_MODELVIEW: dirty |= MODELVIEW | MVP | MVUI | MVIT; break; 496 case GL_PROJECTION: dirty |= PROJECTION | MVP; break; 497 case GL_TEXTURE: dirty |= TEXTURE | MVP; break; 498 } 499 current->dirty = matrix_stack_t::DO_PICKER | 500 matrix_stack_t::DO_FLOAT_TO_FIXED; 501} 502 503void transform_state_t::update_mvp() 504{ 505 matrixf_t temp_mvp; 506 matrixf_t::multiply(temp_mvp, projection.top(), modelview.top()); 507 mvp4.matrix.load(temp_mvp); 508 mvp4.picker(); 509 510 if (mvp4.flags & transform_t::FLAGS_2D_PROJECTION) { 511 // the mvp matrix doesn't transform W, in this case we can 512 // premultiply it with the viewport transformation. In addition to 513 // being more efficient, this is also much more accurate and in fact 514 // is needed for 2D drawing with a resulting 1:1 mapping. 515 matrixf_t mvpv; 516 matrixf_t::multiply(mvpv, vpt.matrix, temp_mvp); 517 mvp.matrix.load(mvpv); 518 mvp.picker(); 519 } else { 520 mvp = mvp4; 521 } 522} 523 524static inline 525GLfloat det22(GLfloat a, GLfloat b, GLfloat c, GLfloat d) { 526 return a*d - b*c; 527} 528 529static inline 530GLfloat ndet22(GLfloat a, GLfloat b, GLfloat c, GLfloat d) { 531 return b*c - a*d; 532} 533 534static __attribute__((noinline)) 535void invert(GLfloat* inverse, const GLfloat* src) 536{ 537 double t; 538 int i, j, k, swap; 539 GLfloat tmp[4][4]; 540 541 memcpy(inverse, gIdentityf, sizeof(gIdentityf)); 542 memcpy(tmp, src, sizeof(GLfloat)*16); 543 544 for (i = 0; i < 4; i++) { 545 // look for largest element in column 546 swap = i; 547 for (j = i + 1; j < 4; j++) { 548 if (fabs(tmp[j][i]) > fabs(tmp[i][i])) { 549 swap = j; 550 } 551 } 552 553 if (swap != i) { 554 /* swap rows. */ 555 for (k = 0; k < 4; k++) { 556 t = tmp[i][k]; 557 tmp[i][k] = tmp[swap][k]; 558 tmp[swap][k] = t; 559 560 t = inverse[i*4+k]; 561 inverse[i*4+k] = inverse[swap*4+k]; 562 inverse[swap*4+k] = t; 563 } 564 } 565 566 t = 1.0f / tmp[i][i]; 567 for (k = 0; k < 4; k++) { 568 tmp[i][k] *= t; 569 inverse[i*4+k] *= t; 570 } 571 for (j = 0; j < 4; j++) { 572 if (j != i) { 573 t = tmp[j][i]; 574 for (k = 0; k < 4; k++) { 575 tmp[j][k] -= tmp[i][k]*t; 576 inverse[j*4+k] -= inverse[i*4+k]*t; 577 } 578 } 579 } 580 } 581} 582 583void transform_state_t::update_mvit() 584{ 585 GLfloat r[16]; 586 const GLfloat* const mv = modelview.top().elements(); 587 invert(r, mv); 588 // convert to fixed-point and transpose 589 GLfixed* const x = mvit4.matrix.m; 590 for (int i=0 ; i<4 ; i++) 591 for (int j=0 ; j<4 ; j++) 592 x[I(i,j)] = gglFloatToFixed(r[I(j,i)]); 593 mvit4.picker(); 594} 595 596void transform_state_t::update_mvui() 597{ 598 const GLfloat* const mv = modelview.top().elements(); 599 600 /* 601 When transforming normals, we can use the upper 3x3 matrix, see: 602 http://www.opengl.org/documentation/specs/version1.1/glspec1.1/node26.html 603 */ 604 605 // Also note that: 606 // l(obj) = tr(M).l(eye) for infinite light 607 // l(obj) = inv(M).l(eye) for local light 608 609 const uint32_t ops = modelview.top_ops() & ~OP_TRANSLATE; 610 if (ggl_likely((!(ops & ~OP_ROTATE)) || 611 (rescaleNormals && modelview.isRigidBody()))) { 612 // if the modelview matrix is a rigid body transformation 613 // (translation, rotation, uniform scaling), then we can bypass 614 // the inverse by transposing the matrix. 615 GLfloat rescale = 1.0f; 616 if (rescaleNormals == GL_RESCALE_NORMAL) { 617 if (!(ops & ~OP_UNIFORM_SCALE)) { 618 rescale = reciprocalf(mv[I(0,0)]); 619 } else { 620 rescale = rsqrtf( 621 sqrf(mv[I(2,0)]) + sqrf(mv[I(2,1)]) + sqrf(mv[I(2,2)])); 622 } 623 } 624 GLfixed* const x = mvui.matrix.m; 625 for (int i=0 ; i<3 ; i++) { 626 x[I(i,0)] = gglFloatToFixed(mv[I(0,i)] * rescale); 627 x[I(i,1)] = gglFloatToFixed(mv[I(1,i)] * rescale); 628 x[I(i,2)] = gglFloatToFixed(mv[I(2,i)] * rescale); 629 } 630 mvui.picker(); 631 return; 632 } 633 634 GLfloat r[3][3]; 635 r[0][0] = det22(mv[I(1,1)], mv[I(2,1)], mv[I(1,2)], mv[I(2,2)]); 636 r[0][1] =ndet22(mv[I(0,1)], mv[I(2,1)], mv[I(0,2)], mv[I(2,2)]); 637 r[0][2] = det22(mv[I(0,1)], mv[I(1,1)], mv[I(0,2)], mv[I(1,2)]); 638 r[1][0] =ndet22(mv[I(1,0)], mv[I(2,0)], mv[I(1,2)], mv[I(2,2)]); 639 r[1][1] = det22(mv[I(0,0)], mv[I(2,0)], mv[I(0,2)], mv[I(2,2)]); 640 r[1][2] =ndet22(mv[I(0,0)], mv[I(1,0)], mv[I(0,2)], mv[I(1,2)]); 641 r[2][0] = det22(mv[I(1,0)], mv[I(2,0)], mv[I(1,1)], mv[I(2,1)]); 642 r[2][1] =ndet22(mv[I(0,0)], mv[I(2,0)], mv[I(0,1)], mv[I(2,1)]); 643 r[2][2] = det22(mv[I(0,0)], mv[I(1,0)], mv[I(0,1)], mv[I(1,1)]); 644 645 GLfloat rdet; 646 if (rescaleNormals == GL_RESCALE_NORMAL) { 647 rdet = rsqrtf(sqrf(r[0][2]) + sqrf(r[1][2]) + sqrf(r[2][2])); 648 } else { 649 rdet = reciprocalf( 650 r[0][0]*mv[I(0,0)] + r[0][1]*mv[I(1,0)] + r[0][2]*mv[I(2,0)]); 651 } 652 653 GLfixed* const x = mvui.matrix.m; 654 for (int i=0 ; i<3 ; i++) { 655 x[I(i,0)] = gglFloatToFixed(r[i][0] * rdet); 656 x[I(i,1)] = gglFloatToFixed(r[i][1] * rdet); 657 x[I(i,2)] = gglFloatToFixed(r[i][2] * rdet); 658 } 659 mvui.picker(); 660} 661 662 663// ---------------------------------------------------------------------------- 664// transformation and matrices API 665// ---------------------------------------------------------------------------- 666#if 0 667#pragma mark - 668#pragma mark transformation and matrices API 669#endif 670 671int ogles_surfaceport(ogles_context_t* c, GLint x, GLint y) 672{ 673 c->viewport.surfaceport.x = x; 674 c->viewport.surfaceport.y = y; 675 676 ogles_viewport(c, 677 c->viewport.x, 678 c->viewport.y, 679 c->viewport.w, 680 c->viewport.h); 681 682 ogles_scissor(c, 683 c->viewport.scissor.x, 684 c->viewport.scissor.y, 685 c->viewport.scissor.w, 686 c->viewport.scissor.h); 687 688 return 0; 689} 690 691void ogles_scissor(ogles_context_t* c, 692 GLint x, GLint y, GLsizei w, GLsizei h) 693{ 694 if ((w|h) < 0) { 695 ogles_error(c, GL_INVALID_VALUE); 696 return; 697 } 698 c->viewport.scissor.x = x; 699 c->viewport.scissor.y = y; 700 c->viewport.scissor.w = w; 701 c->viewport.scissor.h = h; 702 703 x += c->viewport.surfaceport.x; 704 y += c->viewport.surfaceport.y; 705 706 y = c->rasterizer.state.buffers.color.height - (y + h); 707 c->rasterizer.procs.scissor(c, x, y, w, h); 708} 709 710void ogles_viewport(ogles_context_t* c, 711 GLint x, GLint y, GLsizei w, GLsizei h) 712{ 713 if ((w|h)<0) { 714 ogles_error(c, GL_INVALID_VALUE); 715 return; 716 } 717 718 c->viewport.x = x; 719 c->viewport.y = y; 720 c->viewport.w = w; 721 c->viewport.h = h; 722 723 x += c->viewport.surfaceport.x; 724 y += c->viewport.surfaceport.y; 725 726 GLint H = c->rasterizer.state.buffers.color.height; 727 GLfloat sx = div2f(w); 728 GLfloat ox = sx + x; 729 GLfloat sy = div2f(h); 730 GLfloat oy = sy - y + (H - h); 731 732 GLfloat near = c->transforms.vpt.zNear; 733 GLfloat far = c->transforms.vpt.zFar; 734 GLfloat A = div2f(far - near); 735 GLfloat B = div2f(far + near); 736 737 // compute viewport matrix 738 GLfloat* const f = c->transforms.vpt.matrix.editElements(); 739 f[0] = sx; f[4] = 0; f[ 8] = 0; f[12] = ox; 740 f[1] = 0; f[5] =-sy; f[ 9] = 0; f[13] = oy; 741 f[2] = 0; f[6] = 0; f[10] = A; f[14] = B; 742 f[3] = 0; f[7] = 0; f[11] = 0; f[15] = 1; 743 c->transforms.dirty |= transform_state_t::VIEWPORT; 744} 745 746// ---------------------------------------------------------------------------- 747#if 0 748#pragma mark - 749#pragma mark matrix * vertex 750#endif 751 752void point2__generic(transform_t const* mx, vec4_t* lhs, vec4_t const* rhs) { 753 const GLfixed* const m = mx->matrix.m; 754 const GLfixed rx = rhs->x; 755 const GLfixed ry = rhs->y; 756 lhs->x = mla2a(rx, m[ 0], ry, m[ 4], m[12]); 757 lhs->y = mla2a(rx, m[ 1], ry, m[ 5], m[13]); 758 lhs->z = mla2a(rx, m[ 2], ry, m[ 6], m[14]); 759 lhs->w = mla2a(rx, m[ 3], ry, m[ 7], m[15]); 760} 761 762void point3__generic(transform_t const* mx, vec4_t* lhs, vec4_t const* rhs) { 763 const GLfixed* const m = mx->matrix.m; 764 const GLfixed rx = rhs->x; 765 const GLfixed ry = rhs->y; 766 const GLfixed rz = rhs->z; 767 lhs->x = mla3a(rx, m[ 0], ry, m[ 4], rz, m[ 8], m[12]); 768 lhs->y = mla3a(rx, m[ 1], ry, m[ 5], rz, m[ 9], m[13]); 769 lhs->z = mla3a(rx, m[ 2], ry, m[ 6], rz, m[10], m[14]); 770 lhs->w = mla3a(rx, m[ 3], ry, m[ 7], rz, m[11], m[15]); 771} 772 773void point4__generic(transform_t const* mx, vec4_t* lhs, vec4_t const* rhs) { 774 const GLfixed* const m = mx->matrix.m; 775 const GLfixed rx = rhs->x; 776 const GLfixed ry = rhs->y; 777 const GLfixed rz = rhs->z; 778 const GLfixed rw = rhs->w; 779 lhs->x = mla4(rx, m[ 0], ry, m[ 4], rz, m[ 8], rw, m[12]); 780 lhs->y = mla4(rx, m[ 1], ry, m[ 5], rz, m[ 9], rw, m[13]); 781 lhs->z = mla4(rx, m[ 2], ry, m[ 6], rz, m[10], rw, m[14]); 782 lhs->w = mla4(rx, m[ 3], ry, m[ 7], rz, m[11], rw, m[15]); 783} 784 785void normal__generic(transform_t const* mx, vec4_t* lhs, vec4_t const* rhs) { 786 const GLfixed* const m = mx->matrix.m; 787 const GLfixed rx = rhs->x; 788 const GLfixed ry = rhs->y; 789 const GLfixed rz = rhs->z; 790 lhs->x = mla3(rx, m[ 0], ry, m[ 4], rz, m[ 8]); 791 lhs->y = mla3(rx, m[ 1], ry, m[ 5], rz, m[ 9]); 792 lhs->z = mla3(rx, m[ 2], ry, m[ 6], rz, m[10]); 793} 794 795 796void point2__nop(transform_t const*, vec4_t* lhs, vec4_t const* rhs) { 797 lhs->z = 0; 798 lhs->w = 0x10000; 799 if (lhs != rhs) { 800 lhs->x = rhs->x; 801 lhs->y = rhs->y; 802 } 803} 804 805void point3__nop(transform_t const*, vec4_t* lhs, vec4_t const* rhs) { 806 lhs->w = 0x10000; 807 if (lhs != rhs) { 808 lhs->x = rhs->x; 809 lhs->y = rhs->y; 810 lhs->z = rhs->z; 811 } 812} 813 814void point4__nop(transform_t const*, vec4_t* lhs, vec4_t const* rhs) { 815 if (lhs != rhs) 816 *lhs = *rhs; 817} 818 819 820static void frustumf( 821 GLfloat left, GLfloat right, 822 GLfloat bottom, GLfloat top, 823 GLfloat zNear, GLfloat zFar, 824 ogles_context_t* c) 825 { 826 if (cmpf(left,right) || 827 cmpf(top, bottom) || 828 cmpf(zNear, zFar) || 829 isZeroOrNegativef(zNear) || 830 isZeroOrNegativef(zFar)) 831 { 832 ogles_error(c, GL_INVALID_VALUE); 833 return; 834 } 835 const GLfloat r_width = reciprocalf(right - left); 836 const GLfloat r_height = reciprocalf(top - bottom); 837 const GLfloat r_depth = reciprocalf(zNear - zFar); 838 const GLfloat x = mul2f(zNear * r_width); 839 const GLfloat y = mul2f(zNear * r_height); 840 const GLfloat A = mul2f((right + left) * r_width); 841 const GLfloat B = (top + bottom) * r_height; 842 const GLfloat C = (zFar + zNear) * r_depth; 843 const GLfloat D = mul2f(zFar * zNear * r_depth); 844 GLfloat f[16]; 845 f[ 0] = x; 846 f[ 5] = y; 847 f[ 8] = A; 848 f[ 9] = B; 849 f[10] = C; 850 f[14] = D; 851 f[11] = -1.0f; 852 f[ 1] = f[ 2] = f[ 3] = 853 f[ 4] = f[ 6] = f[ 7] = 854 f[12] = f[13] = f[15] = 0.0f; 855 856 matrixf_t rhs; 857 rhs.set(f); 858 c->transforms.current->multiply(rhs); 859 c->transforms.invalidate(); 860} 861 862static void orthof( 863 GLfloat left, GLfloat right, 864 GLfloat bottom, GLfloat top, 865 GLfloat zNear, GLfloat zFar, 866 ogles_context_t* c) 867{ 868 if (cmpf(left,right) || 869 cmpf(top, bottom) || 870 cmpf(zNear, zFar)) 871 { 872 ogles_error(c, GL_INVALID_VALUE); 873 return; 874 } 875 const GLfloat r_width = reciprocalf(right - left); 876 const GLfloat r_height = reciprocalf(top - bottom); 877 const GLfloat r_depth = reciprocalf(zFar - zNear); 878 const GLfloat x = mul2f(r_width); 879 const GLfloat y = mul2f(r_height); 880 const GLfloat z = -mul2f(r_depth); 881 const GLfloat tx = -(right + left) * r_width; 882 const GLfloat ty = -(top + bottom) * r_height; 883 const GLfloat tz = -(zFar + zNear) * r_depth; 884 GLfloat f[16]; 885 f[ 0] = x; 886 f[ 5] = y; 887 f[10] = z; 888 f[12] = tx; 889 f[13] = ty; 890 f[14] = tz; 891 f[15] = 1.0f; 892 f[ 1] = f[ 2] = f[ 3] = 893 f[ 4] = f[ 6] = f[ 7] = 894 f[ 8] = f[ 9] = f[11] = 0.0f; 895 matrixf_t rhs; 896 rhs.set(f); 897 c->transforms.current->multiply(rhs); 898 c->transforms.invalidate(); 899} 900 901static void depthRangef(GLclampf zNear, GLclampf zFar, ogles_context_t* c) 902{ 903 zNear = clampToZerof(zNear > 1 ? 1 : zNear); 904 zFar = clampToZerof(zFar > 1 ? 1 : zFar); 905 GLfloat* const f = c->transforms.vpt.matrix.editElements(); 906 f[10] = div2f(zFar - zNear); 907 f[14] = div2f(zFar + zNear); 908 c->transforms.dirty |= transform_state_t::VIEWPORT; 909 c->transforms.vpt.zNear = zNear; 910 c->transforms.vpt.zFar = zFar; 911} 912 913 914// ---------------------------------------------------------------------------- 915}; // namespace android 916 917using namespace android; 918 919void glMatrixMode(GLenum mode) 920{ 921 ogles_context_t* c = ogles_context_t::get(); 922 matrix_stack_t* stack = 0; 923 switch (mode) { 924 case GL_MODELVIEW: 925 stack = &c->transforms.modelview; 926 break; 927 case GL_PROJECTION: 928 stack = &c->transforms.projection; 929 break; 930 case GL_TEXTURE: 931 stack = &c->transforms.texture[c->textures.active]; 932 break; 933 default: 934 ogles_error(c, GL_INVALID_ENUM); 935 return; 936 } 937 c->transforms.matrixMode = mode; 938 c->transforms.current = stack; 939} 940 941void glLoadIdentity() 942{ 943 ogles_context_t* c = ogles_context_t::get(); 944 c->transforms.current->loadIdentity(); // also loads the GLfixed transform 945 c->transforms.invalidate(); 946 c->transforms.current->dirty = 0; 947} 948 949void glLoadMatrixf(const GLfloat* m) 950{ 951 ogles_context_t* c = ogles_context_t::get(); 952 c->transforms.current->load(m); 953 c->transforms.invalidate(); 954} 955 956void glLoadMatrixx(const GLfixed* m) 957{ 958 ogles_context_t* c = ogles_context_t::get(); 959 c->transforms.current->load(m); // also loads the GLfixed transform 960 c->transforms.invalidate(); 961 c->transforms.current->dirty &= ~matrix_stack_t::DO_FLOAT_TO_FIXED; 962} 963 964void glMultMatrixf(const GLfloat* m) 965{ 966 ogles_context_t* c = ogles_context_t::get(); 967 matrixf_t rhs; 968 rhs.set(m); 969 c->transforms.current->multiply(rhs); 970 c->transforms.invalidate(); 971} 972 973void glMultMatrixx(const GLfixed* m) 974{ 975 ogles_context_t* c = ogles_context_t::get(); 976 matrixf_t rhs; 977 rhs.set(m); 978 c->transforms.current->multiply(rhs); 979 c->transforms.invalidate(); 980} 981 982void glPopMatrix() 983{ 984 ogles_context_t* c = ogles_context_t::get(); 985 GLint err = c->transforms.current->pop(); 986 if (ggl_unlikely(err)) { 987 ogles_error(c, err); 988 return; 989 } 990 c->transforms.invalidate(); 991} 992 993void glPushMatrix() 994{ 995 ogles_context_t* c = ogles_context_t::get(); 996 GLint err = c->transforms.current->push(); 997 if (ggl_unlikely(err)) { 998 ogles_error(c, err); 999 return; 1000 } 1001 c->transforms.invalidate(); 1002} 1003 1004void glFrustumf( 1005 GLfloat left, GLfloat right, 1006 GLfloat bottom, GLfloat top, 1007 GLfloat zNear, GLfloat zFar) 1008{ 1009 ogles_context_t* c = ogles_context_t::get(); 1010 frustumf(left, right, bottom, top, zNear, zFar, c); 1011} 1012 1013void glFrustumx( 1014 GLfixed left, GLfixed right, 1015 GLfixed bottom, GLfixed top, 1016 GLfixed zNear, GLfixed zFar) 1017{ 1018 ogles_context_t* c = ogles_context_t::get(); 1019 frustumf( fixedToFloat(left), fixedToFloat(right), 1020 fixedToFloat(bottom), fixedToFloat(top), 1021 fixedToFloat(zNear), fixedToFloat(zFar), 1022 c); 1023} 1024 1025void glOrthof( 1026 GLfloat left, GLfloat right, 1027 GLfloat bottom, GLfloat top, 1028 GLfloat zNear, GLfloat zFar) 1029{ 1030 ogles_context_t* c = ogles_context_t::get(); 1031 orthof(left, right, bottom, top, zNear, zFar, c); 1032} 1033 1034void glOrthox( 1035 GLfixed left, GLfixed right, 1036 GLfixed bottom, GLfixed top, 1037 GLfixed zNear, GLfixed zFar) 1038{ 1039 ogles_context_t* c = ogles_context_t::get(); 1040 orthof( fixedToFloat(left), fixedToFloat(right), 1041 fixedToFloat(bottom), fixedToFloat(top), 1042 fixedToFloat(zNear), fixedToFloat(zFar), 1043 c); 1044} 1045 1046void glRotatef(GLfloat a, GLfloat x, GLfloat y, GLfloat z) 1047{ 1048 ogles_context_t* c = ogles_context_t::get(); 1049 c->transforms.current->rotate(a, x, y, z); 1050 c->transforms.invalidate(); 1051} 1052 1053void glRotatex(GLfixed a, GLfixed x, GLfixed y, GLfixed z) 1054{ 1055 ogles_context_t* c = ogles_context_t::get(); 1056 c->transforms.current->rotate( 1057 fixedToFloat(a), fixedToFloat(x), 1058 fixedToFloat(y), fixedToFloat(z)); 1059 c->transforms.invalidate(); 1060} 1061 1062void glScalef(GLfloat x, GLfloat y, GLfloat z) 1063{ 1064 ogles_context_t* c = ogles_context_t::get(); 1065 c->transforms.current->scale(x, y, z); 1066 c->transforms.invalidate(); 1067} 1068 1069void glScalex(GLfixed x, GLfixed y, GLfixed z) 1070{ 1071 ogles_context_t* c = ogles_context_t::get(); 1072 c->transforms.current->scale( 1073 fixedToFloat(x), fixedToFloat(y), fixedToFloat(z)); 1074 c->transforms.invalidate(); 1075} 1076 1077void glTranslatef(GLfloat x, GLfloat y, GLfloat z) 1078{ 1079 ogles_context_t* c = ogles_context_t::get(); 1080 c->transforms.current->translate(x, y, z); 1081 c->transforms.invalidate(); 1082} 1083 1084void glTranslatex(GLfixed x, GLfixed y, GLfixed z) 1085{ 1086 ogles_context_t* c = ogles_context_t::get(); 1087 c->transforms.current->translate( 1088 fixedToFloat(x), fixedToFloat(y), fixedToFloat(z)); 1089 c->transforms.invalidate(); 1090} 1091 1092void glScissor(GLint x, GLint y, GLsizei w, GLsizei h) 1093{ 1094 ogles_context_t* c = ogles_context_t::get(); 1095 ogles_scissor(c, x, y, w, h); 1096} 1097 1098void glViewport(GLint x, GLint y, GLsizei w, GLsizei h) 1099{ 1100 ogles_context_t* c = ogles_context_t::get(); 1101 ogles_viewport(c, x, y, w, h); 1102} 1103 1104void glDepthRangef(GLclampf zNear, GLclampf zFar) 1105{ 1106 ogles_context_t* c = ogles_context_t::get(); 1107 depthRangef(zNear, zFar, c); 1108} 1109 1110void glDepthRangex(GLclampx zNear, GLclampx zFar) 1111{ 1112 ogles_context_t* c = ogles_context_t::get(); 1113 depthRangef(fixedToFloat(zNear), fixedToFloat(zFar), c); 1114} 1115 1116void glPolygonOffsetx(GLfixed factor, GLfixed units) 1117{ 1118 ogles_context_t* c = ogles_context_t::get(); 1119 c->polygonOffset.factor = factor; 1120 c->polygonOffset.units = units; 1121} 1122 1123void glPolygonOffset(GLfloat factor, GLfloat units) 1124{ 1125 ogles_context_t* c = ogles_context_t::get(); 1126 c->polygonOffset.factor = gglFloatToFixed(factor); 1127 c->polygonOffset.units = gglFloatToFixed(units); 1128} 1129 1130GLbitfield glQueryMatrixxOES(GLfixed* m, GLint* e) 1131{ 1132 ogles_context_t* c = ogles_context_t::get(); 1133 GLbitfield status = 0; 1134 GLfloat const* f = c->transforms.current->top().elements(); 1135 for (int i=0 ; i<16 ; i++) { 1136 if (isnan(f[i]) || isinf(f[i])) { 1137 status |= 1<<i; 1138 continue; 1139 } 1140 e[i] = exponent(f[i]) - 7; 1141 m[i] = mantissa(f[i]); 1142 } 1143 return status; 1144} 1145