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