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