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