ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

light.c
Go to the documentation of this file.
00001 /*
00002  * Mesa 3-D graphics library
00003  * Version:  7.0
00004  *
00005  * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
00006  *
00007  * Permission is hereby granted, free of charge, to any person obtaining a
00008  * copy of this software and associated documentation files (the "Software"),
00009  * to deal in the Software without restriction, including without limitation
00010  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00011  * and/or sell copies of the Software, and to permit persons to whom the
00012  * Software is furnished to do so, subject to the following conditions:
00013  *
00014  * The above copyright notice and this permission notice shall be included
00015  * in all copies or substantial portions of the Software.
00016  *
00017  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00018  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00019  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00020  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
00021  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00022  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00023  */
00024 
00025 
00026 #include "glheader.h"
00027 #include "imports.h"
00028 #include "context.h"
00029 #include "enums.h"
00030 #include "light.h"
00031 #include "macros.h"
00032 #include "simple_list.h"
00033 #include "mtypes.h"
00034 #include "math/m_matrix.h"
00035 
00036 
00037 void GLAPIENTRY
00038 _mesa_ShadeModel( GLenum mode )
00039 {
00040    GET_CURRENT_CONTEXT(ctx);
00041    ASSERT_OUTSIDE_BEGIN_END(ctx);
00042 
00043    if (MESA_VERBOSE & VERBOSE_API)
00044       _mesa_debug(ctx, "glShadeModel %s\n", _mesa_lookup_enum_by_nr(mode));
00045 
00046    if (mode != GL_FLAT && mode != GL_SMOOTH) {
00047       _mesa_error(ctx, GL_INVALID_ENUM, "glShadeModel");
00048       return;
00049    }
00050 
00051    if (ctx->Light.ShadeModel == mode)
00052       return;
00053 
00054    FLUSH_VERTICES(ctx, _NEW_LIGHT);
00055    ctx->Light.ShadeModel = mode;
00056    if (mode == GL_FLAT)
00057       ctx->_TriangleCaps |= DD_FLATSHADE;
00058    else
00059       ctx->_TriangleCaps &= ~DD_FLATSHADE;
00060 
00061    if (ctx->Driver.ShadeModel)
00062       ctx->Driver.ShadeModel( ctx, mode );
00063 }
00064 
00065 
00073 void
00074 _mesa_light(GLcontext *ctx, GLuint lnum, GLenum pname, const GLfloat *params)
00075 {
00076    struct gl_light *light;
00077 
00078    ASSERT(lnum < MAX_LIGHTS);
00079    light = &ctx->Light.Light[lnum];
00080 
00081    switch (pname) {
00082    case GL_AMBIENT:
00083       if (TEST_EQ_4V(light->Ambient, params))
00084      return;
00085       FLUSH_VERTICES(ctx, _NEW_LIGHT);
00086       COPY_4V( light->Ambient, params );
00087       break;
00088    case GL_DIFFUSE:
00089       if (TEST_EQ_4V(light->Diffuse, params))
00090      return;
00091       FLUSH_VERTICES(ctx, _NEW_LIGHT);
00092       COPY_4V( light->Diffuse, params );
00093       break;
00094    case GL_SPECULAR:
00095       if (TEST_EQ_4V(light->Specular, params))
00096      return;
00097       FLUSH_VERTICES(ctx, _NEW_LIGHT);
00098       COPY_4V( light->Specular, params );
00099       break;
00100    case GL_POSITION:
00101       /* NOTE: position has already been transformed by ModelView! */
00102       if (TEST_EQ_4V(light->EyePosition, params))
00103      return;
00104       FLUSH_VERTICES(ctx, _NEW_LIGHT);
00105       COPY_4V(light->EyePosition, params);
00106       if (light->EyePosition[3] != 0.0F)
00107      light->_Flags |= LIGHT_POSITIONAL;
00108       else
00109      light->_Flags &= ~LIGHT_POSITIONAL;
00110       break;
00111    case GL_SPOT_DIRECTION:
00112       /* NOTE: Direction already transformed by inverse ModelView! */
00113       if (TEST_EQ_3V(light->EyeDirection, params))
00114      return;
00115       FLUSH_VERTICES(ctx, _NEW_LIGHT);
00116       COPY_3V(light->EyeDirection, params);
00117       break;
00118    case GL_SPOT_EXPONENT:
00119       ASSERT(params[0] >= 0.0);
00120       ASSERT(params[0] <= ctx->Const.MaxSpotExponent);
00121       if (light->SpotExponent == params[0])
00122      return;
00123       FLUSH_VERTICES(ctx, _NEW_LIGHT);
00124       light->SpotExponent = params[0];
00125       _mesa_invalidate_spot_exp_table(light);
00126       break;
00127    case GL_SPOT_CUTOFF:
00128       ASSERT(params[0] == 180.0 || (params[0] >= 0.0 && params[0] <= 90.0));
00129       if (light->SpotCutoff == params[0])
00130          return;
00131       FLUSH_VERTICES(ctx, _NEW_LIGHT);
00132       light->SpotCutoff = params[0];
00133       light->_CosCutoffNeg = (GLfloat) (_mesa_cos(light->SpotCutoff * DEG2RAD));
00134       if (light->_CosCutoffNeg < 0)
00135          light->_CosCutoff = 0;
00136       else
00137          light->_CosCutoff = light->_CosCutoffNeg;
00138       if (light->SpotCutoff != 180.0F)
00139          light->_Flags |= LIGHT_SPOT;
00140       else
00141          light->_Flags &= ~LIGHT_SPOT;
00142       break;
00143    case GL_CONSTANT_ATTENUATION:
00144       ASSERT(params[0] >= 0.0);
00145       if (light->ConstantAttenuation == params[0])
00146      return;
00147       FLUSH_VERTICES(ctx, _NEW_LIGHT);
00148       light->ConstantAttenuation = params[0];
00149       break;
00150    case GL_LINEAR_ATTENUATION:
00151       ASSERT(params[0] >= 0.0);
00152       if (light->LinearAttenuation == params[0])
00153      return;
00154       FLUSH_VERTICES(ctx, _NEW_LIGHT);
00155       light->LinearAttenuation = params[0];
00156       break;
00157    case GL_QUADRATIC_ATTENUATION:
00158       ASSERT(params[0] >= 0.0);
00159       if (light->QuadraticAttenuation == params[0])
00160      return;
00161       FLUSH_VERTICES(ctx, _NEW_LIGHT);
00162       light->QuadraticAttenuation = params[0];
00163       break;
00164    default:
00165       _mesa_problem(ctx, "Unexpected pname in _mesa_light()");
00166       return;
00167    }
00168 
00169    if (ctx->Driver.Lightfv)
00170       ctx->Driver.Lightfv( ctx, GL_LIGHT0 + lnum, pname, params );
00171 }
00172 
00173 
00174 void GLAPIENTRY
00175 _mesa_Lightf( GLenum light, GLenum pname, GLfloat param )
00176 {
00177    _mesa_Lightfv( light, pname, &param );
00178 }
00179 
00180 
00181 void GLAPIENTRY
00182 _mesa_Lightfv( GLenum light, GLenum pname, const GLfloat *params )
00183 {
00184    GET_CURRENT_CONTEXT(ctx);
00185    GLint i = (GLint) (light - GL_LIGHT0);
00186    GLfloat temp[4];
00187    ASSERT_OUTSIDE_BEGIN_END(ctx);
00188 
00189    if (i < 0 || i >= (GLint) ctx->Const.MaxLights) {
00190       _mesa_error( ctx, GL_INVALID_ENUM, "glLight(light=0x%x)", light );
00191       return;
00192    }
00193 
00194    /* do particular error checks, transformations */
00195    switch (pname) {
00196    case GL_AMBIENT:
00197    case GL_DIFFUSE:
00198    case GL_SPECULAR:
00199       /* nothing */
00200       break;
00201    case GL_POSITION:
00202       /* transform position by ModelView matrix */
00203       TRANSFORM_POINT(temp, ctx->ModelviewMatrixStack.Top->m, params);
00204       params = temp;
00205       break;
00206    case GL_SPOT_DIRECTION:
00207       /* transform direction by inverse modelview */
00208       if (_math_matrix_is_dirty(ctx->ModelviewMatrixStack.Top)) {
00209      _math_matrix_analyse(ctx->ModelviewMatrixStack.Top);
00210       }
00211       TRANSFORM_DIRECTION(temp, params, ctx->ModelviewMatrixStack.Top->m);
00212       NORMALIZE_3FV(temp);
00213       params = temp;
00214       break;
00215    case GL_SPOT_EXPONENT:
00216       if (params[0] < 0.0 || params[0] > ctx->Const.MaxSpotExponent) {
00217      _mesa_error(ctx, GL_INVALID_VALUE, "glLight");
00218      return;
00219       }
00220       break;
00221    case GL_SPOT_CUTOFF:
00222       if ((params[0] < 0.0 || params[0] > 90.0) && params[0] != 180.0) {
00223      _mesa_error(ctx, GL_INVALID_VALUE, "glLight");
00224      return;
00225       }
00226       break;
00227    case GL_CONSTANT_ATTENUATION:
00228       if (params[0] < 0.0) {
00229      _mesa_error(ctx, GL_INVALID_VALUE, "glLight");
00230      return;
00231       }
00232       break;
00233    case GL_LINEAR_ATTENUATION:
00234       if (params[0] < 0.0) {
00235      _mesa_error(ctx, GL_INVALID_VALUE, "glLight");
00236      return;
00237       }
00238       break;
00239    case GL_QUADRATIC_ATTENUATION:
00240       if (params[0] < 0.0) {
00241      _mesa_error(ctx, GL_INVALID_VALUE, "glLight");
00242      return;
00243       }
00244       break;
00245    default:
00246       _mesa_error(ctx, GL_INVALID_ENUM, "glLight(pname=0x%x)", pname);
00247       return;
00248    }
00249 
00250    _mesa_light(ctx, i, pname, params);
00251 }
00252 
00253 
00254 void GLAPIENTRY
00255 _mesa_Lighti( GLenum light, GLenum pname, GLint param )
00256 {
00257    _mesa_Lightiv( light, pname, &param );
00258 }
00259 
00260 
00261 void GLAPIENTRY
00262 _mesa_Lightiv( GLenum light, GLenum pname, const GLint *params )
00263 {
00264    GLfloat fparam[4];
00265 
00266    switch (pname) {
00267       case GL_AMBIENT:
00268       case GL_DIFFUSE:
00269       case GL_SPECULAR:
00270          fparam[0] = INT_TO_FLOAT( params[0] );
00271          fparam[1] = INT_TO_FLOAT( params[1] );
00272          fparam[2] = INT_TO_FLOAT( params[2] );
00273          fparam[3] = INT_TO_FLOAT( params[3] );
00274          break;
00275       case GL_POSITION:
00276          fparam[0] = (GLfloat) params[0];
00277          fparam[1] = (GLfloat) params[1];
00278          fparam[2] = (GLfloat) params[2];
00279          fparam[3] = (GLfloat) params[3];
00280          break;
00281       case GL_SPOT_DIRECTION:
00282          fparam[0] = (GLfloat) params[0];
00283          fparam[1] = (GLfloat) params[1];
00284          fparam[2] = (GLfloat) params[2];
00285          break;
00286       case GL_SPOT_EXPONENT:
00287       case GL_SPOT_CUTOFF:
00288       case GL_CONSTANT_ATTENUATION:
00289       case GL_LINEAR_ATTENUATION:
00290       case GL_QUADRATIC_ATTENUATION:
00291          fparam[0] = (GLfloat) params[0];
00292          break;
00293       default:
00294          /* error will be caught later in gl_Lightfv */
00295          ;
00296    }
00297 
00298    _mesa_Lightfv( light, pname, fparam );
00299 }
00300 
00301 
00302 
00303 void GLAPIENTRY
00304 _mesa_GetLightfv( GLenum light, GLenum pname, GLfloat *params )
00305 {
00306    GET_CURRENT_CONTEXT(ctx);
00307    GLint l = (GLint) (light - GL_LIGHT0);
00308    ASSERT_OUTSIDE_BEGIN_END(ctx);
00309 
00310    if (l < 0 || l >= (GLint) ctx->Const.MaxLights) {
00311       _mesa_error( ctx, GL_INVALID_ENUM, "glGetLightfv" );
00312       return;
00313    }
00314 
00315    switch (pname) {
00316       case GL_AMBIENT:
00317          COPY_4V( params, ctx->Light.Light[l].Ambient );
00318          break;
00319       case GL_DIFFUSE:
00320          COPY_4V( params, ctx->Light.Light[l].Diffuse );
00321          break;
00322       case GL_SPECULAR:
00323          COPY_4V( params, ctx->Light.Light[l].Specular );
00324          break;
00325       case GL_POSITION:
00326          COPY_4V( params, ctx->Light.Light[l].EyePosition );
00327          break;
00328       case GL_SPOT_DIRECTION:
00329          COPY_3V( params, ctx->Light.Light[l].EyeDirection );
00330          break;
00331       case GL_SPOT_EXPONENT:
00332          params[0] = ctx->Light.Light[l].SpotExponent;
00333          break;
00334       case GL_SPOT_CUTOFF:
00335          params[0] = ctx->Light.Light[l].SpotCutoff;
00336          break;
00337       case GL_CONSTANT_ATTENUATION:
00338          params[0] = ctx->Light.Light[l].ConstantAttenuation;
00339          break;
00340       case GL_LINEAR_ATTENUATION:
00341          params[0] = ctx->Light.Light[l].LinearAttenuation;
00342          break;
00343       case GL_QUADRATIC_ATTENUATION:
00344          params[0] = ctx->Light.Light[l].QuadraticAttenuation;
00345          break;
00346       default:
00347          _mesa_error( ctx, GL_INVALID_ENUM, "glGetLightfv" );
00348          break;
00349    }
00350 }
00351 
00352 
00353 void GLAPIENTRY
00354 _mesa_GetLightiv( GLenum light, GLenum pname, GLint *params )
00355 {
00356    GET_CURRENT_CONTEXT(ctx);
00357    GLint l = (GLint) (light - GL_LIGHT0);
00358    ASSERT_OUTSIDE_BEGIN_END(ctx);
00359 
00360    if (l < 0 || l >= (GLint) ctx->Const.MaxLights) {
00361       _mesa_error( ctx, GL_INVALID_ENUM, "glGetLightiv" );
00362       return;
00363    }
00364 
00365    switch (pname) {
00366       case GL_AMBIENT:
00367          params[0] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[0]);
00368          params[1] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[1]);
00369          params[2] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[2]);
00370          params[3] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[3]);
00371          break;
00372       case GL_DIFFUSE:
00373          params[0] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[0]);
00374          params[1] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[1]);
00375          params[2] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[2]);
00376          params[3] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[3]);
00377          break;
00378       case GL_SPECULAR:
00379          params[0] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[0]);
00380          params[1] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[1]);
00381          params[2] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[2]);
00382          params[3] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[3]);
00383          break;
00384       case GL_POSITION:
00385          params[0] = (GLint) ctx->Light.Light[l].EyePosition[0];
00386          params[1] = (GLint) ctx->Light.Light[l].EyePosition[1];
00387          params[2] = (GLint) ctx->Light.Light[l].EyePosition[2];
00388          params[3] = (GLint) ctx->Light.Light[l].EyePosition[3];
00389          break;
00390       case GL_SPOT_DIRECTION:
00391          params[0] = (GLint) ctx->Light.Light[l].EyeDirection[0];
00392          params[1] = (GLint) ctx->Light.Light[l].EyeDirection[1];
00393          params[2] = (GLint) ctx->Light.Light[l].EyeDirection[2];
00394          break;
00395       case GL_SPOT_EXPONENT:
00396          params[0] = (GLint) ctx->Light.Light[l].SpotExponent;
00397          break;
00398       case GL_SPOT_CUTOFF:
00399          params[0] = (GLint) ctx->Light.Light[l].SpotCutoff;
00400          break;
00401       case GL_CONSTANT_ATTENUATION:
00402          params[0] = (GLint) ctx->Light.Light[l].ConstantAttenuation;
00403          break;
00404       case GL_LINEAR_ATTENUATION:
00405          params[0] = (GLint) ctx->Light.Light[l].LinearAttenuation;
00406          break;
00407       case GL_QUADRATIC_ATTENUATION:
00408          params[0] = (GLint) ctx->Light.Light[l].QuadraticAttenuation;
00409          break;
00410       default:
00411          _mesa_error( ctx, GL_INVALID_ENUM, "glGetLightiv" );
00412          break;
00413    }
00414 }
00415 
00416 
00417 
00418 /**********************************************************************/
00419 /***                        Light Model                             ***/
00420 /**********************************************************************/
00421 
00422 
00423 void GLAPIENTRY
00424 _mesa_LightModelfv( GLenum pname, const GLfloat *params )
00425 {
00426    GLenum newenum;
00427    GLboolean newbool;
00428    GET_CURRENT_CONTEXT(ctx);
00429    ASSERT_OUTSIDE_BEGIN_END(ctx);
00430 
00431    switch (pname) {
00432       case GL_LIGHT_MODEL_AMBIENT:
00433          if (TEST_EQ_4V( ctx->Light.Model.Ambient, params ))
00434         return;
00435      FLUSH_VERTICES(ctx, _NEW_LIGHT);
00436          COPY_4V( ctx->Light.Model.Ambient, params );
00437          break;
00438       case GL_LIGHT_MODEL_LOCAL_VIEWER:
00439          newbool = (params[0]!=0.0);
00440      if (ctx->Light.Model.LocalViewer == newbool)
00441         return;
00442      FLUSH_VERTICES(ctx, _NEW_LIGHT);
00443      ctx->Light.Model.LocalViewer = newbool;
00444          break;
00445       case GL_LIGHT_MODEL_TWO_SIDE:
00446          newbool = (params[0]!=0.0);
00447      if (ctx->Light.Model.TwoSide == newbool)
00448         return;
00449      FLUSH_VERTICES(ctx, _NEW_LIGHT);
00450      ctx->Light.Model.TwoSide = newbool;
00451          if (ctx->Light.Enabled && ctx->Light.Model.TwoSide)
00452             ctx->_TriangleCaps |= DD_TRI_LIGHT_TWOSIDE;
00453          else
00454             ctx->_TriangleCaps &= ~DD_TRI_LIGHT_TWOSIDE;
00455          break;
00456       case GL_LIGHT_MODEL_COLOR_CONTROL:
00457          if (params[0] == (GLfloat) GL_SINGLE_COLOR)
00458         newenum = GL_SINGLE_COLOR;
00459          else if (params[0] == (GLfloat) GL_SEPARATE_SPECULAR_COLOR)
00460         newenum = GL_SEPARATE_SPECULAR_COLOR;
00461      else {
00462             _mesa_error( ctx, GL_INVALID_ENUM, "glLightModel(param=0x0%x)",
00463                          (GLint) params[0] );
00464         return;
00465          }
00466      if (ctx->Light.Model.ColorControl == newenum)
00467         return;
00468      FLUSH_VERTICES(ctx, _NEW_LIGHT);
00469      ctx->Light.Model.ColorControl = newenum;
00470          break;
00471       default:
00472          _mesa_error( ctx, GL_INVALID_ENUM, "glLightModel(pname=0x%x)", pname );
00473          break;
00474    }
00475 
00476    if (ctx->Driver.LightModelfv)
00477       ctx->Driver.LightModelfv( ctx, pname, params );
00478 }
00479 
00480 
00481 void GLAPIENTRY
00482 _mesa_LightModeliv( GLenum pname, const GLint *params )
00483 {
00484    GLfloat fparam[4];
00485 
00486    switch (pname) {
00487       case GL_LIGHT_MODEL_AMBIENT:
00488          fparam[0] = INT_TO_FLOAT( params[0] );
00489          fparam[1] = INT_TO_FLOAT( params[1] );
00490          fparam[2] = INT_TO_FLOAT( params[2] );
00491          fparam[3] = INT_TO_FLOAT( params[3] );
00492          break;
00493       case GL_LIGHT_MODEL_LOCAL_VIEWER:
00494       case GL_LIGHT_MODEL_TWO_SIDE:
00495       case GL_LIGHT_MODEL_COLOR_CONTROL:
00496          fparam[0] = (GLfloat) params[0];
00497          break;
00498       default:
00499          /* Error will be caught later in gl_LightModelfv */
00500          ;
00501    }
00502    _mesa_LightModelfv( pname, fparam );
00503 }
00504 
00505 
00506 void GLAPIENTRY
00507 _mesa_LightModeli( GLenum pname, GLint param )
00508 {
00509    _mesa_LightModeliv( pname, &param );
00510 }
00511 
00512 
00513 void GLAPIENTRY
00514 _mesa_LightModelf( GLenum pname, GLfloat param )
00515 {
00516    _mesa_LightModelfv( pname, &param );
00517 }
00518 
00519 
00520 
00521 /********** MATERIAL **********/
00522 
00523 
00524 /*
00525  * Given a face and pname value (ala glColorMaterial), compute a bitmask
00526  * of the targeted material values.
00527  */
00528 GLuint
00529 _mesa_material_bitmask( GLcontext *ctx, GLenum face, GLenum pname,
00530                         GLuint legal, const char *where )
00531 {
00532    GLuint bitmask = 0;
00533 
00534    /* Make a bitmask indicating what material attribute(s) we're updating */
00535    switch (pname) {
00536       case GL_EMISSION:
00537          bitmask |= MAT_BIT_FRONT_EMISSION | MAT_BIT_BACK_EMISSION;
00538          break;
00539       case GL_AMBIENT:
00540          bitmask |= MAT_BIT_FRONT_AMBIENT | MAT_BIT_BACK_AMBIENT;
00541          break;
00542       case GL_DIFFUSE:
00543          bitmask |= MAT_BIT_FRONT_DIFFUSE | MAT_BIT_BACK_DIFFUSE;
00544          break;
00545       case GL_SPECULAR:
00546          bitmask |= MAT_BIT_FRONT_SPECULAR | MAT_BIT_BACK_SPECULAR;
00547          break;
00548       case GL_SHININESS:
00549          bitmask |= MAT_BIT_FRONT_SHININESS | MAT_BIT_BACK_SHININESS;
00550          break;
00551       case GL_AMBIENT_AND_DIFFUSE:
00552          bitmask |= MAT_BIT_FRONT_AMBIENT | MAT_BIT_BACK_AMBIENT;
00553          bitmask |= MAT_BIT_FRONT_DIFFUSE | MAT_BIT_BACK_DIFFUSE;
00554          break;
00555       case GL_COLOR_INDEXES:
00556          bitmask |= MAT_BIT_FRONT_INDEXES  | MAT_BIT_BACK_INDEXES;
00557          break;
00558       default:
00559          _mesa_error( ctx, GL_INVALID_ENUM, where );
00560          return 0;
00561    }
00562 
00563    if (face==GL_FRONT) {
00564       bitmask &= FRONT_MATERIAL_BITS;
00565    }
00566    else if (face==GL_BACK) {
00567       bitmask &= BACK_MATERIAL_BITS;
00568    }
00569    else if (face != GL_FRONT_AND_BACK) {
00570       _mesa_error( ctx, GL_INVALID_ENUM, where );
00571       return 0;
00572    }
00573 
00574    if (bitmask & ~legal) {
00575       _mesa_error( ctx, GL_INVALID_ENUM, where );
00576       return 0;
00577    }
00578 
00579    return bitmask;
00580 }
00581 
00582 
00583 
00584 /* Perform a straight copy between materials.
00585  */
00586 void
00587 _mesa_copy_materials( struct gl_material *dst,
00588                       const struct gl_material *src,
00589                       GLuint bitmask )
00590 {
00591    int i;
00592 
00593    for (i = 0 ; i < MAT_ATTRIB_MAX ; i++) 
00594       if (bitmask & (1<<i))
00595      COPY_4FV( dst->Attrib[i], src->Attrib[i] );
00596 }
00597 
00598 
00599 
00600 /* Update derived values following a change in ctx->Light.Material
00601  */
00602 void
00603 _mesa_update_material( GLcontext *ctx, GLuint bitmask )
00604 {
00605    struct gl_light *light, *list = &ctx->Light.EnabledList;
00606    GLfloat (*mat)[4] = ctx->Light.Material.Attrib;
00607 
00608    if (MESA_VERBOSE&VERBOSE_IMMEDIATE) 
00609       _mesa_debug(ctx, "_mesa_update_material, mask 0x%x\n", bitmask);
00610 
00611    if (!bitmask)
00612       return;
00613 
00614    /* update material ambience */
00615    if (bitmask & MAT_BIT_FRONT_AMBIENT) {
00616       foreach (light, list) {
00617          SCALE_3V( light->_MatAmbient[0], light->Ambient, 
00618            mat[MAT_ATTRIB_FRONT_AMBIENT]);
00619       }
00620    }
00621 
00622    if (bitmask & MAT_BIT_BACK_AMBIENT) {
00623       foreach (light, list) {
00624          SCALE_3V( light->_MatAmbient[1], light->Ambient, 
00625            mat[MAT_ATTRIB_BACK_AMBIENT]);
00626       }
00627    }
00628 
00629    /* update BaseColor = emission + scene's ambience * material's ambience */
00630    if (bitmask & (MAT_BIT_FRONT_EMISSION | MAT_BIT_FRONT_AMBIENT)) {
00631       COPY_3V( ctx->Light._BaseColor[0], mat[MAT_ATTRIB_FRONT_EMISSION] );
00632       ACC_SCALE_3V( ctx->Light._BaseColor[0], mat[MAT_ATTRIB_FRONT_AMBIENT],
00633             ctx->Light.Model.Ambient );
00634    }
00635 
00636    if (bitmask & (MAT_BIT_BACK_EMISSION | MAT_BIT_BACK_AMBIENT)) {
00637       COPY_3V( ctx->Light._BaseColor[1], mat[MAT_ATTRIB_BACK_EMISSION] );
00638       ACC_SCALE_3V( ctx->Light._BaseColor[1], mat[MAT_ATTRIB_BACK_AMBIENT],
00639             ctx->Light.Model.Ambient );
00640    }
00641 
00642    /* update material diffuse values */
00643    if (bitmask & MAT_BIT_FRONT_DIFFUSE) {
00644       foreach (light, list) {
00645      SCALE_3V( light->_MatDiffuse[0], light->Diffuse, 
00646            mat[MAT_ATTRIB_FRONT_DIFFUSE] );
00647       }
00648    }
00649 
00650    if (bitmask & MAT_BIT_BACK_DIFFUSE) {
00651       foreach (light, list) {
00652      SCALE_3V( light->_MatDiffuse[1], light->Diffuse, 
00653            mat[MAT_ATTRIB_BACK_DIFFUSE] );
00654       }
00655    }
00656 
00657    /* update material specular values */
00658    if (bitmask & MAT_BIT_FRONT_SPECULAR) {
00659       foreach (light, list) {
00660      SCALE_3V( light->_MatSpecular[0], light->Specular, 
00661            mat[MAT_ATTRIB_FRONT_SPECULAR]);
00662       }
00663    }
00664 
00665    if (bitmask & MAT_BIT_BACK_SPECULAR) {
00666       foreach (light, list) {
00667      SCALE_3V( light->_MatSpecular[1], light->Specular,
00668            mat[MAT_ATTRIB_BACK_SPECULAR]);
00669       }
00670    }
00671 
00672    if (bitmask & MAT_BIT_FRONT_SHININESS) {
00673       _mesa_invalidate_shine_table( ctx, 0 );
00674    }
00675 
00676    if (bitmask & MAT_BIT_BACK_SHININESS) {
00677       _mesa_invalidate_shine_table( ctx, 1 );
00678    }
00679 }
00680 
00681 
00682 /*
00683  * Update the current materials from the given rgba color
00684  * according to the bitmask in ColorMaterialBitmask, which is
00685  * set by glColorMaterial().
00686  */
00687 void
00688 _mesa_update_color_material( GLcontext *ctx, const GLfloat color[4] )
00689 {
00690    GLuint bitmask = ctx->Light.ColorMaterialBitmask;
00691    struct gl_material *mat = &ctx->Light.Material;
00692    int i;
00693 
00694    for (i = 0 ; i < MAT_ATTRIB_MAX ; i++) 
00695       if (bitmask & (1<<i))
00696      COPY_4FV( mat->Attrib[i], color );
00697 
00698    _mesa_update_material( ctx, bitmask );
00699 }
00700 
00701 
00702 void GLAPIENTRY
00703 _mesa_ColorMaterial( GLenum face, GLenum mode )
00704 {
00705    GET_CURRENT_CONTEXT(ctx);
00706    GLuint bitmask;
00707    GLuint legal = (MAT_BIT_FRONT_EMISSION | MAT_BIT_BACK_EMISSION |
00708            MAT_BIT_FRONT_SPECULAR | MAT_BIT_BACK_SPECULAR |
00709            MAT_BIT_FRONT_DIFFUSE  | MAT_BIT_BACK_DIFFUSE  |
00710            MAT_BIT_FRONT_AMBIENT  | MAT_BIT_BACK_AMBIENT);
00711    ASSERT_OUTSIDE_BEGIN_END(ctx);
00712 
00713    if (MESA_VERBOSE&VERBOSE_API)
00714       _mesa_debug(ctx, "glColorMaterial %s %s\n",
00715                   _mesa_lookup_enum_by_nr(face),
00716                   _mesa_lookup_enum_by_nr(mode));
00717 
00718    bitmask = _mesa_material_bitmask(ctx, face, mode, legal, "glColorMaterial");
00719 
00720    if (ctx->Light.ColorMaterialBitmask == bitmask &&
00721        ctx->Light.ColorMaterialFace == face &&
00722        ctx->Light.ColorMaterialMode == mode)
00723       return;
00724 
00725    FLUSH_VERTICES(ctx, _NEW_LIGHT);
00726    ctx->Light.ColorMaterialBitmask = bitmask;
00727    ctx->Light.ColorMaterialFace = face;
00728    ctx->Light.ColorMaterialMode = mode;
00729 
00730    if (ctx->Light.ColorMaterialEnabled) {
00731       FLUSH_CURRENT( ctx, 0 );
00732       _mesa_update_color_material(ctx,ctx->Current.Attrib[VERT_ATTRIB_COLOR0]);
00733    }
00734 
00735    if (ctx->Driver.ColorMaterial)
00736       ctx->Driver.ColorMaterial( ctx, face, mode );
00737 }
00738 
00739 
00740 void GLAPIENTRY
00741 _mesa_GetMaterialfv( GLenum face, GLenum pname, GLfloat *params )
00742 {
00743    GET_CURRENT_CONTEXT(ctx);
00744    GLuint f;
00745    GLfloat (*mat)[4] = ctx->Light.Material.Attrib;
00746    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* update materials */
00747 
00748    FLUSH_CURRENT(ctx, 0); /* update ctx->Light.Material from vertex buffer */
00749 
00750    if (face==GL_FRONT) {
00751       f = 0;
00752    }
00753    else if (face==GL_BACK) {
00754       f = 1;
00755    }
00756    else {
00757       _mesa_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(face)" );
00758       return;
00759    }
00760 
00761    switch (pname) {
00762       case GL_AMBIENT:
00763          COPY_4FV( params, mat[MAT_ATTRIB_AMBIENT(f)] );
00764          break;
00765       case GL_DIFFUSE:
00766          COPY_4FV( params, mat[MAT_ATTRIB_DIFFUSE(f)] );
00767      break;
00768       case GL_SPECULAR:
00769          COPY_4FV( params, mat[MAT_ATTRIB_SPECULAR(f)] );
00770      break;
00771       case GL_EMISSION:
00772      COPY_4FV( params, mat[MAT_ATTRIB_EMISSION(f)] );
00773      break;
00774       case GL_SHININESS:
00775      *params = mat[MAT_ATTRIB_SHININESS(f)][0];
00776      break;
00777       case GL_COLOR_INDEXES:
00778      params[0] = mat[MAT_ATTRIB_INDEXES(f)][0];
00779      params[1] = mat[MAT_ATTRIB_INDEXES(f)][1];
00780      params[2] = mat[MAT_ATTRIB_INDEXES(f)][2];
00781      break;
00782       default:
00783          _mesa_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(pname)" );
00784    }
00785 }
00786 
00787 
00788 void GLAPIENTRY
00789 _mesa_GetMaterialiv( GLenum face, GLenum pname, GLint *params )
00790 {
00791    GET_CURRENT_CONTEXT(ctx);
00792    GLuint f;
00793    GLfloat (*mat)[4] = ctx->Light.Material.Attrib;
00794    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* update materials */
00795 
00796    FLUSH_CURRENT(ctx, 0); /* update ctx->Light.Material from vertex buffer */
00797 
00798    if (face==GL_FRONT) {
00799       f = 0;
00800    }
00801    else if (face==GL_BACK) {
00802       f = 1;
00803    }
00804    else {
00805       _mesa_error( ctx, GL_INVALID_ENUM, "glGetMaterialiv(face)" );
00806       return;
00807    }
00808    switch (pname) {
00809       case GL_AMBIENT:
00810          params[0] = FLOAT_TO_INT( mat[MAT_ATTRIB_AMBIENT(f)][0] );
00811          params[1] = FLOAT_TO_INT( mat[MAT_ATTRIB_AMBIENT(f)][1] );
00812          params[2] = FLOAT_TO_INT( mat[MAT_ATTRIB_AMBIENT(f)][2] );
00813          params[3] = FLOAT_TO_INT( mat[MAT_ATTRIB_AMBIENT(f)][3] );
00814          break;
00815       case GL_DIFFUSE:
00816          params[0] = FLOAT_TO_INT( mat[MAT_ATTRIB_DIFFUSE(f)][0] );
00817          params[1] = FLOAT_TO_INT( mat[MAT_ATTRIB_DIFFUSE(f)][1] );
00818          params[2] = FLOAT_TO_INT( mat[MAT_ATTRIB_DIFFUSE(f)][2] );
00819          params[3] = FLOAT_TO_INT( mat[MAT_ATTRIB_DIFFUSE(f)][3] );
00820      break;
00821       case GL_SPECULAR:
00822          params[0] = FLOAT_TO_INT( mat[MAT_ATTRIB_SPECULAR(f)][0] );
00823          params[1] = FLOAT_TO_INT( mat[MAT_ATTRIB_SPECULAR(f)][1] );
00824          params[2] = FLOAT_TO_INT( mat[MAT_ATTRIB_SPECULAR(f)][2] );
00825          params[3] = FLOAT_TO_INT( mat[MAT_ATTRIB_SPECULAR(f)][3] );
00826      break;
00827       case GL_EMISSION:
00828          params[0] = FLOAT_TO_INT( mat[MAT_ATTRIB_EMISSION(f)][0] );
00829          params[1] = FLOAT_TO_INT( mat[MAT_ATTRIB_EMISSION(f)][1] );
00830          params[2] = FLOAT_TO_INT( mat[MAT_ATTRIB_EMISSION(f)][2] );
00831          params[3] = FLOAT_TO_INT( mat[MAT_ATTRIB_EMISSION(f)][3] );
00832      break;
00833       case GL_SHININESS:
00834          *params = IROUND( mat[MAT_ATTRIB_SHININESS(f)][0] );
00835      break;
00836       case GL_COLOR_INDEXES:
00837      params[0] = IROUND( mat[MAT_ATTRIB_INDEXES(f)][0] );
00838      params[1] = IROUND( mat[MAT_ATTRIB_INDEXES(f)][1] );
00839      params[2] = IROUND( mat[MAT_ATTRIB_INDEXES(f)][2] );
00840      break;
00841       default:
00842          _mesa_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(pname)" );
00843    }
00844 }
00845 
00846 
00847 
00848 /**********************************************************************/
00849 /*****                  Lighting computation                      *****/
00850 /**********************************************************************/
00851 
00852 
00853 /*
00854  * Notes:
00855  *   When two-sided lighting is enabled we compute the color (or index)
00856  *   for both the front and back side of the primitive.  Then, when the
00857  *   orientation of the facet is later learned, we can determine which
00858  *   color (or index) to use for rendering.
00859  *
00860  *   KW: We now know orientation in advance and only shade for
00861  *       the side or sides which are actually required.
00862  *
00863  * Variables:
00864  *   n = normal vector
00865  *   V = vertex position
00866  *   P = light source position
00867  *   Pe = (0,0,0,1)
00868  *
00869  * Precomputed:
00870  *   IF P[3]==0 THEN
00871  *       // light at infinity
00872  *       IF local_viewer THEN
00873  *           _VP_inf_norm = unit vector from V to P      // Precompute
00874  *       ELSE
00875  *           // eye at infinity
00876  *           _h_inf_norm = Normalize( VP + <0,0,1> )     // Precompute
00877  *       ENDIF
00878  *   ENDIF
00879  *
00880  * Functions:
00881  *   Normalize( v ) = normalized vector v
00882  *   Magnitude( v ) = length of vector v
00883  */
00884 
00885 
00886 
00887 /*
00888  * Whenever the spotlight exponent for a light changes we must call
00889  * this function to recompute the exponent lookup table.
00890  */
00891 void
00892 _mesa_invalidate_spot_exp_table( struct gl_light *l )
00893 {
00894    l->_SpotExpTable[0][0] = -1;
00895 }
00896 
00897 
00898 static void
00899 validate_spot_exp_table( struct gl_light *l )
00900 {
00901    GLint i;
00902    GLdouble exponent = l->SpotExponent;
00903    GLdouble tmp = 0;
00904    GLint clamp = 0;
00905 
00906    l->_SpotExpTable[0][0] = 0.0;
00907 
00908    for (i = EXP_TABLE_SIZE - 1; i > 0 ;i--) {
00909       if (clamp == 0) {
00910      tmp = _mesa_pow(i / (GLdouble) (EXP_TABLE_SIZE - 1), exponent);
00911      if (tmp < FLT_MIN * 100.0) {
00912         tmp = 0.0;
00913         clamp = 1;
00914      }
00915       }
00916       l->_SpotExpTable[i][0] = (GLfloat) tmp;
00917    }
00918    for (i = 0; i < EXP_TABLE_SIZE - 1; i++) {
00919       l->_SpotExpTable[i][1] = (l->_SpotExpTable[i+1][0] -
00920                 l->_SpotExpTable[i][0]);
00921    }
00922    l->_SpotExpTable[EXP_TABLE_SIZE-1][1] = 0.0;
00923 }
00924 
00925 
00926 
00927 /* Calculate a new shine table.  Doing this here saves a branch in
00928  * lighting, and the cost of doing it early may be partially offset
00929  * by keeping a MRU cache of shine tables for various shine values.
00930  */
00931 void
00932 _mesa_invalidate_shine_table( GLcontext *ctx, GLuint side )
00933 {
00934    ASSERT(side < 2);
00935    if (ctx->_ShineTable[side])
00936       ctx->_ShineTable[side]->refcount--;
00937    ctx->_ShineTable[side] = NULL;
00938 }
00939 
00940 
00941 static void
00942 validate_shine_table( GLcontext *ctx, GLuint side, GLfloat shininess )
00943 {
00944    struct gl_shine_tab *list = ctx->_ShineTabList;
00945    struct gl_shine_tab *s;
00946 
00947    ASSERT(side < 2);
00948 
00949    foreach(s, list)
00950       if ( s->shininess == shininess )
00951      break;
00952 
00953    if (s == list) {
00954       GLint j;
00955       GLfloat *m;
00956 
00957       foreach(s, list)
00958      if (s->refcount == 0)
00959         break;
00960 
00961       m = s->tab;
00962       m[0] = 0.0;
00963       if (shininess == 0.0) {
00964      for (j = 1 ; j <= SHINE_TABLE_SIZE ; j++)
00965         m[j] = 1.0;
00966       }
00967       else {
00968      for (j = 1 ; j < SHINE_TABLE_SIZE ; j++) {
00969             GLdouble t, x = j / (GLfloat) (SHINE_TABLE_SIZE - 1);
00970             if (x < 0.005) /* underflow check */
00971                x = 0.005;
00972             t = _mesa_pow(x, shininess);
00973         if (t > 1e-20)
00974            m[j] = (GLfloat) t;
00975         else
00976            m[j] = 0.0;
00977      }
00978      m[SHINE_TABLE_SIZE] = 1.0;
00979       }
00980 
00981       s->shininess = shininess;
00982    }
00983 
00984    if (ctx->_ShineTable[side])
00985       ctx->_ShineTable[side]->refcount--;
00986 
00987    ctx->_ShineTable[side] = s;
00988    move_to_tail( list, s );
00989    s->refcount++;
00990 }
00991 
00992 
00993 void
00994 _mesa_validate_all_lighting_tables( GLcontext *ctx )
00995 {
00996    GLuint i;
00997    GLfloat shininess;
00998    
00999    shininess = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SHININESS][0];
01000    if (!ctx->_ShineTable[0] || ctx->_ShineTable[0]->shininess != shininess)
01001       validate_shine_table( ctx, 0, shininess );
01002 
01003    shininess = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_SHININESS][0];
01004    if (!ctx->_ShineTable[1] || ctx->_ShineTable[1]->shininess != shininess)
01005       validate_shine_table( ctx, 1, shininess );
01006 
01007    for (i = 0; i < ctx->Const.MaxLights; i++)
01008       if (ctx->Light.Light[i]._SpotExpTable[0][0] == -1)
01009      validate_spot_exp_table( &ctx->Light.Light[i] );
01010 }
01011 
01012 
01019 void
01020 _mesa_update_lighting( GLcontext *ctx )
01021 {
01022    struct gl_light *light;
01023    ctx->Light._NeedEyeCoords = GL_FALSE;
01024    ctx->Light._Flags = 0;
01025 
01026    if (!ctx->Light.Enabled)
01027       return;
01028 
01029    foreach(light, &ctx->Light.EnabledList) {
01030       ctx->Light._Flags |= light->_Flags;
01031    }
01032 
01033    ctx->Light._NeedVertices =
01034       ((ctx->Light._Flags & (LIGHT_POSITIONAL|LIGHT_SPOT)) ||
01035        ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR ||
01036        ctx->Light.Model.LocalViewer);
01037 
01038    ctx->Light._NeedEyeCoords = ((ctx->Light._Flags & LIGHT_POSITIONAL) ||
01039                 ctx->Light.Model.LocalViewer);
01040 
01041    /* XXX: This test is overkill & needs to be fixed both for software and
01042     * hardware t&l drivers.  The above should be sufficient & should
01043     * be tested to verify this.
01044     */
01045    if (ctx->Light._NeedVertices)
01046       ctx->Light._NeedEyeCoords = GL_TRUE;
01047 
01048    /* Precompute some shading values.  Although we reference
01049     * Light.Material here, we can get away without flushing
01050     * FLUSH_UPDATE_CURRENT, as when any outstanding material changes
01051     * are flushed, they will update the derived state at that time.
01052     */
01053    if (ctx->Visual.rgbMode) {
01054       if (ctx->Light.Model.TwoSide)
01055      _mesa_update_material( ctx, 
01056                 MAT_BIT_FRONT_EMISSION |
01057                 MAT_BIT_FRONT_AMBIENT |
01058                 MAT_BIT_FRONT_DIFFUSE | 
01059                 MAT_BIT_FRONT_SPECULAR |
01060                 MAT_BIT_BACK_EMISSION |
01061                 MAT_BIT_BACK_AMBIENT |
01062                 MAT_BIT_BACK_DIFFUSE | 
01063                 MAT_BIT_BACK_SPECULAR);
01064       else
01065      _mesa_update_material( ctx, 
01066                 MAT_BIT_FRONT_EMISSION |
01067                 MAT_BIT_FRONT_AMBIENT |
01068                 MAT_BIT_FRONT_DIFFUSE | 
01069                 MAT_BIT_FRONT_SPECULAR);
01070    }
01071    else {
01072       static const GLfloat ci[3] = { .30F, .59F, .11F };
01073       foreach(light, &ctx->Light.EnabledList) {
01074      light->_dli = DOT3(ci, light->Diffuse);
01075      light->_sli = DOT3(ci, light->Specular);
01076       }
01077    }
01078 }
01079 
01080 
01091 static void
01092 compute_light_positions( GLcontext *ctx )
01093 {
01094    struct gl_light *light;
01095    static const GLfloat eye_z[3] = { 0, 0, 1 };
01096 
01097    if (!ctx->Light.Enabled)
01098       return;
01099 
01100    if (ctx->_NeedEyeCoords) {
01101       COPY_3V( ctx->_EyeZDir, eye_z );
01102    }
01103    else {
01104       TRANSFORM_NORMAL( ctx->_EyeZDir, eye_z, ctx->ModelviewMatrixStack.Top->m );
01105    }
01106 
01107    foreach (light, &ctx->Light.EnabledList) {
01108 
01109       if (ctx->_NeedEyeCoords) {
01110          /* _Position is in eye coordinate space */
01111      COPY_4FV( light->_Position, light->EyePosition );
01112       }
01113       else {
01114          /* _Position is in object coordinate space */
01115      TRANSFORM_POINT( light->_Position, ctx->ModelviewMatrixStack.Top->inv,
01116               light->EyePosition );
01117       }
01118 
01119       if (!(light->_Flags & LIGHT_POSITIONAL)) {
01120      /* VP (VP) = Normalize( Position ) */
01121      COPY_3V( light->_VP_inf_norm, light->_Position );
01122      NORMALIZE_3FV( light->_VP_inf_norm );
01123 
01124      if (!ctx->Light.Model.LocalViewer) {
01125         /* _h_inf_norm = Normalize( V_to_P + <0,0,1> ) */
01126         ADD_3V( light->_h_inf_norm, light->_VP_inf_norm, ctx->_EyeZDir);
01127         NORMALIZE_3FV( light->_h_inf_norm );
01128      }
01129      light->_VP_inf_spot_attenuation = 1.0;
01130       }
01131       else {
01132          /* positional light w/ homogeneous coordinate, divide by W */
01133          GLfloat wInv = (GLfloat)1.0 / light->_Position[3];
01134          light->_Position[0] *= wInv;
01135          light->_Position[1] *= wInv;
01136          light->_Position[2] *= wInv;
01137       }
01138 
01139       if (light->_Flags & LIGHT_SPOT) {
01140      if (ctx->_NeedEyeCoords) {
01141         COPY_3V( light->_NormDirection, light->EyeDirection );
01142      }
01143          else {
01144         TRANSFORM_NORMAL( light->_NormDirection,
01145                   light->EyeDirection,
01146                   ctx->ModelviewMatrixStack.Top->m);
01147      }
01148 
01149      NORMALIZE_3FV( light->_NormDirection );
01150 
01151      if (!(light->_Flags & LIGHT_POSITIONAL)) {
01152         GLfloat PV_dot_dir = - DOT3(light->_VP_inf_norm,
01153                     light->_NormDirection);
01154 
01155         if (PV_dot_dir > light->_CosCutoff) {
01156            double x = PV_dot_dir * (EXP_TABLE_SIZE-1);
01157            int k = (int) x;
01158            light->_VP_inf_spot_attenuation =
01159           (GLfloat) (light->_SpotExpTable[k][0] +
01160            (x-k)*light->_SpotExpTable[k][1]);
01161         }
01162         else {
01163            light->_VP_inf_spot_attenuation = 0;
01164             }
01165      }
01166       }
01167    }
01168 }
01169 
01170 
01171 
01172 static void
01173 update_modelview_scale( GLcontext *ctx )
01174 {
01175    ctx->_ModelViewInvScale = 1.0F;
01176    if (!_math_matrix_is_length_preserving(ctx->ModelviewMatrixStack.Top)) {
01177       const GLfloat *m = ctx->ModelviewMatrixStack.Top->inv;
01178       GLfloat f = m[2] * m[2] + m[6] * m[6] + m[10] * m[10];
01179       if (f < 1e-12) f = 1.0;
01180       if (ctx->_NeedEyeCoords)
01181      ctx->_ModelViewInvScale = (GLfloat) INV_SQRTF(f);
01182       else
01183      ctx->_ModelViewInvScale = (GLfloat) SQRTF(f);
01184    }
01185 }
01186 
01187 
01191 void
01192 _mesa_update_tnl_spaces( GLcontext *ctx, GLuint new_state )
01193 {
01194    const GLuint oldneedeyecoords = ctx->_NeedEyeCoords;
01195 
01196    (void) new_state;
01197    ctx->_NeedEyeCoords = GL_FALSE;
01198 
01199    if (ctx->_ForceEyeCoords ||
01200        (ctx->Texture._GenFlags & TEXGEN_NEED_EYE_COORD) ||
01201        ctx->Point._Attenuated ||
01202        ctx->Light._NeedEyeCoords)
01203       ctx->_NeedEyeCoords = GL_TRUE;
01204 
01205    if (ctx->Light.Enabled &&
01206        !_math_matrix_is_length_preserving(ctx->ModelviewMatrixStack.Top))
01207       ctx->_NeedEyeCoords = GL_TRUE;
01208 
01209    /* Check if the truth-value interpretations of the bitfields have
01210     * changed:
01211     */
01212    if (oldneedeyecoords != ctx->_NeedEyeCoords) {
01213       /* Recalculate all state that depends on _NeedEyeCoords.
01214        */
01215       update_modelview_scale(ctx);
01216       compute_light_positions( ctx );
01217 
01218       if (ctx->Driver.LightingSpaceChange)
01219      ctx->Driver.LightingSpaceChange( ctx );
01220    }
01221    else {
01222       GLuint new_state = ctx->NewState;
01223 
01224       /* Recalculate that same state only if it has been invalidated
01225        * by other statechanges.
01226        */
01227       if (new_state & _NEW_MODELVIEW)
01228      update_modelview_scale(ctx);
01229 
01230       if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW))
01231      compute_light_positions( ctx );
01232    }
01233 }
01234 
01235 
01240 void
01241 _mesa_allow_light_in_model( GLcontext *ctx, GLboolean flag )
01242 {
01243    ctx->_ForceEyeCoords = !flag;
01244    ctx->NewState |= _NEW_POINT; /* one of the bits from
01245                  * _MESA_NEW_NEED_EYE_COORDS.
01246                  */
01247 }
01248 
01249 
01250 
01251 /**********************************************************************/
01252 /*****                      Initialization                        *****/
01253 /**********************************************************************/
01254 
01262 static void
01263 init_light( struct gl_light *l, GLuint n )
01264 {
01265    make_empty_list( l );
01266 
01267    ASSIGN_4V( l->Ambient, 0.0, 0.0, 0.0, 1.0 );
01268    if (n==0) {
01269       ASSIGN_4V( l->Diffuse, 1.0, 1.0, 1.0, 1.0 );
01270       ASSIGN_4V( l->Specular, 1.0, 1.0, 1.0, 1.0 );
01271    }
01272    else {
01273       ASSIGN_4V( l->Diffuse, 0.0, 0.0, 0.0, 1.0 );
01274       ASSIGN_4V( l->Specular, 0.0, 0.0, 0.0, 1.0 );
01275    }
01276    ASSIGN_4V( l->EyePosition, 0.0, 0.0, 1.0, 0.0 );
01277    ASSIGN_3V( l->EyeDirection, 0.0, 0.0, -1.0 );
01278    l->SpotExponent = 0.0;
01279    _mesa_invalidate_spot_exp_table( l );
01280    l->SpotCutoff = 180.0;
01281    l->_CosCutoffNeg = -1.0f;
01282    l->_CosCutoff = 0.0;     /* KW: -ve values not admitted */
01283    l->ConstantAttenuation = 1.0;
01284    l->LinearAttenuation = 0.0;
01285    l->QuadraticAttenuation = 0.0;
01286    l->Enabled = GL_FALSE;
01287 }
01288 
01289 
01295 static void
01296 init_lightmodel( struct gl_lightmodel *lm )
01297 {
01298    ASSIGN_4V( lm->Ambient, 0.2F, 0.2F, 0.2F, 1.0F );
01299    lm->LocalViewer = GL_FALSE;
01300    lm->TwoSide = GL_FALSE;
01301    lm->ColorControl = GL_SINGLE_COLOR;
01302 }
01303 
01304 
01310 static void
01311 init_material( struct gl_material *m )
01312 {
01313    ASSIGN_4V( m->Attrib[MAT_ATTRIB_FRONT_AMBIENT],  0.2F, 0.2F, 0.2F, 1.0F );
01314    ASSIGN_4V( m->Attrib[MAT_ATTRIB_FRONT_DIFFUSE],  0.8F, 0.8F, 0.8F, 1.0F );
01315    ASSIGN_4V( m->Attrib[MAT_ATTRIB_FRONT_SPECULAR], 0.0F, 0.0F, 0.0F, 1.0F );
01316    ASSIGN_4V( m->Attrib[MAT_ATTRIB_FRONT_EMISSION], 0.0F, 0.0F, 0.0F, 1.0F );
01317    ASSIGN_4V( m->Attrib[MAT_ATTRIB_FRONT_SHININESS], 0.0F, 0.0F, 0.0F, 0.0F );
01318    ASSIGN_4V( m->Attrib[MAT_ATTRIB_FRONT_INDEXES], 0.0F, 1.0F, 1.0F, 0.0F );
01319  
01320    ASSIGN_4V( m->Attrib[MAT_ATTRIB_BACK_AMBIENT],  0.2F, 0.2F, 0.2F, 1.0F );
01321    ASSIGN_4V( m->Attrib[MAT_ATTRIB_BACK_DIFFUSE],  0.8F, 0.8F, 0.8F, 1.0F );
01322    ASSIGN_4V( m->Attrib[MAT_ATTRIB_BACK_SPECULAR], 0.0F, 0.0F, 0.0F, 1.0F );
01323    ASSIGN_4V( m->Attrib[MAT_ATTRIB_BACK_EMISSION], 0.0F, 0.0F, 0.0F, 1.0F );
01324    ASSIGN_4V( m->Attrib[MAT_ATTRIB_BACK_SHININESS], 0.0F, 0.0F, 0.0F, 0.0F );
01325    ASSIGN_4V( m->Attrib[MAT_ATTRIB_BACK_INDEXES], 0.0F, 1.0F, 1.0F, 0.0F );
01326 }
01327 
01328 
01332 void
01333 _mesa_init_lighting( GLcontext *ctx )
01334 {
01335    GLuint i;
01336 
01337    /* Lighting group */
01338    for (i = 0; i < MAX_LIGHTS; i++) {
01339       init_light( &ctx->Light.Light[i], i );
01340    }
01341    make_empty_list( &ctx->Light.EnabledList );
01342 
01343    init_lightmodel( &ctx->Light.Model );
01344    init_material( &ctx->Light.Material );
01345    ctx->Light.ShadeModel = GL_SMOOTH;
01346    ctx->Light.Enabled = GL_FALSE;
01347    ctx->Light.ColorMaterialFace = GL_FRONT_AND_BACK;
01348    ctx->Light.ColorMaterialMode = GL_AMBIENT_AND_DIFFUSE;
01349    ctx->Light.ColorMaterialBitmask = _mesa_material_bitmask( ctx,
01350                                                GL_FRONT_AND_BACK,
01351                                                GL_AMBIENT_AND_DIFFUSE, ~0,
01352                                                NULL );
01353 
01354    ctx->Light.ColorMaterialEnabled = GL_FALSE;
01355    ctx->Light.ClampVertexColor = GL_TRUE;
01356 
01357    /* Lighting miscellaneous */
01358    ctx->_ShineTabList = MALLOC_STRUCT( gl_shine_tab );
01359    make_empty_list( ctx->_ShineTabList );
01360    /* Allocate 10 (arbitrary) shininess lookup tables */
01361    for (i = 0 ; i < 10 ; i++) {
01362       struct gl_shine_tab *s = MALLOC_STRUCT( gl_shine_tab );
01363       s->shininess = -1;
01364       s->refcount = 0;
01365       insert_at_tail( ctx->_ShineTabList, s );
01366    }
01367 
01368    /* Miscellaneous */
01369    ctx->Light._NeedEyeCoords = GL_FALSE;
01370    ctx->_NeedEyeCoords = GL_FALSE;
01371    ctx->_ModelViewInvScale = 1.0;
01372 }
01373 
01374 
01378 void
01379 _mesa_free_lighting_data( GLcontext *ctx )
01380 {
01381    struct gl_shine_tab *s, *tmps;
01382 
01383    /* Free lighting shininess exponentiation table */
01384    foreach_s( s, tmps, ctx->_ShineTabList ) {
01385       _mesa_free( s );
01386    }
01387    _mesa_free( ctx->_ShineTabList );
01388 }

Generated on Sun May 27 2012 04:20:20 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.