• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     const vec4_t eyeViewer = { 0, 0, 0x1000, 0 };
221     while (en) {
222         const int i = 31 - gglClz(en);
223         en &= ~(1<<i);
224         light_t& l = c->lighting.lights[i];
225         c->transforms.mvui.point4(&c->transforms.mvui,
226                 &l.objPosition, &l.position);
227         vnorm3(l.normalizedObjPosition.v, l.objPosition.v);
228         c->transforms.mvui.point4(&c->transforms.mvui,
229                 &l.objViewer, &eyeViewer);
230         vnorm3(l.objViewer.v, l.objViewer.v);
231     }
232 }
233 
validate_light(ogles_context_t * c)234 static inline void validate_light(ogles_context_t* c)
235 {
236     // if colorMaterial is enabled, we get the color from the vertex
237     if (!c->lighting.colorMaterial.enable) {
238         material_t& material = c->lighting.front;
239         uint32_t en = c->lighting.enabledLights;
240         while (en) {
241             const int i = 31 - gglClz(en);
242             en &= ~(1<<i);
243             light_t& l = c->lighting.lights[i];
244             vmul3(l.implicitAmbient.v,  material.ambient.v,  l.ambient.v);
245             vmul3(l.implicitDiffuse.v,  material.diffuse.v,  l.diffuse.v);
246             vmul3(l.implicitSpecular.v, material.specular.v, l.specular.v);
247 
248             // this is just a flag to tell if we have a specular component
249             l.implicitSpecular.v[3] =
250                     l.implicitSpecular.r |
251                     l.implicitSpecular.g |
252                     l.implicitSpecular.b;
253 
254             l.rConstAttenuation = (l.attenuation[1] | l.attenuation[2])==0;
255             if (l.rConstAttenuation)
256                 l.rConstAttenuation = gglRecipFast(l.attenuation[0]);
257         }
258         // emission and ambient for the whole scene
259         vmla3(  c->lighting.implicitSceneEmissionAndAmbient.v,
260                 c->lighting.lightModel.ambient.v,
261                 material.ambient.v,
262                 material.emission.v);
263         c->lighting.implicitSceneEmissionAndAmbient.a = material.diffuse.a;
264     }
265     validate_light_mvi(c);
266 }
267 
invalidate_lighting(ogles_context_t * c)268 void invalidate_lighting(ogles_context_t* c)
269 {
270     // TODO: pick lightVertexValidate or lightVertexValidateMVI
271     // instead of systematically the heavier lightVertexValidate()
272     c->lighting.lightVertex = lightVertexValidate;
273 }
274 
ogles_invalidate_lighting_mvui(ogles_context_t * c)275 void ogles_invalidate_lighting_mvui(ogles_context_t* c)
276 {
277     invalidate_lighting(c);
278 }
279 
lightVertexNop(ogles_context_t *,vertex_t * v)280 void lightVertexNop(ogles_context_t*, vertex_t* v)
281 {
282     // we should never end-up here
283 }
284 
lightVertexValidateMVI(ogles_context_t * c,vertex_t * v)285 void lightVertexValidateMVI(ogles_context_t* c, vertex_t* v)
286 {
287     validate_light_mvi(c);
288     light_picker(c);
289     c->lighting.lightVertex(c, v);
290 }
291 
lightVertexValidate(ogles_context_t * c,vertex_t * v)292 void lightVertexValidate(ogles_context_t* c, vertex_t* v)
293 {
294     validate_light(c);
295     light_picker(c);
296     c->lighting.lightVertex(c, v);
297 }
298 
lightVertexMaterial(ogles_context_t * c,vertex_t * v)299 void lightVertexMaterial(ogles_context_t* c, vertex_t* v)
300 {
301     // fetch the material color
302     const GLvoid* cp = c->arrays.color.element(
303             v->index & vertex_cache_t::INDEX_MASK);
304     c->arrays.color.fetch(c, v->color.v, cp);
305 
306     // acquire the color-material from the vertex
307     material_t& material = c->lighting.front;
308     material.ambient =
309     material.diffuse = v->color;
310     // implicit arguments need to be computed per/vertex
311     uint32_t en = c->lighting.enabledLights;
312     while (en) {
313         const int i = 31 - gglClz(en);
314         en &= ~(1<<i);
315         light_t& l = c->lighting.lights[i];
316         vmul3(l.implicitAmbient.v,  material.ambient.v,  l.ambient.v);
317         vmul3(l.implicitDiffuse.v,  material.diffuse.v,  l.diffuse.v);
318         vmul3(l.implicitSpecular.v, material.specular.v, l.specular.v);
319         // this is just a flag to tell if we have a specular component
320         l.implicitSpecular.v[3] =
321                 l.implicitSpecular.r |
322                 l.implicitSpecular.g |
323                 l.implicitSpecular.b;
324     }
325     // emission and ambient for the whole scene
326     vmla3(  c->lighting.implicitSceneEmissionAndAmbient.v,
327             c->lighting.lightModel.ambient.v,
328             material.ambient.v,
329             material.emission.v);
330     c->lighting.implicitSceneEmissionAndAmbient.a = material.diffuse.a;
331 
332     // now we can light our vertex as usual
333     lightVertex(c, v);
334 }
335 
lightVertex(ogles_context_t * c,vertex_t * v)336 void lightVertex(ogles_context_t* c, vertex_t* v)
337 {
338     // emission and ambient for the whole scene
339     vec4_t r = c->lighting.implicitSceneEmissionAndAmbient;
340 
341     uint32_t en = c->lighting.enabledLights;
342     if (ggl_likely(en)) {
343         // since we do the lighting in object-space, we don't need to
344         // transform each normal. However, we might still have to normalize
345         // it if GL_NORMALIZE is enabled.
346         vec4_t n;
347         c->arrays.normal.fetch(c, n.v,
348             c->arrays.normal.element(v->index & vertex_cache_t::INDEX_MASK));
349 
350         // TODO: right now we handle GL_RESCALE_NORMALS as if ti were
351         // GL_NORMALIZE. We could optimize this by  scaling mvui
352         // appropriately instead.
353         if (c->transforms.rescaleNormals)
354             vnorm3(n.v, n.v);
355 
356         const material_t& material = c->lighting.front;
357         const int twoSide = c->lighting.lightModel.twoSide;
358 
359         while (en) {
360             const int i = 31 - gglClz(en);
361             en &= ~(1<<i);
362             const light_t& l = c->lighting.lights[i];
363 
364             vec4_t d, t;
365             GLfixed s;
366             GLfixed sqDist = 0x10000;
367 
368             // compute vertex-to-light vector
369             if (ggl_unlikely(l.position.w)) {
370                 // lightPos/1.0 - vertex/vertex.w == lightPos*vertex.w - vertex
371                 vss3(d.v, l.objPosition.v, v->obj.w, v->obj.v);
372                 sqDist = dot3(d.v, d.v);
373                 vscale3(d.v, d.v, gglSqrtRecipx(sqDist));
374             } else {
375                 // TODO: avoid copy here
376                 d = l.normalizedObjPosition;
377             }
378 
379             // ambient & diffuse
380             s = dot3(n.v, d.v);
381             s = (s<0) ? (twoSide?(-s):0) : s;
382             vsa3(t.v, l.implicitDiffuse.v, s, l.implicitAmbient.v);
383 
384             // specular
385             if (ggl_unlikely(s && l.implicitSpecular.v[3])) {
386                 vec4_t h;
387                 h.x = d.x + l.objViewer.x;
388                 h.y = d.y + l.objViewer.y;
389                 h.z = d.z + l.objViewer.z;
390                 vnorm3(h.v, h.v);
391                 s = dot3(n.v, h.v);
392                 s = (s<0) ? (twoSide?(-s):0) : s;
393                 if (s > 0) {
394                     s = gglPowx(s, material.shininess);
395                     vsa3(t.v, l.implicitSpecular.v, s, t.v);
396                 }
397             }
398 
399             // spot
400             if (ggl_unlikely(l.spotCutoff != gglIntToFixed(180))) {
401                 GLfixed spotAtt = -dot3(l.normalizedSpotDir.v, d.v);
402                 if (spotAtt >= l.spotCutoffCosine) {
403                     vscale3(t.v, t.v, gglPowx(spotAtt, l.spotExp));
404                 }
405             }
406 
407             // attenuation
408             if (ggl_unlikely(l.position.w)) {
409                 if (l.rConstAttenuation) {
410                     s = l.rConstAttenuation;
411                 } else {
412                     s = gglMulAddx(sqDist, l.attenuation[2], l.attenuation[0]);
413                     if (l.attenuation[1])
414                         s = gglMulAddx(gglSqrtx(sqDist), l.attenuation[1], s);
415                     s = gglRecipFast(s);
416                 }
417                 vscale3(t.v, t.v, s);
418             }
419 
420             r.r += t.r;
421             r.g += t.g;
422             r.b += t.b;
423         }
424     }
425     v->color.r = gglClampx(r.r);
426     v->color.g = gglClampx(r.g);
427     v->color.b = gglClampx(r.b);
428     v->color.a = gglClampx(r.a);
429     v->flags |= vertex_t::LIT;
430 }
431 
lightModelx(GLenum pname,GLfixed param,ogles_context_t * c)432 static void lightModelx(GLenum pname, GLfixed param, ogles_context_t* c)
433 {
434     if (ggl_unlikely(pname != GL_LIGHT_MODEL_TWO_SIDE)) {
435         ogles_error(c, GL_INVALID_ENUM);
436         return;
437     }
438     c->lighting.lightModel.twoSide = param ? GL_TRUE : GL_FALSE;
439     invalidate_lighting(c);
440 }
441 
lightx(GLenum i,GLenum pname,GLfixed param,ogles_context_t * c)442 static void lightx(GLenum i, GLenum pname, GLfixed param, ogles_context_t* c)
443 {
444     if (ggl_unlikely(uint32_t(i-GL_LIGHT0) >= OGLES_MAX_LIGHTS)) {
445         ogles_error(c, GL_INVALID_ENUM);
446         return;
447     }
448 
449     light_t& light = c->lighting.lights[i-GL_LIGHT0];
450     const GLfixed kDegToRad = GLfixed((M_PI * gglIntToFixed(1)) / 180.0f);
451     switch (pname) {
452     case GL_SPOT_EXPONENT:
453         if (GGLfixed(param) >= gglIntToFixed(128)) {
454             ogles_error(c, GL_INVALID_VALUE);
455             return;
456         }
457         light.spotExp = param;
458         break;
459     case GL_SPOT_CUTOFF:
460         if (param!=gglIntToFixed(180) && GGLfixed(param)>=gglIntToFixed(90)) {
461             ogles_error(c, GL_INVALID_VALUE);
462             return;
463         }
464         light.spotCutoff = param;
465         light.spotCutoffCosine =
466                 gglFloatToFixed(cosinef((M_PI/(180.0f*65536.0f))*param));
467         break;
468     case GL_CONSTANT_ATTENUATION:
469         if (param < 0) {
470             ogles_error(c, GL_INVALID_VALUE);
471             return;
472         }
473         light.attenuation[0] = param;
474         break;
475     case GL_LINEAR_ATTENUATION:
476         if (param < 0) {
477             ogles_error(c, GL_INVALID_VALUE);
478             return;
479         }
480         light.attenuation[1] = param;
481         break;
482     case GL_QUADRATIC_ATTENUATION:
483         if (param < 0) {
484             ogles_error(c, GL_INVALID_VALUE);
485             return;
486         }
487         light.attenuation[2] = param;
488         break;
489     default:
490         ogles_error(c, GL_INVALID_ENUM);
491         return;
492     }
493     invalidate_lighting(c);
494 }
495 
lightxv(GLenum i,GLenum pname,const GLfixed * params,ogles_context_t * c)496 static void lightxv(GLenum i, GLenum pname, const GLfixed *params, ogles_context_t* c)
497 {
498     if (ggl_unlikely(uint32_t(i-GL_LIGHT0) >= OGLES_MAX_LIGHTS)) {
499         ogles_error(c, GL_INVALID_ENUM);
500         return;
501     }
502 
503     GLfixed* what;
504     light_t& light = c->lighting.lights[i-GL_LIGHT0];
505     switch (pname) {
506     case GL_AMBIENT:
507         what = light.ambient.v;
508         break;
509     case GL_DIFFUSE:
510         what = light.diffuse.v;
511         break;
512     case GL_SPECULAR:
513         what = light.specular.v;
514         break;
515     case GL_POSITION: {
516         ogles_validate_transform(c, transform_state_t::MODELVIEW);
517         transform_t& mv = c->transforms.modelview.transform;
518         memcpy(light.position.v, params, sizeof(light.position.v));
519         mv.point4(&mv, &light.position, &light.position);
520         invalidate_lighting(c);
521         return;
522     }
523     case GL_SPOT_DIRECTION: {
524         ogles_validate_transform(c, transform_state_t::MVUI);
525         transform_t& mvui = c->transforms.mvui;
526         mvui.point3(&mvui, &light.spotDir, (vec4_t*)params);
527         vnorm3(light.normalizedSpotDir.v, light.spotDir.v);
528         invalidate_lighting(c);
529         return;
530     }
531     default:
532         lightx(i, pname, params[0], c);
533         return;
534     }
535     what[0] = params[0];
536     what[1] = params[1];
537     what[2] = params[2];
538     what[3] = params[3];
539     invalidate_lighting(c);
540 }
541 
materialx(GLenum face,GLenum pname,GLfixed param,ogles_context_t * c)542 static void materialx(GLenum face, GLenum pname, GLfixed param, ogles_context_t* c)
543 {
544     if (ggl_unlikely(face != GL_FRONT_AND_BACK)) {
545         ogles_error(c, GL_INVALID_ENUM);
546         return;
547     }
548     if (ggl_unlikely(pname != GL_SHININESS)) {
549         ogles_error(c, GL_INVALID_ENUM);
550         return;
551     }
552     c->lighting.front.shininess = param;
553     invalidate_lighting(c);
554 }
555 
fogx(GLenum pname,GLfixed param,ogles_context_t * c)556 static void fogx(GLenum pname, GLfixed param, ogles_context_t* c)
557 {
558     switch (pname) {
559     case GL_FOG_DENSITY:
560         if (param >= 0) {
561             c->fog.density = param;
562             break;
563         }
564         ogles_error(c, GL_INVALID_VALUE);
565         break;
566     case GL_FOG_START:
567         c->fog.start = param;
568         c->fog.invEndMinusStart = gglRecip(c->fog.end - c->fog.start);
569         break;
570     case GL_FOG_END:
571         c->fog.end = param;
572         c->fog.invEndMinusStart = gglRecip(c->fog.end - c->fog.start);
573         break;
574     case GL_FOG_MODE:
575         switch (param) {
576         case GL_LINEAR:
577             c->fog.mode = param;
578             c->fog.fog = fog_linear;
579             break;
580         case GL_EXP:
581             c->fog.mode = param;
582             c->fog.fog = fog_exp;
583             break;
584         case GL_EXP2:
585             c->fog.mode = param;
586             c->fog.fog = fog_exp2;
587             break;
588         default:
589             ogles_error(c, GL_INVALID_ENUM);
590             break;
591         }
592         break;
593     default:
594         ogles_error(c, GL_INVALID_ENUM);
595         break;
596     }
597 }
598 
599 // ----------------------------------------------------------------------------
600 }; // namespace android
601 // ----------------------------------------------------------------------------
602 
603 using namespace android;
604 
605 #if 0
606 #pragma mark -
607 #pragma mark lighting APIs
608 #endif
609 
glShadeModel(GLenum mode)610 void glShadeModel(GLenum mode)
611 {
612     ogles_context_t* c = ogles_context_t::get();
613     if (ggl_unlikely(mode != GL_SMOOTH && mode != GL_FLAT)) {
614         ogles_error(c, GL_INVALID_ENUM);
615         return;
616     }
617     c->lighting.shadeModel = mode;
618 }
619 
glLightModelf(GLenum pname,GLfloat param)620 void glLightModelf(GLenum pname, GLfloat param)
621 {
622     ogles_context_t* c = ogles_context_t::get();
623     lightModelx(pname, gglFloatToFixed(param), c);
624 }
625 
glLightModelx(GLenum pname,GLfixed param)626 void glLightModelx(GLenum pname, GLfixed param)
627 {
628     ogles_context_t* c = ogles_context_t::get();
629     lightModelx(pname, param, c);
630 }
631 
glLightModelfv(GLenum pname,const GLfloat * params)632 void glLightModelfv(GLenum pname, const GLfloat *params)
633 {
634     ogles_context_t* c = ogles_context_t::get();
635     if (pname == GL_LIGHT_MODEL_TWO_SIDE) {
636         lightModelx(pname, gglFloatToFixed(params[0]), c);
637         return;
638     }
639 
640     if (ggl_unlikely(pname != GL_LIGHT_MODEL_AMBIENT)) {
641         ogles_error(c, GL_INVALID_ENUM);
642         return;
643     }
644 
645     c->lighting.lightModel.ambient.r = gglFloatToFixed(params[0]);
646     c->lighting.lightModel.ambient.g = gglFloatToFixed(params[1]);
647     c->lighting.lightModel.ambient.b = gglFloatToFixed(params[2]);
648     c->lighting.lightModel.ambient.a = gglFloatToFixed(params[3]);
649     invalidate_lighting(c);
650 }
651 
glLightModelxv(GLenum pname,const GLfixed * params)652 void glLightModelxv(GLenum pname, const GLfixed *params)
653 {
654     ogles_context_t* c = ogles_context_t::get();
655     if (pname == GL_LIGHT_MODEL_TWO_SIDE) {
656         lightModelx(pname, params[0], c);
657         return;
658     }
659 
660     if (ggl_unlikely(pname != GL_LIGHT_MODEL_AMBIENT)) {
661         ogles_error(c, GL_INVALID_ENUM);
662         return;
663     }
664 
665     c->lighting.lightModel.ambient.r = params[0];
666     c->lighting.lightModel.ambient.g = params[1];
667     c->lighting.lightModel.ambient.b = params[2];
668     c->lighting.lightModel.ambient.a = params[3];
669     invalidate_lighting(c);
670 }
671 
672 // ----------------------------------------------------------------------------
673 #if 0
674 #pragma mark -
675 #endif
676 
glLightf(GLenum i,GLenum pname,GLfloat param)677 void glLightf(GLenum i, GLenum pname, GLfloat param)
678 {
679     ogles_context_t* c = ogles_context_t::get();
680     lightx(i, pname, gglFloatToFixed(param), c);
681 }
682 
glLightx(GLenum i,GLenum pname,GLfixed param)683 void glLightx(GLenum i, GLenum pname, GLfixed param)
684 {
685     ogles_context_t* c = ogles_context_t::get();
686     lightx(i, pname, param, c);
687 }
688 
glLightfv(GLenum i,GLenum pname,const GLfloat * params)689 void glLightfv(GLenum i, GLenum pname, const GLfloat *params)
690 {
691     ogles_context_t* c = ogles_context_t::get();
692     switch (pname) {
693     case GL_SPOT_EXPONENT:
694     case GL_SPOT_CUTOFF:
695     case GL_CONSTANT_ATTENUATION:
696     case GL_LINEAR_ATTENUATION:
697     case GL_QUADRATIC_ATTENUATION:
698         lightx(i, pname, gglFloatToFixed(params[0]), c);
699         return;
700     }
701 
702     GLfixed paramsx[4];
703     paramsx[0] = gglFloatToFixed(params[0]);
704     paramsx[1] = gglFloatToFixed(params[1]);
705     paramsx[2] = gglFloatToFixed(params[2]);
706     if (pname != GL_SPOT_DIRECTION)
707         paramsx[3] = gglFloatToFixed(params[3]);
708 
709     lightxv(i, pname, paramsx, c);
710 }
711 
glLightxv(GLenum i,GLenum pname,const GLfixed * params)712 void glLightxv(GLenum i, GLenum pname, const GLfixed *params)
713 {
714     ogles_context_t* c = ogles_context_t::get();
715     lightxv(i, pname, params, c);
716 }
717 
718 // ----------------------------------------------------------------------------
719 #if 0
720 #pragma mark -
721 #endif
722 
glMaterialf(GLenum face,GLenum pname,GLfloat param)723 void glMaterialf(GLenum face, GLenum pname, GLfloat param)
724 {
725     ogles_context_t* c = ogles_context_t::get();
726     materialx(face, pname, gglFloatToFixed(param), c);
727 }
728 
glMaterialx(GLenum face,GLenum pname,GLfixed param)729 void glMaterialx(GLenum face, GLenum pname, GLfixed param)
730 {
731     ogles_context_t* c = ogles_context_t::get();
732     materialx(face, pname, param, c);
733 }
734 
glMaterialfv(GLenum face,GLenum pname,const GLfloat * params)735 void glMaterialfv(
736     GLenum face, GLenum pname, const GLfloat *params)
737 {
738     ogles_context_t* c = ogles_context_t::get();
739     if (ggl_unlikely(face != GL_FRONT_AND_BACK)) {
740         ogles_error(c, GL_INVALID_ENUM);
741         return;
742     }
743     GLfixed* what=0;
744     GLfixed* other=0;
745     switch (pname) {
746     case GL_AMBIENT:    what = c->lighting.front.ambient.v; break;
747     case GL_DIFFUSE:    what = c->lighting.front.diffuse.v; break;
748     case GL_SPECULAR:   what = c->lighting.front.specular.v; break;
749     case GL_EMISSION:   what = c->lighting.front.emission.v; break;
750     case GL_AMBIENT_AND_DIFFUSE:
751         what  = c->lighting.front.ambient.v; break;
752         other = c->lighting.front.diffuse.v; break;
753         break;
754     case GL_SHININESS:
755         c->lighting.front.shininess = gglFloatToFixed(params[0]);
756         invalidate_lighting(c);
757         return;
758     default:
759         ogles_error(c, GL_INVALID_ENUM);
760         return;
761     }
762     what[0] = gglFloatToFixed(params[0]);
763     what[1] = gglFloatToFixed(params[1]);
764     what[2] = gglFloatToFixed(params[2]);
765     what[3] = gglFloatToFixed(params[3]);
766     if (other) {
767         other[0] = what[0];
768         other[1] = what[1];
769         other[2] = what[2];
770         other[3] = what[3];
771     }
772     invalidate_lighting(c);
773 }
774 
glMaterialxv(GLenum face,GLenum pname,const GLfixed * params)775 void glMaterialxv(
776     GLenum face, GLenum pname, const GLfixed *params)
777 {
778     ogles_context_t* c = ogles_context_t::get();
779     if (ggl_unlikely(face != GL_FRONT_AND_BACK)) {
780         ogles_error(c, GL_INVALID_ENUM);
781         return;
782     }
783     GLfixed* what=0;
784     GLfixed* other=0;
785     switch (pname) {
786     case GL_AMBIENT:    what = c->lighting.front.ambient.v; break;
787     case GL_DIFFUSE:    what = c->lighting.front.diffuse.v; break;
788     case GL_SPECULAR:   what = c->lighting.front.specular.v; break;
789     case GL_EMISSION:   what = c->lighting.front.emission.v; break;
790     case GL_AMBIENT_AND_DIFFUSE:
791         what = c->lighting.front.ambient.v; break;
792         other= c->lighting.front.diffuse.v; break;
793         break;
794     case GL_SHININESS:
795         c->lighting.front.shininess = gglFloatToFixed(params[0]);
796         invalidate_lighting(c);
797         return;
798     default:
799         ogles_error(c, GL_INVALID_ENUM);
800         return;
801     }
802     what[0] = params[0];
803     what[1] = params[1];
804     what[2] = params[2];
805     what[3] = params[3];
806     if (other) {
807         other[0] = what[0];
808         other[1] = what[1];
809         other[2] = what[2];
810         other[3] = what[3];
811     }
812     invalidate_lighting(c);
813 }
814 
815 // ----------------------------------------------------------------------------
816 #if 0
817 #pragma mark -
818 #pragma mark fog
819 #endif
820 
glFogf(GLenum pname,GLfloat param)821 void glFogf(GLenum pname, GLfloat param) {
822     ogles_context_t* c = ogles_context_t::get();
823     GLfixed paramx = (GLfixed)param;
824     if (pname != GL_FOG_MODE)
825         paramx = gglFloatToFixed(param);
826     fogx(pname, paramx, c);
827 }
828 
glFogx(GLenum pname,GLfixed param)829 void glFogx(GLenum pname, GLfixed param) {
830     ogles_context_t* c = ogles_context_t::get();
831     fogx(pname, param, c);
832 }
833 
glFogfv(GLenum pname,const GLfloat * params)834 void glFogfv(GLenum pname, const GLfloat *params)
835 {
836     ogles_context_t* c = ogles_context_t::get();
837     if (pname != GL_FOG_COLOR) {
838         GLfixed paramx = (GLfixed)params[0];
839         if (pname != GL_FOG_MODE)
840             paramx = gglFloatToFixed(params[0]);
841         fogx(pname, paramx, c);
842         return;
843     }
844     GLfixed paramsx[4];
845     paramsx[0] = gglFloatToFixed(params[0]);
846     paramsx[1] = gglFloatToFixed(params[1]);
847     paramsx[2] = gglFloatToFixed(params[2]);
848     paramsx[3] = gglFloatToFixed(params[3]);
849     c->rasterizer.procs.fogColor3xv(c, paramsx);
850 }
851 
glFogxv(GLenum pname,const GLfixed * params)852 void glFogxv(GLenum pname, const GLfixed *params)
853 {
854     ogles_context_t* c = ogles_context_t::get();
855     if (pname != GL_FOG_COLOR) {
856         fogx(pname, params[0], c);
857         return;
858     }
859     c->rasterizer.procs.fogColor3xv(c, params);
860 }
861