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