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 *)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 *)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 #if !OBJECT_SPACE_LIGHTING
385                 vec4_t o;
386                 const transform_t& mv = c->transforms.modelview.transform;
387                 mv.point4(&mv, &o, &v->obj);
388                 vss3(d.v, l.objPosition.v, o.w, o.v);
389 #else
390                 vss3(d.v, l.objPosition.v, v->obj.w, v->obj.v);
391 #endif
392                 sqDist = dot3(d.v, d.v);
393                 vscale3(d.v, d.v, gglSqrtRecipx(sqDist));
394             } else {
395                 // TODO: avoid copy here
396                 d = l.normalizedObjPosition;
397             }
398 
399             // ambient & diffuse
400             s = dot3(n.v, d.v);
401             s = (s<0) ? (twoSide?(-s):0) : s;
402             vsa3(t.v, l.implicitDiffuse.v, s, l.implicitAmbient.v);
403 
404             // specular
405             if (ggl_unlikely(s && l.implicitSpecular.v[3])) {
406                 vec4_t h;
407                 h.x = d.x + objViewer.x;
408                 h.y = d.y + objViewer.y;
409                 h.z = d.z + objViewer.z;
410                 vnorm3(h.v, h.v);
411                 s = dot3(n.v, h.v);
412                 s = (s<0) ? (twoSide?(-s):0) : s;
413                 if (s > 0) {
414                     s = gglPowx(s, material.shininess);
415                     vsa3(t.v, l.implicitSpecular.v, s, t.v);
416                 }
417             }
418 
419             // spot
420             if (ggl_unlikely(l.spotCutoff != gglIntToFixed(180))) {
421                 GLfixed spotAtt = -dot3(l.normalizedSpotDir.v, d.v);
422                 if (spotAtt >= l.spotCutoffCosine) {
423                     vscale3(t.v, t.v, gglPowx(spotAtt, l.spotExp));
424                 }
425             }
426 
427             // attenuation
428             if (ggl_unlikely(l.position.w)) {
429                 if (l.rConstAttenuation) {
430                     s = l.rConstAttenuation;
431                 } else {
432                     s = gglMulAddx(sqDist, l.attenuation[2], l.attenuation[0]);
433                     if (l.attenuation[1])
434                         s = gglMulAddx(gglSqrtx(sqDist), l.attenuation[1], s);
435                     s = gglRecipFast(s);
436                 }
437                 vscale3(t.v, t.v, s);
438             }
439 
440             r.r += t.r;
441             r.g += t.g;
442             r.b += t.b;
443         }
444     }
445     v->color.r = gglClampx(r.r);
446     v->color.g = gglClampx(r.g);
447     v->color.b = gglClampx(r.b);
448     v->color.a = gglClampx(r.a);
449     v->flags |= vertex_t::LIT;
450 }
451 
lightModelx(GLenum pname,GLfixed param,ogles_context_t * c)452 static void lightModelx(GLenum pname, GLfixed param, ogles_context_t* c)
453 {
454     if (ggl_unlikely(pname != GL_LIGHT_MODEL_TWO_SIDE)) {
455         ogles_error(c, GL_INVALID_ENUM);
456         return;
457     }
458     c->lighting.lightModel.twoSide = param ? GL_TRUE : GL_FALSE;
459     invalidate_lighting(c);
460 }
461 
lightx(GLenum i,GLenum pname,GLfixed param,ogles_context_t * c)462 static void lightx(GLenum i, GLenum pname, GLfixed param, ogles_context_t* c)
463 {
464     if (ggl_unlikely(uint32_t(i-GL_LIGHT0) >= OGLES_MAX_LIGHTS)) {
465         ogles_error(c, GL_INVALID_ENUM);
466         return;
467     }
468 
469     light_t& light = c->lighting.lights[i-GL_LIGHT0];
470     const GLfixed kDegToRad = GLfixed((M_PI * gglIntToFixed(1)) / 180.0f);
471     switch (pname) {
472     case GL_SPOT_EXPONENT:
473         if (GGLfixed(param) >= gglIntToFixed(128)) {
474             ogles_error(c, GL_INVALID_VALUE);
475             return;
476         }
477         light.spotExp = param;
478         break;
479     case GL_SPOT_CUTOFF:
480         if (param!=gglIntToFixed(180) && GGLfixed(param)>=gglIntToFixed(90)) {
481             ogles_error(c, GL_INVALID_VALUE);
482             return;
483         }
484         light.spotCutoff = param;
485         light.spotCutoffCosine =
486                 gglFloatToFixed(cosinef((M_PI/(180.0f*65536.0f))*param));
487         break;
488     case GL_CONSTANT_ATTENUATION:
489         if (param < 0) {
490             ogles_error(c, GL_INVALID_VALUE);
491             return;
492         }
493         light.attenuation[0] = param;
494         break;
495     case GL_LINEAR_ATTENUATION:
496         if (param < 0) {
497             ogles_error(c, GL_INVALID_VALUE);
498             return;
499         }
500         light.attenuation[1] = param;
501         break;
502     case GL_QUADRATIC_ATTENUATION:
503         if (param < 0) {
504             ogles_error(c, GL_INVALID_VALUE);
505             return;
506         }
507         light.attenuation[2] = param;
508         break;
509     default:
510         ogles_error(c, GL_INVALID_ENUM);
511         return;
512     }
513     invalidate_lighting(c);
514 }
515 
lightxv(GLenum i,GLenum pname,const GLfixed * params,ogles_context_t * c)516 static void lightxv(GLenum i, GLenum pname, const GLfixed *params, ogles_context_t* c)
517 {
518     if (ggl_unlikely(uint32_t(i-GL_LIGHT0) >= OGLES_MAX_LIGHTS)) {
519         ogles_error(c, GL_INVALID_ENUM);
520         return;
521     }
522 
523     GLfixed* what;
524     light_t& light = c->lighting.lights[i-GL_LIGHT0];
525     switch (pname) {
526     case GL_AMBIENT:
527         what = light.ambient.v;
528         break;
529     case GL_DIFFUSE:
530         what = light.diffuse.v;
531         break;
532     case GL_SPECULAR:
533         what = light.specular.v;
534         break;
535     case GL_POSITION: {
536         ogles_validate_transform(c, transform_state_t::MODELVIEW);
537         transform_t& mv = c->transforms.modelview.transform;
538         mv.point4(&mv, &light.position, reinterpret_cast<vec4_t const*>(params));
539         invalidate_lighting(c);
540         return;
541     }
542     case GL_SPOT_DIRECTION: {
543 #if OBJECT_SPACE_LIGHTING
544         ogles_validate_transform(c, transform_state_t::MVUI);
545         transform_t& mvui = c->transforms.mvui;
546         mvui.point3(&mvui, &light.spotDir, reinterpret_cast<vec4_t const*>(params));
547 #else
548         light.spotDir = *reinterpret_cast<vec4_t const*>(params);
549 #endif
550         vnorm3(light.normalizedSpotDir.v, light.spotDir.v);
551         invalidate_lighting(c);
552         return;
553     }
554     default:
555         lightx(i, pname, params[0], c);
556         return;
557     }
558     what[0] = params[0];
559     what[1] = params[1];
560     what[2] = params[2];
561     what[3] = params[3];
562     invalidate_lighting(c);
563 }
564 
materialx(GLenum face,GLenum pname,GLfixed param,ogles_context_t * c)565 static void materialx(GLenum face, GLenum pname, GLfixed param, ogles_context_t* c)
566 {
567     if (ggl_unlikely(face != GL_FRONT_AND_BACK)) {
568         ogles_error(c, GL_INVALID_ENUM);
569         return;
570     }
571     if (ggl_unlikely(pname != GL_SHININESS)) {
572         ogles_error(c, GL_INVALID_ENUM);
573         return;
574     }
575     c->lighting.front.shininess = param;
576     invalidate_lighting(c);
577 }
578 
fogx(GLenum pname,GLfixed param,ogles_context_t * c)579 static void fogx(GLenum pname, GLfixed param, ogles_context_t* c)
580 {
581     switch (pname) {
582     case GL_FOG_DENSITY:
583         if (param >= 0) {
584             c->fog.density = param;
585             break;
586         }
587         ogles_error(c, GL_INVALID_VALUE);
588         break;
589     case GL_FOG_START:
590         c->fog.start = param;
591         c->fog.invEndMinusStart = gglRecip(c->fog.end - c->fog.start);
592         break;
593     case GL_FOG_END:
594         c->fog.end = param;
595         c->fog.invEndMinusStart = gglRecip(c->fog.end - c->fog.start);
596         break;
597     case GL_FOG_MODE:
598         switch (param) {
599         case GL_LINEAR:
600             c->fog.mode = param;
601             c->fog.fog = fog_linear;
602             break;
603         case GL_EXP:
604             c->fog.mode = param;
605             c->fog.fog = fog_exp;
606             break;
607         case GL_EXP2:
608             c->fog.mode = param;
609             c->fog.fog = fog_exp2;
610             break;
611         default:
612             ogles_error(c, GL_INVALID_ENUM);
613             break;
614         }
615         break;
616     default:
617         ogles_error(c, GL_INVALID_ENUM);
618         break;
619     }
620 }
621 
622 // ----------------------------------------------------------------------------
623 }; // namespace android
624 // ----------------------------------------------------------------------------
625 
626 using namespace android;
627 
628 #if 0
629 #pragma mark -
630 #pragma mark lighting APIs
631 #endif
632 
glShadeModel(GLenum mode)633 void glShadeModel(GLenum mode)
634 {
635     ogles_context_t* c = ogles_context_t::get();
636     if (ggl_unlikely(mode != GL_SMOOTH && mode != GL_FLAT)) {
637         ogles_error(c, GL_INVALID_ENUM);
638         return;
639     }
640     c->lighting.shadeModel = mode;
641 }
642 
glLightModelf(GLenum pname,GLfloat param)643 void glLightModelf(GLenum pname, GLfloat param)
644 {
645     ogles_context_t* c = ogles_context_t::get();
646     lightModelx(pname, gglFloatToFixed(param), c);
647 }
648 
glLightModelx(GLenum pname,GLfixed param)649 void glLightModelx(GLenum pname, GLfixed param)
650 {
651     ogles_context_t* c = ogles_context_t::get();
652     lightModelx(pname, param, c);
653 }
654 
glLightModelfv(GLenum pname,const GLfloat * params)655 void glLightModelfv(GLenum pname, const GLfloat *params)
656 {
657     ogles_context_t* c = ogles_context_t::get();
658     if (pname == GL_LIGHT_MODEL_TWO_SIDE) {
659         lightModelx(pname, gglFloatToFixed(params[0]), c);
660         return;
661     }
662 
663     if (ggl_unlikely(pname != GL_LIGHT_MODEL_AMBIENT)) {
664         ogles_error(c, GL_INVALID_ENUM);
665         return;
666     }
667 
668     c->lighting.lightModel.ambient.r = gglFloatToFixed(params[0]);
669     c->lighting.lightModel.ambient.g = gglFloatToFixed(params[1]);
670     c->lighting.lightModel.ambient.b = gglFloatToFixed(params[2]);
671     c->lighting.lightModel.ambient.a = gglFloatToFixed(params[3]);
672     invalidate_lighting(c);
673 }
674 
glLightModelxv(GLenum pname,const GLfixed * params)675 void glLightModelxv(GLenum pname, const GLfixed *params)
676 {
677     ogles_context_t* c = ogles_context_t::get();
678     if (pname == GL_LIGHT_MODEL_TWO_SIDE) {
679         lightModelx(pname, params[0], c);
680         return;
681     }
682 
683     if (ggl_unlikely(pname != GL_LIGHT_MODEL_AMBIENT)) {
684         ogles_error(c, GL_INVALID_ENUM);
685         return;
686     }
687 
688     c->lighting.lightModel.ambient.r = params[0];
689     c->lighting.lightModel.ambient.g = params[1];
690     c->lighting.lightModel.ambient.b = params[2];
691     c->lighting.lightModel.ambient.a = params[3];
692     invalidate_lighting(c);
693 }
694 
695 // ----------------------------------------------------------------------------
696 #if 0
697 #pragma mark -
698 #endif
699 
glLightf(GLenum i,GLenum pname,GLfloat param)700 void glLightf(GLenum i, GLenum pname, GLfloat param)
701 {
702     ogles_context_t* c = ogles_context_t::get();
703     lightx(i, pname, gglFloatToFixed(param), c);
704 }
705 
glLightx(GLenum i,GLenum pname,GLfixed param)706 void glLightx(GLenum i, GLenum pname, GLfixed param)
707 {
708     ogles_context_t* c = ogles_context_t::get();
709     lightx(i, pname, param, c);
710 }
711 
glLightfv(GLenum i,GLenum pname,const GLfloat * params)712 void glLightfv(GLenum i, GLenum pname, const GLfloat *params)
713 {
714     ogles_context_t* c = ogles_context_t::get();
715     switch (pname) {
716     case GL_SPOT_EXPONENT:
717     case GL_SPOT_CUTOFF:
718     case GL_CONSTANT_ATTENUATION:
719     case GL_LINEAR_ATTENUATION:
720     case GL_QUADRATIC_ATTENUATION:
721         lightx(i, pname, gglFloatToFixed(params[0]), c);
722         return;
723     }
724 
725     GLfixed paramsx[4];
726     paramsx[0] = gglFloatToFixed(params[0]);
727     paramsx[1] = gglFloatToFixed(params[1]);
728     paramsx[2] = gglFloatToFixed(params[2]);
729     if (pname != GL_SPOT_DIRECTION)
730         paramsx[3] = gglFloatToFixed(params[3]);
731 
732     lightxv(i, pname, paramsx, c);
733 }
734 
glLightxv(GLenum i,GLenum pname,const GLfixed * params)735 void glLightxv(GLenum i, GLenum pname, const GLfixed *params)
736 {
737     ogles_context_t* c = ogles_context_t::get();
738     lightxv(i, pname, params, c);
739 }
740 
741 // ----------------------------------------------------------------------------
742 #if 0
743 #pragma mark -
744 #endif
745 
glMaterialf(GLenum face,GLenum pname,GLfloat param)746 void glMaterialf(GLenum face, GLenum pname, GLfloat param)
747 {
748     ogles_context_t* c = ogles_context_t::get();
749     materialx(face, pname, gglFloatToFixed(param), c);
750 }
751 
glMaterialx(GLenum face,GLenum pname,GLfixed param)752 void glMaterialx(GLenum face, GLenum pname, GLfixed param)
753 {
754     ogles_context_t* c = ogles_context_t::get();
755     materialx(face, pname, param, c);
756 }
757 
glMaterialfv(GLenum face,GLenum pname,const GLfloat * params)758 void glMaterialfv(
759     GLenum face, GLenum pname, const GLfloat *params)
760 {
761     ogles_context_t* c = ogles_context_t::get();
762     if (ggl_unlikely(face != GL_FRONT_AND_BACK)) {
763         ogles_error(c, GL_INVALID_ENUM);
764         return;
765     }
766     GLfixed* what=0;
767     GLfixed* other=0;
768     switch (pname) {
769     case GL_AMBIENT:    what = c->lighting.front.ambient.v; break;
770     case GL_DIFFUSE:    what = c->lighting.front.diffuse.v; break;
771     case GL_SPECULAR:   what = c->lighting.front.specular.v; break;
772     case GL_EMISSION:   what = c->lighting.front.emission.v; break;
773     case GL_AMBIENT_AND_DIFFUSE:
774         what  = c->lighting.front.ambient.v;
775         other = c->lighting.front.diffuse.v;
776         break;
777     case GL_SHININESS:
778         c->lighting.front.shininess = gglFloatToFixed(params[0]);
779         invalidate_lighting(c);
780         return;
781     default:
782         ogles_error(c, GL_INVALID_ENUM);
783         return;
784     }
785     what[0] = gglFloatToFixed(params[0]);
786     what[1] = gglFloatToFixed(params[1]);
787     what[2] = gglFloatToFixed(params[2]);
788     what[3] = gglFloatToFixed(params[3]);
789     if (other) {
790         other[0] = what[0];
791         other[1] = what[1];
792         other[2] = what[2];
793         other[3] = what[3];
794     }
795     invalidate_lighting(c);
796 }
797 
glMaterialxv(GLenum face,GLenum pname,const GLfixed * params)798 void glMaterialxv(
799     GLenum face, GLenum pname, const GLfixed *params)
800 {
801     ogles_context_t* c = ogles_context_t::get();
802     if (ggl_unlikely(face != GL_FRONT_AND_BACK)) {
803         ogles_error(c, GL_INVALID_ENUM);
804         return;
805     }
806     GLfixed* what=0;
807     GLfixed* other=0;
808     switch (pname) {
809     case GL_AMBIENT:    what = c->lighting.front.ambient.v; break;
810     case GL_DIFFUSE:    what = c->lighting.front.diffuse.v; break;
811     case GL_SPECULAR:   what = c->lighting.front.specular.v; break;
812     case GL_EMISSION:   what = c->lighting.front.emission.v; break;
813     case GL_AMBIENT_AND_DIFFUSE:
814         what  = c->lighting.front.ambient.v;
815         other = c->lighting.front.diffuse.v;
816         break;
817     case GL_SHININESS:
818         c->lighting.front.shininess = gglFloatToFixed(params[0]);
819         invalidate_lighting(c);
820         return;
821     default:
822         ogles_error(c, GL_INVALID_ENUM);
823         return;
824     }
825     what[0] = params[0];
826     what[1] = params[1];
827     what[2] = params[2];
828     what[3] = params[3];
829     if (other) {
830         other[0] = what[0];
831         other[1] = what[1];
832         other[2] = what[2];
833         other[3] = what[3];
834     }
835     invalidate_lighting(c);
836 }
837 
838 // ----------------------------------------------------------------------------
839 #if 0
840 #pragma mark -
841 #pragma mark fog
842 #endif
843 
glFogf(GLenum pname,GLfloat param)844 void glFogf(GLenum pname, GLfloat param) {
845     ogles_context_t* c = ogles_context_t::get();
846     GLfixed paramx = (GLfixed)param;
847     if (pname != GL_FOG_MODE)
848         paramx = gglFloatToFixed(param);
849     fogx(pname, paramx, c);
850 }
851 
glFogx(GLenum pname,GLfixed param)852 void glFogx(GLenum pname, GLfixed param) {
853     ogles_context_t* c = ogles_context_t::get();
854     fogx(pname, param, c);
855 }
856 
glFogfv(GLenum pname,const GLfloat * params)857 void glFogfv(GLenum pname, const GLfloat *params)
858 {
859     ogles_context_t* c = ogles_context_t::get();
860     if (pname != GL_FOG_COLOR) {
861         GLfixed paramx = (GLfixed)params[0];
862         if (pname != GL_FOG_MODE)
863             paramx = gglFloatToFixed(params[0]);
864         fogx(pname, paramx, c);
865         return;
866     }
867     GLfixed paramsx[4];
868     paramsx[0] = gglFloatToFixed(params[0]);
869     paramsx[1] = gglFloatToFixed(params[1]);
870     paramsx[2] = gglFloatToFixed(params[2]);
871     paramsx[3] = gglFloatToFixed(params[3]);
872     c->rasterizer.procs.fogColor3xv(c, paramsx);
873 }
874 
glFogxv(GLenum pname,const GLfixed * params)875 void glFogxv(GLenum pname, const GLfixed *params)
876 {
877     ogles_context_t* c = ogles_context_t::get();
878     if (pname != GL_FOG_COLOR) {
879         fogx(pname, params[0], c);
880         return;
881     }
882     c->rasterizer.procs.fogColor3xv(c, params);
883 }
884