light.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884
  1. /* libs/opengles/light.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 <stdio.h>
  18. #include "context.h"
  19. #include "fp.h"
  20. #include "light.h"
  21. #include "state.h"
  22. #include "matrix.h"
  23. #if defined(__arm__) && defined(__thumb__)
  24. #warning "light.cpp should not be compiled in thumb on ARM."
  25. #endif
  26. namespace android {
  27. // ----------------------------------------------------------------------------
  28. static void invalidate_lighting(ogles_context_t* c);
  29. static void lightVertexValidate(ogles_context_t* c, vertex_t* v);
  30. static void lightVertexNop(ogles_context_t* c, vertex_t* v);
  31. static void lightVertex(ogles_context_t* c, vertex_t* v);
  32. static void lightVertexMaterial(ogles_context_t* c, vertex_t* v);
  33. static inline void vscale3(GLfixed* d, const GLfixed* m, GLfixed s);
  34. static __attribute__((noinline))
  35. void vnorm3(GLfixed* d, const GLfixed* a);
  36. static inline void vsa3(GLfixed* d,
  37. const GLfixed* m, GLfixed s, const GLfixed* a);
  38. static inline void vss3(GLfixed* d,
  39. const GLfixed* m, GLfixed s, const GLfixed* a);
  40. static inline void vmla3(GLfixed* d,
  41. const GLfixed* m0, const GLfixed* m1, const GLfixed* a);
  42. static inline void vmul3(GLfixed* d,
  43. const GLfixed* m0, const GLfixed* m1);
  44. static GLfixed fog_linear(ogles_context_t* c, GLfixed z);
  45. static GLfixed fog_exp(ogles_context_t* c, GLfixed z);
  46. static GLfixed fog_exp2(ogles_context_t* c, GLfixed z);
  47. // ----------------------------------------------------------------------------
  48. static void init_white(vec4_t& c) {
  49. c.r = c.g = c.b = c.a = 0x10000;
  50. }
  51. void ogles_init_light(ogles_context_t* c)
  52. {
  53. for (unsigned int i=0 ; i<OGLES_MAX_LIGHTS ; i++) {
  54. c->lighting.lights[i].ambient.a = 0x10000;
  55. c->lighting.lights[i].position.z = 0x10000;
  56. c->lighting.lights[i].spotDir.z = -0x10000;
  57. c->lighting.lights[i].spotCutoff = gglIntToFixed(180);
  58. c->lighting.lights[i].attenuation[0] = 0x10000;
  59. }
  60. init_white(c->lighting.lights[0].diffuse);
  61. init_white(c->lighting.lights[0].specular);
  62. c->lighting.front.ambient.r =
  63. c->lighting.front.ambient.g =
  64. c->lighting.front.ambient.b = gglFloatToFixed(0.2f);
  65. c->lighting.front.ambient.a = 0x10000;
  66. c->lighting.front.diffuse.r =
  67. c->lighting.front.diffuse.g =
  68. c->lighting.front.diffuse.b = gglFloatToFixed(0.8f);
  69. c->lighting.front.diffuse.a = 0x10000;
  70. c->lighting.front.specular.a = 0x10000;
  71. c->lighting.front.emission.a = 0x10000;
  72. c->lighting.lightModel.ambient.r =
  73. c->lighting.lightModel.ambient.g =
  74. c->lighting.lightModel.ambient.b = gglFloatToFixed(0.2f);
  75. c->lighting.lightModel.ambient.a = 0x10000;
  76. c->lighting.colorMaterial.face = GL_FRONT_AND_BACK;
  77. c->lighting.colorMaterial.mode = GL_AMBIENT_AND_DIFFUSE;
  78. c->fog.mode = GL_EXP;
  79. c->fog.fog = fog_exp;
  80. c->fog.density = 0x10000;
  81. c->fog.end = 0x10000;
  82. c->fog.invEndMinusStart = 0x10000;
  83. invalidate_lighting(c);
  84. c->rasterizer.procs.shadeModel(c, GL_SMOOTH);
  85. c->lighting.shadeModel = GL_SMOOTH;
  86. }
  87. void ogles_uninit_light(ogles_context_t* /*c*/)
  88. {
  89. }
  90. static inline int32_t clampF(GLfixed f) CONST;
  91. int32_t clampF(GLfixed f) {
  92. f = (f & ~(f>>31));
  93. if (f >= 0x10000)
  94. f = 0x10000;
  95. return f;
  96. }
  97. static GLfixed fog_linear(ogles_context_t* c, GLfixed z) {
  98. return clampF(gglMulx((c->fog.end - ((z<0)?-z:z)), c->fog.invEndMinusStart));
  99. }
  100. static GLfixed fog_exp(ogles_context_t* c, GLfixed z) {
  101. const float e = fixedToFloat(gglMulx(c->fog.density, ((z<0)?-z:z)));
  102. return clampF(gglFloatToFixed(fastexpf(-e)));
  103. }
  104. static GLfixed fog_exp2(ogles_context_t* c, GLfixed z) {
  105. const float e = fixedToFloat(gglMulx(c->fog.density, z));
  106. return clampF(gglFloatToFixed(fastexpf(-e*e)));
  107. }
  108. // ----------------------------------------------------------------------------
  109. #if 0
  110. #pragma mark -
  111. #pragma mark math helpers
  112. #endif
  113. static inline
  114. void vscale3(GLfixed* d, const GLfixed* m, GLfixed s) {
  115. d[0] = gglMulx(m[0], s);
  116. d[1] = gglMulx(m[1], s);
  117. d[2] = gglMulx(m[2], s);
  118. }
  119. static inline
  120. void vsa3(GLfixed* d, const GLfixed* m, GLfixed s, const GLfixed* a) {
  121. d[0] = gglMulAddx(m[0], s, a[0]);
  122. d[1] = gglMulAddx(m[1], s, a[1]);
  123. d[2] = gglMulAddx(m[2], s, a[2]);
  124. }
  125. static inline
  126. void vss3(GLfixed* d, const GLfixed* m, GLfixed s, const GLfixed* a) {
  127. d[0] = gglMulSubx(m[0], s, a[0]);
  128. d[1] = gglMulSubx(m[1], s, a[1]);
  129. d[2] = gglMulSubx(m[2], s, a[2]);
  130. }
  131. static inline
  132. void vmla3(GLfixed* d,
  133. const GLfixed* m0, const GLfixed* m1, const GLfixed* a)
  134. {
  135. d[0] = gglMulAddx(m0[0], m1[0], a[0]);
  136. d[1] = gglMulAddx(m0[1], m1[1], a[1]);
  137. d[2] = gglMulAddx(m0[2], m1[2], a[2]);
  138. }
  139. static inline
  140. void vmul3(GLfixed* d, const GLfixed* m0, const GLfixed* m1) {
  141. d[0] = gglMulx(m0[0], m1[0]);
  142. d[1] = gglMulx(m0[1], m1[1]);
  143. d[2] = gglMulx(m0[2], m1[2]);
  144. }
  145. void vnorm3(GLfixed* d, const GLfixed* a)
  146. {
  147. // we must take care of overflows when normalizing a vector
  148. GLfixed n;
  149. int32_t x = a[0]; x = x>=0 ? x : -x;
  150. int32_t y = a[1]; y = y>=0 ? y : -y;
  151. int32_t z = a[2]; z = z>=0 ? z : -z;
  152. if (ggl_likely(x<=0x6800 && y<=0x6800 && z<= 0x6800)) {
  153. // in this case this will all fit on 32 bits
  154. n = x*x + y*y + z*z;
  155. n = gglSqrtRecipx(n);
  156. n <<= 8;
  157. } else {
  158. // here norm^2 is at least 0x7EC00000 (>>32 == 0.495117)
  159. n = vsquare3(x, y, z);
  160. n = gglSqrtRecipx(n);
  161. }
  162. vscale3(d, a, n);
  163. }
  164. // ----------------------------------------------------------------------------
  165. #if 0
  166. #pragma mark -
  167. #pragma mark lighting equations
  168. #endif
  169. static inline void light_picker(ogles_context_t* c)
  170. {
  171. if (ggl_likely(!c->lighting.enable)) {
  172. c->lighting.lightVertex = lightVertexNop;
  173. return;
  174. }
  175. if (c->lighting.colorMaterial.enable) {
  176. c->lighting.lightVertex = lightVertexMaterial;
  177. } else {
  178. c->lighting.lightVertex = lightVertex;
  179. }
  180. }
  181. static inline void validate_light_mvi(ogles_context_t* c)
  182. {
  183. uint32_t en = c->lighting.enabledLights;
  184. // Vector from object to viewer, in eye coordinates
  185. while (en) {
  186. const int i = 31 - gglClz(en);
  187. en &= ~(1<<i);
  188. light_t& l = c->lighting.lights[i];
  189. #if OBJECT_SPACE_LIGHTING
  190. c->transforms.mvui.point4(&c->transforms.mvui,
  191. &l.objPosition, &l.position);
  192. #else
  193. l.objPosition = l.position;
  194. #endif
  195. vnorm3(l.normalizedObjPosition.v, l.objPosition.v);
  196. }
  197. const vec4_t eyeViewer = { 0, 0, 0x10000, 0 };
  198. #if OBJECT_SPACE_LIGHTING
  199. c->transforms.mvui.point3(&c->transforms.mvui,
  200. &c->lighting.objViewer, &eyeViewer);
  201. vnorm3(c->lighting.objViewer.v, c->lighting.objViewer.v);
  202. #else
  203. c->lighting.objViewer = eyeViewer;
  204. #endif
  205. }
  206. static inline void validate_light(ogles_context_t* c)
  207. {
  208. // if colorMaterial is enabled, we get the color from the vertex
  209. if (!c->lighting.colorMaterial.enable) {
  210. material_t& material = c->lighting.front;
  211. uint32_t en = c->lighting.enabledLights;
  212. while (en) {
  213. const int i = 31 - gglClz(en);
  214. en &= ~(1<<i);
  215. light_t& l = c->lighting.lights[i];
  216. vmul3(l.implicitAmbient.v, material.ambient.v, l.ambient.v);
  217. vmul3(l.implicitDiffuse.v, material.diffuse.v, l.diffuse.v);
  218. vmul3(l.implicitSpecular.v, material.specular.v, l.specular.v);
  219. // this is just a flag to tell if we have a specular component
  220. l.implicitSpecular.v[3] =
  221. l.implicitSpecular.r |
  222. l.implicitSpecular.g |
  223. l.implicitSpecular.b;
  224. l.rConstAttenuation = (l.attenuation[1] | l.attenuation[2])==0;
  225. if (l.rConstAttenuation)
  226. l.rConstAttenuation = gglRecipFast(l.attenuation[0]);
  227. }
  228. // emission and ambient for the whole scene
  229. vmla3( c->lighting.implicitSceneEmissionAndAmbient.v,
  230. c->lighting.lightModel.ambient.v,
  231. material.ambient.v,
  232. material.emission.v);
  233. c->lighting.implicitSceneEmissionAndAmbient.a = material.diffuse.a;
  234. }
  235. validate_light_mvi(c);
  236. }
  237. void invalidate_lighting(ogles_context_t* c)
  238. {
  239. // TODO: pick lightVertexValidate or lightVertexValidateMVI
  240. // instead of systematically the heavier lightVertexValidate()
  241. c->lighting.lightVertex = lightVertexValidate;
  242. }
  243. void ogles_invalidate_lighting_mvui(ogles_context_t* c)
  244. {
  245. invalidate_lighting(c);
  246. }
  247. void lightVertexNop(ogles_context_t*, vertex_t* /*v*/)
  248. {
  249. // we should never end-up here
  250. }
  251. void lightVertexValidateMVI(ogles_context_t* c, vertex_t* v)
  252. {
  253. validate_light_mvi(c);
  254. light_picker(c);
  255. c->lighting.lightVertex(c, v);
  256. }
  257. void lightVertexValidate(ogles_context_t* c, vertex_t* v)
  258. {
  259. validate_light(c);
  260. light_picker(c);
  261. c->lighting.lightVertex(c, v);
  262. }
  263. void lightVertexMaterial(ogles_context_t* c, vertex_t* v)
  264. {
  265. // fetch the material color
  266. const GLvoid* cp = c->arrays.color.element(
  267. v->index & vertex_cache_t::INDEX_MASK);
  268. c->arrays.color.fetch(c, v->color.v, cp);
  269. // acquire the color-material from the vertex
  270. material_t& material = c->lighting.front;
  271. material.ambient =
  272. material.diffuse = v->color;
  273. // implicit arguments need to be computed per/vertex
  274. uint32_t en = c->lighting.enabledLights;
  275. while (en) {
  276. const int i = 31 - gglClz(en);
  277. en &= ~(1<<i);
  278. light_t& l = c->lighting.lights[i];
  279. vmul3(l.implicitAmbient.v, material.ambient.v, l.ambient.v);
  280. vmul3(l.implicitDiffuse.v, material.diffuse.v, l.diffuse.v);
  281. vmul3(l.implicitSpecular.v, material.specular.v, l.specular.v);
  282. // this is just a flag to tell if we have a specular component
  283. l.implicitSpecular.v[3] =
  284. l.implicitSpecular.r |
  285. l.implicitSpecular.g |
  286. l.implicitSpecular.b;
  287. }
  288. // emission and ambient for the whole scene
  289. vmla3( c->lighting.implicitSceneEmissionAndAmbient.v,
  290. c->lighting.lightModel.ambient.v,
  291. material.ambient.v,
  292. material.emission.v);
  293. c->lighting.implicitSceneEmissionAndAmbient.a = material.diffuse.a;
  294. // now we can light our vertex as usual
  295. lightVertex(c, v);
  296. }
  297. void lightVertex(ogles_context_t* c, vertex_t* v)
  298. {
  299. // emission and ambient for the whole scene
  300. vec4_t r = c->lighting.implicitSceneEmissionAndAmbient;
  301. const vec4_t objViewer = c->lighting.objViewer;
  302. uint32_t en = c->lighting.enabledLights;
  303. if (ggl_likely(en)) {
  304. // since we do the lighting in object-space, we don't need to
  305. // transform each normal. However, we might still have to normalize
  306. // it if GL_NORMALIZE is enabled.
  307. vec4_t n;
  308. c->arrays.normal.fetch(c, n.v,
  309. c->arrays.normal.element(v->index & vertex_cache_t::INDEX_MASK));
  310. #if !OBJECT_SPACE_LIGHTING
  311. c->transforms.mvui.point3(&c->transforms.mvui, &n, &n);
  312. #endif
  313. // TODO: right now we handle GL_RESCALE_NORMALS as if it were
  314. // GL_NORMALIZE. We could optimize this by scaling mvui
  315. // appropriately instead.
  316. if (c->transforms.rescaleNormals)
  317. vnorm3(n.v, n.v);
  318. const material_t& material = c->lighting.front;
  319. const int twoSide = c->lighting.lightModel.twoSide;
  320. while (en) {
  321. const int i = 31 - gglClz(en);
  322. en &= ~(1<<i);
  323. const light_t& l = c->lighting.lights[i];
  324. vec4_t d, t;
  325. GLfixed s;
  326. GLfixed sqDist = 0x10000;
  327. // compute vertex-to-light vector
  328. if (ggl_unlikely(l.position.w)) {
  329. // lightPos/1.0 - vertex/vertex.w == lightPos*vertex.w - vertex
  330. #if !OBJECT_SPACE_LIGHTING
  331. vec4_t o;
  332. const transform_t& mv = c->transforms.modelview.transform;
  333. mv.point4(&mv, &o, &v->obj);
  334. vss3(d.v, l.objPosition.v, o.w, o.v);
  335. #else
  336. vss3(d.v, l.objPosition.v, v->obj.w, v->obj.v);
  337. #endif
  338. sqDist = dot3(d.v, d.v);
  339. vscale3(d.v, d.v, gglSqrtRecipx(sqDist));
  340. } else {
  341. // TODO: avoid copy here
  342. d = l.normalizedObjPosition;
  343. }
  344. // ambient & diffuse
  345. s = dot3(n.v, d.v);
  346. s = (s<0) ? (twoSide?(-s):0) : s;
  347. vsa3(t.v, l.implicitDiffuse.v, s, l.implicitAmbient.v);
  348. // specular
  349. if (ggl_unlikely(s && l.implicitSpecular.v[3])) {
  350. vec4_t h;
  351. h.x = d.x + objViewer.x;
  352. h.y = d.y + objViewer.y;
  353. h.z = d.z + objViewer.z;
  354. vnorm3(h.v, h.v);
  355. s = dot3(n.v, h.v);
  356. s = (s<0) ? (twoSide?(-s):0) : s;
  357. if (s > 0) {
  358. s = gglPowx(s, material.shininess);
  359. vsa3(t.v, l.implicitSpecular.v, s, t.v);
  360. }
  361. }
  362. // spot
  363. if (ggl_unlikely(l.spotCutoff != gglIntToFixed(180))) {
  364. GLfixed spotAtt = -dot3(l.normalizedSpotDir.v, d.v);
  365. if (spotAtt >= l.spotCutoffCosine) {
  366. vscale3(t.v, t.v, gglPowx(spotAtt, l.spotExp));
  367. }
  368. }
  369. // attenuation
  370. if (ggl_unlikely(l.position.w)) {
  371. if (l.rConstAttenuation) {
  372. s = l.rConstAttenuation;
  373. } else {
  374. s = gglMulAddx(sqDist, l.attenuation[2], l.attenuation[0]);
  375. if (l.attenuation[1])
  376. s = gglMulAddx(gglSqrtx(sqDist), l.attenuation[1], s);
  377. s = gglRecipFast(s);
  378. }
  379. vscale3(t.v, t.v, s);
  380. }
  381. r.r += t.r;
  382. r.g += t.g;
  383. r.b += t.b;
  384. }
  385. }
  386. v->color.r = gglClampx(r.r);
  387. v->color.g = gglClampx(r.g);
  388. v->color.b = gglClampx(r.b);
  389. v->color.a = gglClampx(r.a);
  390. v->flags |= vertex_t::LIT;
  391. }
  392. static void lightModelx(GLenum pname, GLfixed param, ogles_context_t* c)
  393. {
  394. if (ggl_unlikely(pname != GL_LIGHT_MODEL_TWO_SIDE)) {
  395. ogles_error(c, GL_INVALID_ENUM);
  396. return;
  397. }
  398. c->lighting.lightModel.twoSide = param ? GL_TRUE : GL_FALSE;
  399. invalidate_lighting(c);
  400. }
  401. static void lightx(GLenum i, GLenum pname, GLfixed param, ogles_context_t* c)
  402. {
  403. if (ggl_unlikely(uint32_t(i-GL_LIGHT0) >= OGLES_MAX_LIGHTS)) {
  404. ogles_error(c, GL_INVALID_ENUM);
  405. return;
  406. }
  407. light_t& light = c->lighting.lights[i-GL_LIGHT0];
  408. const GLfixed kDegToRad = GLfixed((M_PI * gglIntToFixed(1)) / 180.0f);
  409. switch (pname) {
  410. case GL_SPOT_EXPONENT:
  411. if (GGLfixed(param) >= gglIntToFixed(128)) {
  412. ogles_error(c, GL_INVALID_VALUE);
  413. return;
  414. }
  415. light.spotExp = param;
  416. break;
  417. case GL_SPOT_CUTOFF:
  418. if (param!=gglIntToFixed(180) && GGLfixed(param)>=gglIntToFixed(90)) {
  419. ogles_error(c, GL_INVALID_VALUE);
  420. return;
  421. }
  422. light.spotCutoff = param;
  423. light.spotCutoffCosine =
  424. gglFloatToFixed(cosinef((M_PI/(180.0f*65536.0f))*param));
  425. break;
  426. case GL_CONSTANT_ATTENUATION:
  427. if (param < 0) {
  428. ogles_error(c, GL_INVALID_VALUE);
  429. return;
  430. }
  431. light.attenuation[0] = param;
  432. break;
  433. case GL_LINEAR_ATTENUATION:
  434. if (param < 0) {
  435. ogles_error(c, GL_INVALID_VALUE);
  436. return;
  437. }
  438. light.attenuation[1] = param;
  439. break;
  440. case GL_QUADRATIC_ATTENUATION:
  441. if (param < 0) {
  442. ogles_error(c, GL_INVALID_VALUE);
  443. return;
  444. }
  445. light.attenuation[2] = param;
  446. break;
  447. default:
  448. ogles_error(c, GL_INVALID_ENUM);
  449. return;
  450. }
  451. invalidate_lighting(c);
  452. }
  453. static void lightxv(GLenum i, GLenum pname, const GLfixed *params, ogles_context_t* c)
  454. {
  455. if (ggl_unlikely(uint32_t(i-GL_LIGHT0) >= OGLES_MAX_LIGHTS)) {
  456. ogles_error(c, GL_INVALID_ENUM);
  457. return;
  458. }
  459. GLfixed* what;
  460. light_t& light = c->lighting.lights[i-GL_LIGHT0];
  461. switch (pname) {
  462. case GL_AMBIENT:
  463. what = light.ambient.v;
  464. break;
  465. case GL_DIFFUSE:
  466. what = light.diffuse.v;
  467. break;
  468. case GL_SPECULAR:
  469. what = light.specular.v;
  470. break;
  471. case GL_POSITION: {
  472. ogles_validate_transform(c, transform_state_t::MODELVIEW);
  473. transform_t& mv = c->transforms.modelview.transform;
  474. mv.point4(&mv, &light.position, reinterpret_cast<vec4_t const*>(params));
  475. invalidate_lighting(c);
  476. return;
  477. }
  478. case GL_SPOT_DIRECTION: {
  479. #if OBJECT_SPACE_LIGHTING
  480. ogles_validate_transform(c, transform_state_t::MVUI);
  481. transform_t& mvui = c->transforms.mvui;
  482. mvui.point3(&mvui, &light.spotDir, reinterpret_cast<vec4_t const*>(params));
  483. #else
  484. light.spotDir = *reinterpret_cast<vec4_t const*>(params);
  485. #endif
  486. vnorm3(light.normalizedSpotDir.v, light.spotDir.v);
  487. invalidate_lighting(c);
  488. return;
  489. }
  490. default:
  491. lightx(i, pname, params[0], c);
  492. return;
  493. }
  494. what[0] = params[0];
  495. what[1] = params[1];
  496. what[2] = params[2];
  497. what[3] = params[3];
  498. invalidate_lighting(c);
  499. }
  500. static void materialx(GLenum face, GLenum pname, GLfixed param, ogles_context_t* c)
  501. {
  502. if (ggl_unlikely(face != GL_FRONT_AND_BACK)) {
  503. ogles_error(c, GL_INVALID_ENUM);
  504. return;
  505. }
  506. if (ggl_unlikely(pname != GL_SHININESS)) {
  507. ogles_error(c, GL_INVALID_ENUM);
  508. return;
  509. }
  510. c->lighting.front.shininess = param;
  511. invalidate_lighting(c);
  512. }
  513. static void fogx(GLenum pname, GLfixed param, ogles_context_t* c)
  514. {
  515. switch (pname) {
  516. case GL_FOG_DENSITY:
  517. if (param >= 0) {
  518. c->fog.density = param;
  519. break;
  520. }
  521. ogles_error(c, GL_INVALID_VALUE);
  522. break;
  523. case GL_FOG_START:
  524. c->fog.start = param;
  525. c->fog.invEndMinusStart = gglRecip(c->fog.end - c->fog.start);
  526. break;
  527. case GL_FOG_END:
  528. c->fog.end = param;
  529. c->fog.invEndMinusStart = gglRecip(c->fog.end - c->fog.start);
  530. break;
  531. case GL_FOG_MODE:
  532. switch (param) {
  533. case GL_LINEAR:
  534. c->fog.mode = param;
  535. c->fog.fog = fog_linear;
  536. break;
  537. case GL_EXP:
  538. c->fog.mode = param;
  539. c->fog.fog = fog_exp;
  540. break;
  541. case GL_EXP2:
  542. c->fog.mode = param;
  543. c->fog.fog = fog_exp2;
  544. break;
  545. default:
  546. ogles_error(c, GL_INVALID_ENUM);
  547. break;
  548. }
  549. break;
  550. default:
  551. ogles_error(c, GL_INVALID_ENUM);
  552. break;
  553. }
  554. }
  555. // ----------------------------------------------------------------------------
  556. }; // namespace android
  557. // ----------------------------------------------------------------------------
  558. using namespace android;
  559. #if 0
  560. #pragma mark -
  561. #pragma mark lighting APIs
  562. #endif
  563. void glShadeModel(GLenum mode)
  564. {
  565. ogles_context_t* c = ogles_context_t::get();
  566. if (ggl_unlikely(mode != GL_SMOOTH && mode != GL_FLAT)) {
  567. ogles_error(c, GL_INVALID_ENUM);
  568. return;
  569. }
  570. c->lighting.shadeModel = mode;
  571. }
  572. void glLightModelf(GLenum pname, GLfloat param)
  573. {
  574. ogles_context_t* c = ogles_context_t::get();
  575. lightModelx(pname, gglFloatToFixed(param), c);
  576. }
  577. void glLightModelx(GLenum pname, GLfixed param)
  578. {
  579. ogles_context_t* c = ogles_context_t::get();
  580. lightModelx(pname, param, c);
  581. }
  582. void glLightModelfv(GLenum pname, const GLfloat *params)
  583. {
  584. ogles_context_t* c = ogles_context_t::get();
  585. if (pname == GL_LIGHT_MODEL_TWO_SIDE) {
  586. lightModelx(pname, gglFloatToFixed(params[0]), c);
  587. return;
  588. }
  589. if (ggl_unlikely(pname != GL_LIGHT_MODEL_AMBIENT)) {
  590. ogles_error(c, GL_INVALID_ENUM);
  591. return;
  592. }
  593. c->lighting.lightModel.ambient.r = gglFloatToFixed(params[0]);
  594. c->lighting.lightModel.ambient.g = gglFloatToFixed(params[1]);
  595. c->lighting.lightModel.ambient.b = gglFloatToFixed(params[2]);
  596. c->lighting.lightModel.ambient.a = gglFloatToFixed(params[3]);
  597. invalidate_lighting(c);
  598. }
  599. void glLightModelxv(GLenum pname, const GLfixed *params)
  600. {
  601. ogles_context_t* c = ogles_context_t::get();
  602. if (pname == GL_LIGHT_MODEL_TWO_SIDE) {
  603. lightModelx(pname, params[0], c);
  604. return;
  605. }
  606. if (ggl_unlikely(pname != GL_LIGHT_MODEL_AMBIENT)) {
  607. ogles_error(c, GL_INVALID_ENUM);
  608. return;
  609. }
  610. c->lighting.lightModel.ambient.r = params[0];
  611. c->lighting.lightModel.ambient.g = params[1];
  612. c->lighting.lightModel.ambient.b = params[2];
  613. c->lighting.lightModel.ambient.a = params[3];
  614. invalidate_lighting(c);
  615. }
  616. // ----------------------------------------------------------------------------
  617. #if 0
  618. #pragma mark -
  619. #endif
  620. void glLightf(GLenum i, GLenum pname, GLfloat param)
  621. {
  622. ogles_context_t* c = ogles_context_t::get();
  623. lightx(i, pname, gglFloatToFixed(param), c);
  624. }
  625. void glLightx(GLenum i, GLenum pname, GLfixed param)
  626. {
  627. ogles_context_t* c = ogles_context_t::get();
  628. lightx(i, pname, param, c);
  629. }
  630. void glLightfv(GLenum i, GLenum pname, const GLfloat *params)
  631. {
  632. ogles_context_t* c = ogles_context_t::get();
  633. switch (pname) {
  634. case GL_SPOT_EXPONENT:
  635. case GL_SPOT_CUTOFF:
  636. case GL_CONSTANT_ATTENUATION:
  637. case GL_LINEAR_ATTENUATION:
  638. case GL_QUADRATIC_ATTENUATION:
  639. lightx(i, pname, gglFloatToFixed(params[0]), c);
  640. return;
  641. }
  642. GLfixed paramsx[4];
  643. paramsx[0] = gglFloatToFixed(params[0]);
  644. paramsx[1] = gglFloatToFixed(params[1]);
  645. paramsx[2] = gglFloatToFixed(params[2]);
  646. if (pname != GL_SPOT_DIRECTION)
  647. paramsx[3] = gglFloatToFixed(params[3]);
  648. lightxv(i, pname, paramsx, c);
  649. }
  650. void glLightxv(GLenum i, GLenum pname, const GLfixed *params)
  651. {
  652. ogles_context_t* c = ogles_context_t::get();
  653. lightxv(i, pname, params, c);
  654. }
  655. // ----------------------------------------------------------------------------
  656. #if 0
  657. #pragma mark -
  658. #endif
  659. void glMaterialf(GLenum face, GLenum pname, GLfloat param)
  660. {
  661. ogles_context_t* c = ogles_context_t::get();
  662. materialx(face, pname, gglFloatToFixed(param), c);
  663. }
  664. void glMaterialx(GLenum face, GLenum pname, GLfixed param)
  665. {
  666. ogles_context_t* c = ogles_context_t::get();
  667. materialx(face, pname, param, c);
  668. }
  669. void glMaterialfv(
  670. GLenum face, GLenum pname, const GLfloat *params)
  671. {
  672. ogles_context_t* c = ogles_context_t::get();
  673. if (ggl_unlikely(face != GL_FRONT_AND_BACK)) {
  674. ogles_error(c, GL_INVALID_ENUM);
  675. return;
  676. }
  677. GLfixed* what=0;
  678. GLfixed* other=0;
  679. switch (pname) {
  680. case GL_AMBIENT: what = c->lighting.front.ambient.v; break;
  681. case GL_DIFFUSE: what = c->lighting.front.diffuse.v; break;
  682. case GL_SPECULAR: what = c->lighting.front.specular.v; break;
  683. case GL_EMISSION: what = c->lighting.front.emission.v; break;
  684. case GL_AMBIENT_AND_DIFFUSE:
  685. what = c->lighting.front.ambient.v;
  686. other = c->lighting.front.diffuse.v;
  687. break;
  688. case GL_SHININESS:
  689. c->lighting.front.shininess = gglFloatToFixed(params[0]);
  690. invalidate_lighting(c);
  691. return;
  692. default:
  693. ogles_error(c, GL_INVALID_ENUM);
  694. return;
  695. }
  696. what[0] = gglFloatToFixed(params[0]);
  697. what[1] = gglFloatToFixed(params[1]);
  698. what[2] = gglFloatToFixed(params[2]);
  699. what[3] = gglFloatToFixed(params[3]);
  700. if (other) {
  701. other[0] = what[0];
  702. other[1] = what[1];
  703. other[2] = what[2];
  704. other[3] = what[3];
  705. }
  706. invalidate_lighting(c);
  707. }
  708. void glMaterialxv(
  709. GLenum face, GLenum pname, const GLfixed *params)
  710. {
  711. ogles_context_t* c = ogles_context_t::get();
  712. if (ggl_unlikely(face != GL_FRONT_AND_BACK)) {
  713. ogles_error(c, GL_INVALID_ENUM);
  714. return;
  715. }
  716. GLfixed* what=0;
  717. GLfixed* other=0;
  718. switch (pname) {
  719. case GL_AMBIENT: what = c->lighting.front.ambient.v; break;
  720. case GL_DIFFUSE: what = c->lighting.front.diffuse.v; break;
  721. case GL_SPECULAR: what = c->lighting.front.specular.v; break;
  722. case GL_EMISSION: what = c->lighting.front.emission.v; break;
  723. case GL_AMBIENT_AND_DIFFUSE:
  724. what = c->lighting.front.ambient.v;
  725. other = c->lighting.front.diffuse.v;
  726. break;
  727. case GL_SHININESS:
  728. c->lighting.front.shininess = gglFloatToFixed(params[0]);
  729. invalidate_lighting(c);
  730. return;
  731. default:
  732. ogles_error(c, GL_INVALID_ENUM);
  733. return;
  734. }
  735. what[0] = params[0];
  736. what[1] = params[1];
  737. what[2] = params[2];
  738. what[3] = params[3];
  739. if (other) {
  740. other[0] = what[0];
  741. other[1] = what[1];
  742. other[2] = what[2];
  743. other[3] = what[3];
  744. }
  745. invalidate_lighting(c);
  746. }
  747. // ----------------------------------------------------------------------------
  748. #if 0
  749. #pragma mark -
  750. #pragma mark fog
  751. #endif
  752. void glFogf(GLenum pname, GLfloat param) {
  753. ogles_context_t* c = ogles_context_t::get();
  754. GLfixed paramx = (GLfixed)param;
  755. if (pname != GL_FOG_MODE)
  756. paramx = gglFloatToFixed(param);
  757. fogx(pname, paramx, c);
  758. }
  759. void glFogx(GLenum pname, GLfixed param) {
  760. ogles_context_t* c = ogles_context_t::get();
  761. fogx(pname, param, c);
  762. }
  763. void glFogfv(GLenum pname, const GLfloat *params)
  764. {
  765. ogles_context_t* c = ogles_context_t::get();
  766. if (pname != GL_FOG_COLOR) {
  767. GLfixed paramx = (GLfixed)params[0];
  768. if (pname != GL_FOG_MODE)
  769. paramx = gglFloatToFixed(params[0]);
  770. fogx(pname, paramx, c);
  771. return;
  772. }
  773. GLfixed paramsx[4];
  774. paramsx[0] = gglFloatToFixed(params[0]);
  775. paramsx[1] = gglFloatToFixed(params[1]);
  776. paramsx[2] = gglFloatToFixed(params[2]);
  777. paramsx[3] = gglFloatToFixed(params[3]);
  778. c->rasterizer.procs.fogColor3xv(c, paramsx);
  779. }
  780. void glFogxv(GLenum pname, const GLfixed *params)
  781. {
  782. ogles_context_t* c = ogles_context_t::get();
  783. if (pname != GL_FOG_COLOR) {
  784. fogx(pname, params[0], c);
  785. return;
  786. }
  787. c->rasterizer.procs.fogColor3xv(c, params);
  788. }