matrix.cpp 31 KB

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