Home | History | Annotate | Download | only in libagl
      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 
     61 static void init_white(vec4_t& c) {
     62     c.r = c.g = c.b = c.a = 0x10000;
     63 }
     64 
     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 
    108 void ogles_uninit_light(ogles_context_t* /*c*/)
    109 {
    110 }
    111 
    112 static inline int32_t clampF(GLfixed f) CONST;
    113 int32_t clampF(GLfixed f) {
    114     f = (f & ~(f>>31));
    115     if (f >= 0x10000)
    116         f = 0x10000;
    117     return f;
    118 }
    119 
    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 
    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 
    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
    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
    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
    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
    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
    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 
    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 
    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 
    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 
    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 
    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 
    283 void ogles_invalidate_lighting_mvui(ogles_context_t* c)
    284 {
    285     invalidate_lighting(c);
    286 }
    287 
    288 void lightVertexNop(ogles_context_t*, vertex_t* /*v*/)
    289 {
    290     // we should never end-up here
    291 }
    292 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    649 void glLightModelx(GLenum pname, GLfixed param)
    650 {
    651     ogles_context_t* c = ogles_context_t::get();
    652     lightModelx(pname, param, c);
    653 }
    654 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    852 void glFogx(GLenum pname, GLfixed param) {
    853     ogles_context_t* c = ogles_context_t::get();
    854     fogx(pname, param, c);
    855 }
    856 
    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 
    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