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