Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Mesa 3-D graphics library
  3.  * Version:  7.5
  4.  *
  5.  * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
  6.  * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
  7.  *
  8.  * Permission is hereby granted, free of charge, to any person obtaining a
  9.  * copy of this software and associated documentation files (the "Software"),
  10.  * to deal in the Software without restriction, including without limitation
  11.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  12.  * and/or sell copies of the Software, and to permit persons to whom the
  13.  * Software is furnished to do so, subject to the following conditions:
  14.  *
  15.  * The above copyright notice and this permission notice shall be included
  16.  * in all copies or substantial portions of the Software.
  17.  *
  18.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  19.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  21.  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  22.  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  23.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  24.  */
  25.  
  26.  
  27. #include "glheader.h"
  28. #include "imports.h"
  29. #include "context.h"
  30. #include "enums.h"
  31. #include "light.h"
  32. #include "macros.h"
  33. #include "simple_list.h"
  34. #include "mtypes.h"
  35. #include "math/m_matrix.h"
  36.  
  37.  
  38. void GLAPIENTRY
  39. _mesa_ShadeModel( GLenum mode )
  40. {
  41.    GET_CURRENT_CONTEXT(ctx);
  42.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  43.  
  44.    if (MESA_VERBOSE & VERBOSE_API)
  45.       _mesa_debug(ctx, "glShadeModel %s\n", _mesa_lookup_enum_by_nr(mode));
  46.  
  47.    if (mode != GL_FLAT && mode != GL_SMOOTH) {
  48.       _mesa_error(ctx, GL_INVALID_ENUM, "glShadeModel");
  49.       return;
  50.    }
  51.  
  52.    if (ctx->Light.ShadeModel == mode)
  53.       return;
  54.  
  55.    FLUSH_VERTICES(ctx, _NEW_LIGHT);
  56.    ctx->Light.ShadeModel = mode;
  57.    if (mode == GL_FLAT)
  58.       ctx->_TriangleCaps |= DD_FLATSHADE;
  59.    else
  60.       ctx->_TriangleCaps &= ~DD_FLATSHADE;
  61.  
  62.    if (ctx->Driver.ShadeModel)
  63.       ctx->Driver.ShadeModel( ctx, mode );
  64. }
  65.  
  66.  
  67. /**
  68.  * Set the provoking vertex (the vertex which specifies the prim's
  69.  * color when flat shading) to either the first or last vertex of the
  70.  * triangle or line.
  71.  */
  72. void GLAPIENTRY
  73. _mesa_ProvokingVertexEXT(GLenum mode)
  74. {
  75.    GET_CURRENT_CONTEXT(ctx);
  76.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  77.  
  78.    if (MESA_VERBOSE&VERBOSE_API)
  79.       _mesa_debug(ctx, "glProvokingVertexEXT 0x%x\n", mode);
  80.  
  81.    switch (mode) {
  82.    case GL_FIRST_VERTEX_CONVENTION_EXT:
  83.    case GL_LAST_VERTEX_CONVENTION_EXT:
  84.       break;
  85.    default:
  86.       _mesa_error(ctx, GL_INVALID_ENUM, "glProvokingVertexEXT(0x%x)", mode);
  87.       return;
  88.    }
  89.  
  90.    if (ctx->Light.ProvokingVertex == mode)
  91.       return;
  92.  
  93.    FLUSH_VERTICES(ctx, _NEW_LIGHT);
  94.    ctx->Light.ProvokingVertex = mode;
  95. }
  96.  
  97.  
  98. /**
  99.  * Helper function called by _mesa_Lightfv and _mesa_PopAttrib to set
  100.  * per-light state.
  101.  * For GL_POSITION and GL_SPOT_DIRECTION the params position/direction
  102.  * will have already been transformed by the modelview matrix!
  103.  * Also, all error checking should have already been done.
  104.  */
  105. void
  106. _mesa_light(struct gl_context *ctx, GLuint lnum, GLenum pname, const GLfloat *params)
  107. {
  108.    struct gl_light *light;
  109.  
  110.    ASSERT(lnum < MAX_LIGHTS);
  111.    light = &ctx->Light.Light[lnum];
  112.  
  113.    switch (pname) {
  114.    case GL_AMBIENT:
  115.       if (TEST_EQ_4V(light->Ambient, params))
  116.          return;
  117.       FLUSH_VERTICES(ctx, _NEW_LIGHT);
  118.       COPY_4V( light->Ambient, params );
  119.       break;
  120.    case GL_DIFFUSE:
  121.       if (TEST_EQ_4V(light->Diffuse, params))
  122.          return;
  123.       FLUSH_VERTICES(ctx, _NEW_LIGHT);
  124.       COPY_4V( light->Diffuse, params );
  125.       break;
  126.    case GL_SPECULAR:
  127.       if (TEST_EQ_4V(light->Specular, params))
  128.          return;
  129.       FLUSH_VERTICES(ctx, _NEW_LIGHT);
  130.       COPY_4V( light->Specular, params );
  131.       break;
  132.    case GL_POSITION:
  133.       /* NOTE: position has already been transformed by ModelView! */
  134.       if (TEST_EQ_4V(light->EyePosition, params))
  135.          return;
  136.       FLUSH_VERTICES(ctx, _NEW_LIGHT);
  137.       COPY_4V(light->EyePosition, params);
  138.       if (light->EyePosition[3] != 0.0F)
  139.          light->_Flags |= LIGHT_POSITIONAL;
  140.       else
  141.          light->_Flags &= ~LIGHT_POSITIONAL;
  142.       break;
  143.    case GL_SPOT_DIRECTION:
  144.       /* NOTE: Direction already transformed by inverse ModelView! */
  145.       if (TEST_EQ_3V(light->SpotDirection, params))
  146.          return;
  147.       FLUSH_VERTICES(ctx, _NEW_LIGHT);
  148.       COPY_3V(light->SpotDirection, params);
  149.       break;
  150.    case GL_SPOT_EXPONENT:
  151.       ASSERT(params[0] >= 0.0);
  152.       ASSERT(params[0] <= ctx->Const.MaxSpotExponent);
  153.       if (light->SpotExponent == params[0])
  154.          return;
  155.       FLUSH_VERTICES(ctx, _NEW_LIGHT);
  156.       light->SpotExponent = params[0];
  157.       _mesa_invalidate_spot_exp_table(light);
  158.       break;
  159.    case GL_SPOT_CUTOFF:
  160.       ASSERT(params[0] == 180.0 || (params[0] >= 0.0 && params[0] <= 90.0));
  161.       if (light->SpotCutoff == params[0])
  162.          return;
  163.       FLUSH_VERTICES(ctx, _NEW_LIGHT);
  164.       light->SpotCutoff = params[0];
  165.       light->_CosCutoffNeg = (GLfloat) (cos(light->SpotCutoff * DEG2RAD));
  166.       if (light->_CosCutoffNeg < 0)
  167.          light->_CosCutoff = 0;
  168.       else
  169.          light->_CosCutoff = light->_CosCutoffNeg;
  170.       if (light->SpotCutoff != 180.0F)
  171.          light->_Flags |= LIGHT_SPOT;
  172.       else
  173.          light->_Flags &= ~LIGHT_SPOT;
  174.       break;
  175.    case GL_CONSTANT_ATTENUATION:
  176.       ASSERT(params[0] >= 0.0);
  177.       if (light->ConstantAttenuation == params[0])
  178.          return;
  179.       FLUSH_VERTICES(ctx, _NEW_LIGHT);
  180.       light->ConstantAttenuation = params[0];
  181.       break;
  182.    case GL_LINEAR_ATTENUATION:
  183.       ASSERT(params[0] >= 0.0);
  184.       if (light->LinearAttenuation == params[0])
  185.          return;
  186.       FLUSH_VERTICES(ctx, _NEW_LIGHT);
  187.       light->LinearAttenuation = params[0];
  188.       break;
  189.    case GL_QUADRATIC_ATTENUATION:
  190.       ASSERT(params[0] >= 0.0);
  191.       if (light->QuadraticAttenuation == params[0])
  192.          return;
  193.       FLUSH_VERTICES(ctx, _NEW_LIGHT);
  194.       light->QuadraticAttenuation = params[0];
  195.       break;
  196.    default:
  197.       _mesa_problem(ctx, "Unexpected pname in _mesa_light()");
  198.       return;
  199.    }
  200.  
  201.    if (ctx->Driver.Lightfv)
  202.       ctx->Driver.Lightfv( ctx, GL_LIGHT0 + lnum, pname, params );
  203. }
  204.  
  205.  
  206. void GLAPIENTRY
  207. _mesa_Lightf( GLenum light, GLenum pname, GLfloat param )
  208. {
  209.    GLfloat fparam[4];
  210.    fparam[0] = param;
  211.    fparam[1] = fparam[2] = fparam[3] = 0.0F;
  212.    _mesa_Lightfv( light, pname, fparam );
  213. }
  214.  
  215.  
  216. void GLAPIENTRY
  217. _mesa_Lightfv( GLenum light, GLenum pname, const GLfloat *params )
  218. {
  219.    GET_CURRENT_CONTEXT(ctx);
  220.    GLint i = (GLint) (light - GL_LIGHT0);
  221.    GLfloat temp[4];
  222.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  223.  
  224.    if (i < 0 || i >= (GLint) ctx->Const.MaxLights) {
  225.       _mesa_error( ctx, GL_INVALID_ENUM, "glLight(light=0x%x)", light );
  226.       return;
  227.    }
  228.  
  229.    /* do particular error checks, transformations */
  230.    switch (pname) {
  231.    case GL_AMBIENT:
  232.    case GL_DIFFUSE:
  233.    case GL_SPECULAR:
  234.       /* nothing */
  235.       break;
  236.    case GL_POSITION:
  237.       /* transform position by ModelView matrix */
  238.       TRANSFORM_POINT(temp, ctx->ModelviewMatrixStack.Top->m, params);
  239.       params = temp;
  240.       break;
  241.    case GL_SPOT_DIRECTION:
  242.       /* transform direction by inverse modelview */
  243.       if (_math_matrix_is_dirty(ctx->ModelviewMatrixStack.Top)) {
  244.          _math_matrix_analyse(ctx->ModelviewMatrixStack.Top);
  245.       }
  246.       TRANSFORM_DIRECTION(temp, params, ctx->ModelviewMatrixStack.Top->m);
  247.       params = temp;
  248.       break;
  249.    case GL_SPOT_EXPONENT:
  250.       if (params[0] < 0.0 || params[0] > ctx->Const.MaxSpotExponent) {
  251.          _mesa_error(ctx, GL_INVALID_VALUE, "glLight");
  252.          return;
  253.       }
  254.       break;
  255.    case GL_SPOT_CUTOFF:
  256.       if ((params[0] < 0.0 || params[0] > 90.0) && params[0] != 180.0) {
  257.          _mesa_error(ctx, GL_INVALID_VALUE, "glLight");
  258.          return;
  259.       }
  260.       break;
  261.    case GL_CONSTANT_ATTENUATION:
  262.       if (params[0] < 0.0) {
  263.          _mesa_error(ctx, GL_INVALID_VALUE, "glLight");
  264.          return;
  265.       }
  266.       break;
  267.    case GL_LINEAR_ATTENUATION:
  268.       if (params[0] < 0.0) {
  269.          _mesa_error(ctx, GL_INVALID_VALUE, "glLight");
  270.          return;
  271.       }
  272.       break;
  273.    case GL_QUADRATIC_ATTENUATION:
  274.       if (params[0] < 0.0) {
  275.          _mesa_error(ctx, GL_INVALID_VALUE, "glLight");
  276.          return;
  277.       }
  278.       break;
  279.    default:
  280.       _mesa_error(ctx, GL_INVALID_ENUM, "glLight(pname=0x%x)", pname);
  281.       return;
  282.    }
  283.  
  284.    _mesa_light(ctx, i, pname, params);
  285. }
  286.  
  287.  
  288. void GLAPIENTRY
  289. _mesa_Lighti( GLenum light, GLenum pname, GLint param )
  290. {
  291.    GLint iparam[4];
  292.    iparam[0] = param;
  293.    iparam[1] = iparam[2] = iparam[3] = 0;
  294.    _mesa_Lightiv( light, pname, iparam );
  295. }
  296.  
  297.  
  298. void GLAPIENTRY
  299. _mesa_Lightiv( GLenum light, GLenum pname, const GLint *params )
  300. {
  301.    GLfloat fparam[4];
  302.  
  303.    switch (pname) {
  304.       case GL_AMBIENT:
  305.       case GL_DIFFUSE:
  306.       case GL_SPECULAR:
  307.          fparam[0] = INT_TO_FLOAT( params[0] );
  308.          fparam[1] = INT_TO_FLOAT( params[1] );
  309.          fparam[2] = INT_TO_FLOAT( params[2] );
  310.          fparam[3] = INT_TO_FLOAT( params[3] );
  311.          break;
  312.       case GL_POSITION:
  313.          fparam[0] = (GLfloat) params[0];
  314.          fparam[1] = (GLfloat) params[1];
  315.          fparam[2] = (GLfloat) params[2];
  316.          fparam[3] = (GLfloat) params[3];
  317.          break;
  318.       case GL_SPOT_DIRECTION:
  319.          fparam[0] = (GLfloat) params[0];
  320.          fparam[1] = (GLfloat) params[1];
  321.          fparam[2] = (GLfloat) params[2];
  322.          break;
  323.       case GL_SPOT_EXPONENT:
  324.       case GL_SPOT_CUTOFF:
  325.       case GL_CONSTANT_ATTENUATION:
  326.       case GL_LINEAR_ATTENUATION:
  327.       case GL_QUADRATIC_ATTENUATION:
  328.          fparam[0] = (GLfloat) params[0];
  329.          break;
  330.       default:
  331.          /* error will be caught later in gl_Lightfv */
  332.          ;
  333.    }
  334.  
  335.    _mesa_Lightfv( light, pname, fparam );
  336. }
  337.  
  338.  
  339.  
  340. void GLAPIENTRY
  341. _mesa_GetLightfv( GLenum light, GLenum pname, GLfloat *params )
  342. {
  343.    GET_CURRENT_CONTEXT(ctx);
  344.    GLint l = (GLint) (light - GL_LIGHT0);
  345.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  346.  
  347.    if (l < 0 || l >= (GLint) ctx->Const.MaxLights) {
  348.       _mesa_error( ctx, GL_INVALID_ENUM, "glGetLightfv" );
  349.       return;
  350.    }
  351.  
  352.    switch (pname) {
  353.       case GL_AMBIENT:
  354.          COPY_4V( params, ctx->Light.Light[l].Ambient );
  355.          break;
  356.       case GL_DIFFUSE:
  357.          COPY_4V( params, ctx->Light.Light[l].Diffuse );
  358.          break;
  359.       case GL_SPECULAR:
  360.          COPY_4V( params, ctx->Light.Light[l].Specular );
  361.          break;
  362.       case GL_POSITION:
  363.          COPY_4V( params, ctx->Light.Light[l].EyePosition );
  364.          break;
  365.       case GL_SPOT_DIRECTION:
  366.          COPY_3V( params, ctx->Light.Light[l].SpotDirection );
  367.          break;
  368.       case GL_SPOT_EXPONENT:
  369.          params[0] = ctx->Light.Light[l].SpotExponent;
  370.          break;
  371.       case GL_SPOT_CUTOFF:
  372.          params[0] = ctx->Light.Light[l].SpotCutoff;
  373.          break;
  374.       case GL_CONSTANT_ATTENUATION:
  375.          params[0] = ctx->Light.Light[l].ConstantAttenuation;
  376.          break;
  377.       case GL_LINEAR_ATTENUATION:
  378.          params[0] = ctx->Light.Light[l].LinearAttenuation;
  379.          break;
  380.       case GL_QUADRATIC_ATTENUATION:
  381.          params[0] = ctx->Light.Light[l].QuadraticAttenuation;
  382.          break;
  383.       default:
  384.          _mesa_error( ctx, GL_INVALID_ENUM, "glGetLightfv" );
  385.          break;
  386.    }
  387. }
  388.  
  389.  
  390. void GLAPIENTRY
  391. _mesa_GetLightiv( GLenum light, GLenum pname, GLint *params )
  392. {
  393.    GET_CURRENT_CONTEXT(ctx);
  394.    GLint l = (GLint) (light - GL_LIGHT0);
  395.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  396.  
  397.    if (l < 0 || l >= (GLint) ctx->Const.MaxLights) {
  398.       _mesa_error( ctx, GL_INVALID_ENUM, "glGetLightiv" );
  399.       return;
  400.    }
  401.  
  402.    switch (pname) {
  403.       case GL_AMBIENT:
  404.          params[0] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[0]);
  405.          params[1] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[1]);
  406.          params[2] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[2]);
  407.          params[3] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[3]);
  408.          break;
  409.       case GL_DIFFUSE:
  410.          params[0] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[0]);
  411.          params[1] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[1]);
  412.          params[2] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[2]);
  413.          params[3] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[3]);
  414.          break;
  415.       case GL_SPECULAR:
  416.          params[0] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[0]);
  417.          params[1] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[1]);
  418.          params[2] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[2]);
  419.          params[3] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[3]);
  420.          break;
  421.       case GL_POSITION:
  422.          params[0] = (GLint) ctx->Light.Light[l].EyePosition[0];
  423.          params[1] = (GLint) ctx->Light.Light[l].EyePosition[1];
  424.          params[2] = (GLint) ctx->Light.Light[l].EyePosition[2];
  425.          params[3] = (GLint) ctx->Light.Light[l].EyePosition[3];
  426.          break;
  427.       case GL_SPOT_DIRECTION:
  428.          params[0] = (GLint) ctx->Light.Light[l].SpotDirection[0];
  429.          params[1] = (GLint) ctx->Light.Light[l].SpotDirection[1];
  430.          params[2] = (GLint) ctx->Light.Light[l].SpotDirection[2];
  431.          break;
  432.       case GL_SPOT_EXPONENT:
  433.          params[0] = (GLint) ctx->Light.Light[l].SpotExponent;
  434.          break;
  435.       case GL_SPOT_CUTOFF:
  436.          params[0] = (GLint) ctx->Light.Light[l].SpotCutoff;
  437.          break;
  438.       case GL_CONSTANT_ATTENUATION:
  439.          params[0] = (GLint) ctx->Light.Light[l].ConstantAttenuation;
  440.          break;
  441.       case GL_LINEAR_ATTENUATION:
  442.          params[0] = (GLint) ctx->Light.Light[l].LinearAttenuation;
  443.          break;
  444.       case GL_QUADRATIC_ATTENUATION:
  445.          params[0] = (GLint) ctx->Light.Light[l].QuadraticAttenuation;
  446.          break;
  447.       default:
  448.          _mesa_error( ctx, GL_INVALID_ENUM, "glGetLightiv" );
  449.          break;
  450.    }
  451. }
  452.  
  453.  
  454.  
  455. /**********************************************************************/
  456. /***                        Light Model                             ***/
  457. /**********************************************************************/
  458.  
  459.  
  460. void GLAPIENTRY
  461. _mesa_LightModelfv( GLenum pname, const GLfloat *params )
  462. {
  463.    GLenum newenum;
  464.    GLboolean newbool;
  465.    GET_CURRENT_CONTEXT(ctx);
  466.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  467.  
  468.    switch (pname) {
  469.       case GL_LIGHT_MODEL_AMBIENT:
  470.          if (TEST_EQ_4V( ctx->Light.Model.Ambient, params ))
  471.             return;
  472.          FLUSH_VERTICES(ctx, _NEW_LIGHT);
  473.          COPY_4V( ctx->Light.Model.Ambient, params );
  474.          break;
  475.       case GL_LIGHT_MODEL_LOCAL_VIEWER:
  476.          newbool = (params[0]!=0.0);
  477.          if (ctx->Light.Model.LocalViewer == newbool)
  478.             return;
  479.          FLUSH_VERTICES(ctx, _NEW_LIGHT);
  480.          ctx->Light.Model.LocalViewer = newbool;
  481.          break;
  482.       case GL_LIGHT_MODEL_TWO_SIDE:
  483.          newbool = (params[0]!=0.0);
  484.          if (ctx->Light.Model.TwoSide == newbool)
  485.             return;
  486.          FLUSH_VERTICES(ctx, _NEW_LIGHT);
  487.          ctx->Light.Model.TwoSide = newbool;
  488.          if (ctx->Light.Enabled && ctx->Light.Model.TwoSide)
  489.             ctx->_TriangleCaps |= DD_TRI_LIGHT_TWOSIDE;
  490.          else
  491.             ctx->_TriangleCaps &= ~DD_TRI_LIGHT_TWOSIDE;
  492.          break;
  493.       case GL_LIGHT_MODEL_COLOR_CONTROL:
  494.          if (params[0] == (GLfloat) GL_SINGLE_COLOR)
  495.             newenum = GL_SINGLE_COLOR;
  496.          else if (params[0] == (GLfloat) GL_SEPARATE_SPECULAR_COLOR)
  497.             newenum = GL_SEPARATE_SPECULAR_COLOR;
  498.          else {
  499.             _mesa_error( ctx, GL_INVALID_ENUM, "glLightModel(param=0x0%x)",
  500.                          (GLint) params[0] );
  501.             return;
  502.          }
  503.          if (ctx->Light.Model.ColorControl == newenum)
  504.             return;
  505.          FLUSH_VERTICES(ctx, _NEW_LIGHT);
  506.          ctx->Light.Model.ColorControl = newenum;
  507.          break;
  508.       default:
  509.          _mesa_error( ctx, GL_INVALID_ENUM, "glLightModel(pname=0x%x)", pname );
  510.          break;
  511.    }
  512.  
  513.    if (ctx->Driver.LightModelfv)
  514.       ctx->Driver.LightModelfv( ctx, pname, params );
  515. }
  516.  
  517.  
  518. void GLAPIENTRY
  519. _mesa_LightModeliv( GLenum pname, const GLint *params )
  520. {
  521.    GLfloat fparam[4];
  522.  
  523.    switch (pname) {
  524.       case GL_LIGHT_MODEL_AMBIENT:
  525.          fparam[0] = INT_TO_FLOAT( params[0] );
  526.          fparam[1] = INT_TO_FLOAT( params[1] );
  527.          fparam[2] = INT_TO_FLOAT( params[2] );
  528.          fparam[3] = INT_TO_FLOAT( params[3] );
  529.          break;
  530.       case GL_LIGHT_MODEL_LOCAL_VIEWER:
  531.       case GL_LIGHT_MODEL_TWO_SIDE:
  532.       case GL_LIGHT_MODEL_COLOR_CONTROL:
  533.          fparam[0] = (GLfloat) params[0];
  534.          break;
  535.       default:
  536.          /* Error will be caught later in gl_LightModelfv */
  537.          ASSIGN_4V(fparam, 0.0F, 0.0F, 0.0F, 0.0F);
  538.    }
  539.    _mesa_LightModelfv( pname, fparam );
  540. }
  541.  
  542.  
  543. void GLAPIENTRY
  544. _mesa_LightModeli( GLenum pname, GLint param )
  545. {
  546.    GLint iparam[4];
  547.    iparam[0] = param;
  548.    iparam[1] = iparam[2] = iparam[3] = 0;
  549.    _mesa_LightModeliv( pname, iparam );
  550. }
  551.  
  552.  
  553. void GLAPIENTRY
  554. _mesa_LightModelf( GLenum pname, GLfloat param )
  555. {
  556.    GLfloat fparam[4];
  557.    fparam[0] = param;
  558.    fparam[1] = fparam[2] = fparam[3] = 0.0F;
  559.    _mesa_LightModelfv( pname, fparam );
  560. }
  561.  
  562.  
  563.  
  564. /********** MATERIAL **********/
  565.  
  566.  
  567. /*
  568.  * Given a face and pname value (ala glColorMaterial), compute a bitmask
  569.  * of the targeted material values.
  570.  */
  571. GLuint
  572. _mesa_material_bitmask( struct gl_context *ctx, GLenum face, GLenum pname,
  573.                         GLuint legal, const char *where )
  574. {
  575.    GLuint bitmask = 0;
  576.  
  577.    /* Make a bitmask indicating what material attribute(s) we're updating */
  578.    switch (pname) {
  579.       case GL_EMISSION:
  580.          bitmask |= MAT_BIT_FRONT_EMISSION | MAT_BIT_BACK_EMISSION;
  581.          break;
  582.       case GL_AMBIENT:
  583.          bitmask |= MAT_BIT_FRONT_AMBIENT | MAT_BIT_BACK_AMBIENT;
  584.          break;
  585.       case GL_DIFFUSE:
  586.          bitmask |= MAT_BIT_FRONT_DIFFUSE | MAT_BIT_BACK_DIFFUSE;
  587.          break;
  588.       case GL_SPECULAR:
  589.          bitmask |= MAT_BIT_FRONT_SPECULAR | MAT_BIT_BACK_SPECULAR;
  590.          break;
  591.       case GL_SHININESS:
  592.          bitmask |= MAT_BIT_FRONT_SHININESS | MAT_BIT_BACK_SHININESS;
  593.          break;
  594.       case GL_AMBIENT_AND_DIFFUSE:
  595.          bitmask |= MAT_BIT_FRONT_AMBIENT | MAT_BIT_BACK_AMBIENT;
  596.          bitmask |= MAT_BIT_FRONT_DIFFUSE | MAT_BIT_BACK_DIFFUSE;
  597.          break;
  598.       case GL_COLOR_INDEXES:
  599.          bitmask |= MAT_BIT_FRONT_INDEXES  | MAT_BIT_BACK_INDEXES;
  600.          break;
  601.       default:
  602.          _mesa_error( ctx, GL_INVALID_ENUM, "%s", where );
  603.          return 0;
  604.    }
  605.  
  606.    if (face==GL_FRONT) {
  607.       bitmask &= FRONT_MATERIAL_BITS;
  608.    }
  609.    else if (face==GL_BACK) {
  610.       bitmask &= BACK_MATERIAL_BITS;
  611.    }
  612.    else if (face != GL_FRONT_AND_BACK) {
  613.       _mesa_error( ctx, GL_INVALID_ENUM, "%s", where );
  614.       return 0;
  615.    }
  616.  
  617.    if (bitmask & ~legal) {
  618.       _mesa_error( ctx, GL_INVALID_ENUM, "%s", where );
  619.       return 0;
  620.    }
  621.  
  622.    return bitmask;
  623. }
  624.  
  625.  
  626.  
  627. /* Perform a straight copy between materials.
  628.  */
  629. void
  630. _mesa_copy_materials( struct gl_material *dst,
  631.                       const struct gl_material *src,
  632.                       GLuint bitmask )
  633. {
  634.    int i;
  635.  
  636.    for (i = 0 ; i < MAT_ATTRIB_MAX ; i++)
  637.       if (bitmask & (1<<i))
  638.          COPY_4FV( dst->Attrib[i], src->Attrib[i] );
  639. }
  640.  
  641.  
  642.  
  643. /* Update derived values following a change in ctx->Light.Material
  644.  */
  645. void
  646. _mesa_update_material( struct gl_context *ctx, GLuint bitmask )
  647. {
  648.    struct gl_light *light, *list = &ctx->Light.EnabledList;
  649.    GLfloat (*mat)[4] = ctx->Light.Material.Attrib;
  650.  
  651.    if (MESA_VERBOSE & VERBOSE_MATERIAL)
  652.       _mesa_debug(ctx, "_mesa_update_material, mask 0x%x\n", bitmask);
  653.  
  654.    if (!bitmask)
  655.       return;
  656.  
  657.    /* update material ambience */
  658.    if (bitmask & MAT_BIT_FRONT_AMBIENT) {
  659.       foreach (light, list) {
  660.          SCALE_3V( light->_MatAmbient[0], light->Ambient,
  661.                    mat[MAT_ATTRIB_FRONT_AMBIENT]);
  662.       }
  663.    }
  664.  
  665.    if (bitmask & MAT_BIT_BACK_AMBIENT) {
  666.       foreach (light, list) {
  667.          SCALE_3V( light->_MatAmbient[1], light->Ambient,
  668.                    mat[MAT_ATTRIB_BACK_AMBIENT]);
  669.       }
  670.    }
  671.  
  672.    /* update BaseColor = emission + scene's ambience * material's ambience */
  673.    if (bitmask & (MAT_BIT_FRONT_EMISSION | MAT_BIT_FRONT_AMBIENT)) {
  674.       COPY_3V( ctx->Light._BaseColor[0], mat[MAT_ATTRIB_FRONT_EMISSION] );
  675.       ACC_SCALE_3V( ctx->Light._BaseColor[0], mat[MAT_ATTRIB_FRONT_AMBIENT],
  676.                     ctx->Light.Model.Ambient );
  677.    }
  678.  
  679.    if (bitmask & (MAT_BIT_BACK_EMISSION | MAT_BIT_BACK_AMBIENT)) {
  680.       COPY_3V( ctx->Light._BaseColor[1], mat[MAT_ATTRIB_BACK_EMISSION] );
  681.       ACC_SCALE_3V( ctx->Light._BaseColor[1], mat[MAT_ATTRIB_BACK_AMBIENT],
  682.                     ctx->Light.Model.Ambient );
  683.    }
  684.  
  685.    /* update material diffuse values */
  686.    if (bitmask & MAT_BIT_FRONT_DIFFUSE) {
  687.       foreach (light, list) {
  688.          SCALE_3V( light->_MatDiffuse[0], light->Diffuse,
  689.                    mat[MAT_ATTRIB_FRONT_DIFFUSE] );
  690.       }
  691.    }
  692.  
  693.    if (bitmask & MAT_BIT_BACK_DIFFUSE) {
  694.       foreach (light, list) {
  695.          SCALE_3V( light->_MatDiffuse[1], light->Diffuse,
  696.                    mat[MAT_ATTRIB_BACK_DIFFUSE] );
  697.       }
  698.    }
  699.  
  700.    /* update material specular values */
  701.    if (bitmask & MAT_BIT_FRONT_SPECULAR) {
  702.       foreach (light, list) {
  703.          SCALE_3V( light->_MatSpecular[0], light->Specular,
  704.                    mat[MAT_ATTRIB_FRONT_SPECULAR]);
  705.       }
  706.    }
  707.  
  708.    if (bitmask & MAT_BIT_BACK_SPECULAR) {
  709.       foreach (light, list) {
  710.          SCALE_3V( light->_MatSpecular[1], light->Specular,
  711.                    mat[MAT_ATTRIB_BACK_SPECULAR]);
  712.       }
  713.    }
  714.  
  715.    if (bitmask & MAT_BIT_FRONT_SHININESS) {
  716.       _mesa_invalidate_shine_table( ctx, 0 );
  717.    }
  718.  
  719.    if (bitmask & MAT_BIT_BACK_SHININESS) {
  720.       _mesa_invalidate_shine_table( ctx, 1 );
  721.    }
  722. }
  723.  
  724.  
  725. /*
  726.  * Update the current materials from the given rgba color
  727.  * according to the bitmask in ColorMaterialBitmask, which is
  728.  * set by glColorMaterial().
  729.  */
  730. void
  731. _mesa_update_color_material( struct gl_context *ctx, const GLfloat color[4] )
  732. {
  733.    GLuint bitmask = ctx->Light.ColorMaterialBitmask;
  734.    struct gl_material *mat = &ctx->Light.Material;
  735.    int i;
  736.  
  737.    for (i = 0 ; i < MAT_ATTRIB_MAX ; i++)
  738.       if (bitmask & (1<<i))
  739.          COPY_4FV( mat->Attrib[i], color );
  740.  
  741.    _mesa_update_material( ctx, bitmask );
  742. }
  743.  
  744.  
  745. void GLAPIENTRY
  746. _mesa_ColorMaterial( GLenum face, GLenum mode )
  747. {
  748.    GET_CURRENT_CONTEXT(ctx);
  749.    GLuint bitmask;
  750.    GLuint legal = (MAT_BIT_FRONT_EMISSION | MAT_BIT_BACK_EMISSION |
  751.                    MAT_BIT_FRONT_SPECULAR | MAT_BIT_BACK_SPECULAR |
  752.                    MAT_BIT_FRONT_DIFFUSE  | MAT_BIT_BACK_DIFFUSE  |
  753.                    MAT_BIT_FRONT_AMBIENT  | MAT_BIT_BACK_AMBIENT);
  754.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  755.  
  756.    if (MESA_VERBOSE&VERBOSE_API)
  757.       _mesa_debug(ctx, "glColorMaterial %s %s\n",
  758.                   _mesa_lookup_enum_by_nr(face),
  759.                   _mesa_lookup_enum_by_nr(mode));
  760.  
  761.    bitmask = _mesa_material_bitmask(ctx, face, mode, legal, "glColorMaterial");
  762.  
  763.    if (ctx->Light.ColorMaterialBitmask == bitmask &&
  764.        ctx->Light.ColorMaterialFace == face &&
  765.        ctx->Light.ColorMaterialMode == mode)
  766.       return;
  767.  
  768.    FLUSH_VERTICES(ctx, _NEW_LIGHT);
  769.    ctx->Light.ColorMaterialBitmask = bitmask;
  770.    ctx->Light.ColorMaterialFace = face;
  771.    ctx->Light.ColorMaterialMode = mode;
  772.  
  773.    if (ctx->Light.ColorMaterialEnabled) {
  774.       FLUSH_CURRENT( ctx, 0 );
  775.       _mesa_update_color_material(ctx,ctx->Current.Attrib[VERT_ATTRIB_COLOR0]);
  776.    }
  777.  
  778.    if (ctx->Driver.ColorMaterial)
  779.       ctx->Driver.ColorMaterial( ctx, face, mode );
  780. }
  781.  
  782.  
  783. void GLAPIENTRY
  784. _mesa_GetMaterialfv( GLenum face, GLenum pname, GLfloat *params )
  785. {
  786.    GET_CURRENT_CONTEXT(ctx);
  787.    GLuint f;
  788.    GLfloat (*mat)[4] = ctx->Light.Material.Attrib;
  789.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* update materials */
  790.  
  791.    FLUSH_CURRENT(ctx, 0); /* update ctx->Light.Material from vertex buffer */
  792.  
  793.    if (face==GL_FRONT) {
  794.       f = 0;
  795.    }
  796.    else if (face==GL_BACK) {
  797.       f = 1;
  798.    }
  799.    else {
  800.       _mesa_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(face)" );
  801.       return;
  802.    }
  803.  
  804.    switch (pname) {
  805.       case GL_AMBIENT:
  806.          COPY_4FV( params, mat[MAT_ATTRIB_AMBIENT(f)] );
  807.          break;
  808.       case GL_DIFFUSE:
  809.          COPY_4FV( params, mat[MAT_ATTRIB_DIFFUSE(f)] );
  810.          break;
  811.       case GL_SPECULAR:
  812.          COPY_4FV( params, mat[MAT_ATTRIB_SPECULAR(f)] );
  813.          break;
  814.       case GL_EMISSION:
  815.          COPY_4FV( params, mat[MAT_ATTRIB_EMISSION(f)] );
  816.          break;
  817.       case GL_SHININESS:
  818.          *params = mat[MAT_ATTRIB_SHININESS(f)][0];
  819.          break;
  820.       case GL_COLOR_INDEXES:
  821.          params[0] = mat[MAT_ATTRIB_INDEXES(f)][0];
  822.          params[1] = mat[MAT_ATTRIB_INDEXES(f)][1];
  823.          params[2] = mat[MAT_ATTRIB_INDEXES(f)][2];
  824.          break;
  825.       default:
  826.          _mesa_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(pname)" );
  827.    }
  828. }
  829.  
  830.  
  831. void GLAPIENTRY
  832. _mesa_GetMaterialiv( GLenum face, GLenum pname, GLint *params )
  833. {
  834.    GET_CURRENT_CONTEXT(ctx);
  835.    GLuint f;
  836.    GLfloat (*mat)[4] = ctx->Light.Material.Attrib;
  837.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* update materials */
  838.  
  839.    FLUSH_CURRENT(ctx, 0); /* update ctx->Light.Material from vertex buffer */
  840.  
  841.    if (face==GL_FRONT) {
  842.       f = 0;
  843.    }
  844.    else if (face==GL_BACK) {
  845.       f = 1;
  846.    }
  847.    else {
  848.       _mesa_error( ctx, GL_INVALID_ENUM, "glGetMaterialiv(face)" );
  849.       return;
  850.    }
  851.    switch (pname) {
  852.       case GL_AMBIENT:
  853.          params[0] = FLOAT_TO_INT( mat[MAT_ATTRIB_AMBIENT(f)][0] );
  854.          params[1] = FLOAT_TO_INT( mat[MAT_ATTRIB_AMBIENT(f)][1] );
  855.          params[2] = FLOAT_TO_INT( mat[MAT_ATTRIB_AMBIENT(f)][2] );
  856.          params[3] = FLOAT_TO_INT( mat[MAT_ATTRIB_AMBIENT(f)][3] );
  857.          break;
  858.       case GL_DIFFUSE:
  859.          params[0] = FLOAT_TO_INT( mat[MAT_ATTRIB_DIFFUSE(f)][0] );
  860.          params[1] = FLOAT_TO_INT( mat[MAT_ATTRIB_DIFFUSE(f)][1] );
  861.          params[2] = FLOAT_TO_INT( mat[MAT_ATTRIB_DIFFUSE(f)][2] );
  862.          params[3] = FLOAT_TO_INT( mat[MAT_ATTRIB_DIFFUSE(f)][3] );
  863.          break;
  864.       case GL_SPECULAR:
  865.          params[0] = FLOAT_TO_INT( mat[MAT_ATTRIB_SPECULAR(f)][0] );
  866.          params[1] = FLOAT_TO_INT( mat[MAT_ATTRIB_SPECULAR(f)][1] );
  867.          params[2] = FLOAT_TO_INT( mat[MAT_ATTRIB_SPECULAR(f)][2] );
  868.          params[3] = FLOAT_TO_INT( mat[MAT_ATTRIB_SPECULAR(f)][3] );
  869.          break;
  870.       case GL_EMISSION:
  871.          params[0] = FLOAT_TO_INT( mat[MAT_ATTRIB_EMISSION(f)][0] );
  872.          params[1] = FLOAT_TO_INT( mat[MAT_ATTRIB_EMISSION(f)][1] );
  873.          params[2] = FLOAT_TO_INT( mat[MAT_ATTRIB_EMISSION(f)][2] );
  874.          params[3] = FLOAT_TO_INT( mat[MAT_ATTRIB_EMISSION(f)][3] );
  875.          break;
  876.       case GL_SHININESS:
  877.          *params = IROUND( mat[MAT_ATTRIB_SHININESS(f)][0] );
  878.          break;
  879.       case GL_COLOR_INDEXES:
  880.          params[0] = IROUND( mat[MAT_ATTRIB_INDEXES(f)][0] );
  881.          params[1] = IROUND( mat[MAT_ATTRIB_INDEXES(f)][1] );
  882.          params[2] = IROUND( mat[MAT_ATTRIB_INDEXES(f)][2] );
  883.          break;
  884.       default:
  885.          _mesa_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(pname)" );
  886.    }
  887. }
  888.  
  889.  
  890.  
  891. /**********************************************************************/
  892. /*****                  Lighting computation                      *****/
  893. /**********************************************************************/
  894.  
  895.  
  896. /*
  897.  * Notes:
  898.  *   When two-sided lighting is enabled we compute the color (or index)
  899.  *   for both the front and back side of the primitive.  Then, when the
  900.  *   orientation of the facet is later learned, we can determine which
  901.  *   color (or index) to use for rendering.
  902.  *
  903.  *   KW: We now know orientation in advance and only shade for
  904.  *       the side or sides which are actually required.
  905.  *
  906.  * Variables:
  907.  *   n = normal vector
  908.  *   V = vertex position
  909.  *   P = light source position
  910.  *   Pe = (0,0,0,1)
  911.  *
  912.  * Precomputed:
  913.  *   IF P[3]==0 THEN
  914.  *       // light at infinity
  915.  *       IF local_viewer THEN
  916.  *           _VP_inf_norm = unit vector from V to P      // Precompute
  917.  *       ELSE
  918.  *           // eye at infinity
  919.  *           _h_inf_norm = Normalize( VP + <0,0,1> )     // Precompute
  920.  *       ENDIF
  921.  *   ENDIF
  922.  *
  923.  * Functions:
  924.  *   Normalize( v ) = normalized vector v
  925.  *   Magnitude( v ) = length of vector v
  926.  */
  927.  
  928.  
  929.  
  930. /*
  931.  * Whenever the spotlight exponent for a light changes we must call
  932.  * this function to recompute the exponent lookup table.
  933.  */
  934. void
  935. _mesa_invalidate_spot_exp_table( struct gl_light *l )
  936. {
  937.    l->_SpotExpTable[0][0] = -1;
  938. }
  939.  
  940.  
  941. static void
  942. validate_spot_exp_table( struct gl_light *l )
  943. {
  944.    GLint i;
  945.    GLdouble exponent = l->SpotExponent;
  946.    GLdouble tmp = 0;
  947.    GLint clamp = 0;
  948.  
  949.    l->_SpotExpTable[0][0] = 0.0;
  950.  
  951.    for (i = EXP_TABLE_SIZE - 1; i > 0 ;i--) {
  952.       if (clamp == 0) {
  953.          tmp = pow(i / (GLdouble) (EXP_TABLE_SIZE - 1), exponent);
  954.          if (tmp < FLT_MIN * 100.0) {
  955.             tmp = 0.0;
  956.             clamp = 1;
  957.          }
  958.       }
  959.       l->_SpotExpTable[i][0] = (GLfloat) tmp;
  960.    }
  961.    for (i = 0; i < EXP_TABLE_SIZE - 1; i++) {
  962.       l->_SpotExpTable[i][1] = (l->_SpotExpTable[i+1][0] -
  963.                                 l->_SpotExpTable[i][0]);
  964.    }
  965.    l->_SpotExpTable[EXP_TABLE_SIZE-1][1] = 0.0;
  966. }
  967.  
  968.  
  969.  
  970. /* Calculate a new shine table.  Doing this here saves a branch in
  971.  * lighting, and the cost of doing it early may be partially offset
  972.  * by keeping a MRU cache of shine tables for various shine values.
  973.  */
  974. void
  975. _mesa_invalidate_shine_table( struct gl_context *ctx, GLuint side )
  976. {
  977.    ASSERT(side < 2);
  978.    if (ctx->_ShineTable[side])
  979.       ctx->_ShineTable[side]->refcount--;
  980.    ctx->_ShineTable[side] = NULL;
  981. }
  982.  
  983.  
  984. static void
  985. validate_shine_table( struct gl_context *ctx, GLuint side, GLfloat shininess )
  986. {
  987.    struct gl_shine_tab *list = ctx->_ShineTabList;
  988.    struct gl_shine_tab *s;
  989.  
  990.    ASSERT(side < 2);
  991.  
  992.    foreach(s, list)
  993.       if ( s->shininess == shininess )
  994.          break;
  995.  
  996.    if (s == list) {
  997.       GLint j;
  998.       GLfloat *m;
  999.  
  1000.       foreach(s, list)
  1001.          if (s->refcount == 0)
  1002.             break;
  1003.  
  1004.       m = s->tab;
  1005.       m[0] = 0.0;
  1006.       if (shininess == 0.0) {
  1007.          for (j = 1 ; j <= SHINE_TABLE_SIZE ; j++)
  1008.             m[j] = 1.0;
  1009.       }
  1010.       else {
  1011.          for (j = 1 ; j < SHINE_TABLE_SIZE ; j++) {
  1012.             GLdouble t, x = j / (GLfloat) (SHINE_TABLE_SIZE - 1);
  1013.             if (x < 0.005) /* underflow check */
  1014.                x = 0.005;
  1015.             t = pow(x, shininess);
  1016.             if (t > 1e-20)
  1017.                m[j] = (GLfloat) t;
  1018.             else
  1019.                m[j] = 0.0;
  1020.          }
  1021.          m[SHINE_TABLE_SIZE] = 1.0;
  1022.       }
  1023.  
  1024.       s->shininess = shininess;
  1025.    }
  1026.  
  1027.    if (ctx->_ShineTable[side])
  1028.       ctx->_ShineTable[side]->refcount--;
  1029.  
  1030.    ctx->_ShineTable[side] = s;
  1031.    move_to_tail( list, s );
  1032.    s->refcount++;
  1033. }
  1034.  
  1035.  
  1036. void
  1037. _mesa_validate_all_lighting_tables( struct gl_context *ctx )
  1038. {
  1039.    GLuint i;
  1040.    GLfloat shininess;
  1041.    
  1042.    shininess = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SHININESS][0];
  1043.    if (!ctx->_ShineTable[0] || ctx->_ShineTable[0]->shininess != shininess)
  1044.       validate_shine_table( ctx, 0, shininess );
  1045.  
  1046.    shininess = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_SHININESS][0];
  1047.    if (!ctx->_ShineTable[1] || ctx->_ShineTable[1]->shininess != shininess)
  1048.       validate_shine_table( ctx, 1, shininess );
  1049.  
  1050.    for (i = 0; i < ctx->Const.MaxLights; i++)
  1051.       if (ctx->Light.Light[i]._SpotExpTable[0][0] == -1)
  1052.          validate_spot_exp_table( &ctx->Light.Light[i] );
  1053. }
  1054.  
  1055.  
  1056. /**
  1057.  * Examine current lighting parameters to determine if the optimized lighting
  1058.  * function can be used.
  1059.  * Also, precompute some lighting values such as the products of light
  1060.  * source and material ambient, diffuse and specular coefficients.
  1061.  */
  1062. void
  1063. _mesa_update_lighting( struct gl_context *ctx )
  1064. {
  1065.    struct gl_light *light;
  1066.    ctx->Light._NeedEyeCoords = GL_FALSE;
  1067.    ctx->Light._Flags = 0;
  1068.  
  1069.    if (!ctx->Light.Enabled)
  1070.       return;
  1071.  
  1072.    foreach(light, &ctx->Light.EnabledList) {
  1073.       ctx->Light._Flags |= light->_Flags;
  1074.    }
  1075.  
  1076.    ctx->Light._NeedVertices =
  1077.       ((ctx->Light._Flags & (LIGHT_POSITIONAL|LIGHT_SPOT)) ||
  1078.        ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR ||
  1079.        ctx->Light.Model.LocalViewer);
  1080.  
  1081.    ctx->Light._NeedEyeCoords = ((ctx->Light._Flags & LIGHT_POSITIONAL) ||
  1082.                                 ctx->Light.Model.LocalViewer);
  1083.  
  1084.    /* XXX: This test is overkill & needs to be fixed both for software and
  1085.     * hardware t&l drivers.  The above should be sufficient & should
  1086.     * be tested to verify this.
  1087.     */
  1088.    if (ctx->Light._NeedVertices)
  1089.       ctx->Light._NeedEyeCoords = GL_TRUE;
  1090.  
  1091.    /* Precompute some shading values.  Although we reference
  1092.     * Light.Material here, we can get away without flushing
  1093.     * FLUSH_UPDATE_CURRENT, as when any outstanding material changes
  1094.     * are flushed, they will update the derived state at that time.
  1095.     */
  1096.    if (ctx->Light.Model.TwoSide)
  1097.       _mesa_update_material(ctx,
  1098.                             MAT_BIT_FRONT_EMISSION |
  1099.                             MAT_BIT_FRONT_AMBIENT |
  1100.                             MAT_BIT_FRONT_DIFFUSE |
  1101.                             MAT_BIT_FRONT_SPECULAR |
  1102.                             MAT_BIT_BACK_EMISSION |
  1103.                             MAT_BIT_BACK_AMBIENT |
  1104.                             MAT_BIT_BACK_DIFFUSE |
  1105.                             MAT_BIT_BACK_SPECULAR);
  1106.    else
  1107.       _mesa_update_material(ctx,
  1108.                             MAT_BIT_FRONT_EMISSION |
  1109.                             MAT_BIT_FRONT_AMBIENT |
  1110.                             MAT_BIT_FRONT_DIFFUSE |
  1111.                             MAT_BIT_FRONT_SPECULAR);
  1112. }
  1113.  
  1114.  
  1115. /**
  1116.  * Update state derived from light position, spot direction.
  1117.  * Called upon:
  1118.  *   _NEW_MODELVIEW
  1119.  *   _NEW_LIGHT
  1120.  *   _TNL_NEW_NEED_EYE_COORDS
  1121.  *
  1122.  * Update on (_NEW_MODELVIEW | _NEW_LIGHT) when lighting is enabled.
  1123.  * Also update on lighting space changes.
  1124.  */
  1125. static void
  1126. compute_light_positions( struct gl_context *ctx )
  1127. {
  1128.    struct gl_light *light;
  1129.    static const GLfloat eye_z[3] = { 0, 0, 1 };
  1130.  
  1131.    if (!ctx->Light.Enabled)
  1132.       return;
  1133.  
  1134.    if (ctx->_NeedEyeCoords) {
  1135.       COPY_3V( ctx->_EyeZDir, eye_z );
  1136.    }
  1137.    else {
  1138.       TRANSFORM_NORMAL( ctx->_EyeZDir, eye_z, ctx->ModelviewMatrixStack.Top->m );
  1139.    }
  1140.  
  1141.    foreach (light, &ctx->Light.EnabledList) {
  1142.  
  1143.       if (ctx->_NeedEyeCoords) {
  1144.          /* _Position is in eye coordinate space */
  1145.          COPY_4FV( light->_Position, light->EyePosition );
  1146.       }
  1147.       else {
  1148.          /* _Position is in object coordinate space */
  1149.          TRANSFORM_POINT( light->_Position, ctx->ModelviewMatrixStack.Top->inv,
  1150.                           light->EyePosition );
  1151.       }
  1152.  
  1153.       if (!(light->_Flags & LIGHT_POSITIONAL)) {
  1154.          /* VP (VP) = Normalize( Position ) */
  1155.          COPY_3V( light->_VP_inf_norm, light->_Position );
  1156.          NORMALIZE_3FV( light->_VP_inf_norm );
  1157.  
  1158.          if (!ctx->Light.Model.LocalViewer) {
  1159.             /* _h_inf_norm = Normalize( V_to_P + <0,0,1> ) */
  1160.             ADD_3V( light->_h_inf_norm, light->_VP_inf_norm, ctx->_EyeZDir);
  1161.             NORMALIZE_3FV( light->_h_inf_norm );
  1162.          }
  1163.          light->_VP_inf_spot_attenuation = 1.0;
  1164.       }
  1165.       else {
  1166.          /* positional light w/ homogeneous coordinate, divide by W */
  1167.          GLfloat wInv = (GLfloat)1.0 / light->_Position[3];
  1168.          light->_Position[0] *= wInv;
  1169.          light->_Position[1] *= wInv;
  1170.          light->_Position[2] *= wInv;
  1171.       }
  1172.  
  1173.       if (light->_Flags & LIGHT_SPOT) {
  1174.          /* Note: we normalize the spot direction now */
  1175.  
  1176.          if (ctx->_NeedEyeCoords) {
  1177.             COPY_3V( light->_NormSpotDirection, light->SpotDirection );
  1178.             NORMALIZE_3FV( light->_NormSpotDirection );
  1179.          }
  1180.          else {
  1181.             GLfloat spotDir[3];
  1182.             COPY_3V(spotDir, light->SpotDirection);
  1183.             NORMALIZE_3FV(spotDir);
  1184.             TRANSFORM_NORMAL( light->_NormSpotDirection,
  1185.                               spotDir,
  1186.                               ctx->ModelviewMatrixStack.Top->m);
  1187.          }
  1188.  
  1189.          NORMALIZE_3FV( light->_NormSpotDirection );
  1190.  
  1191.          if (!(light->_Flags & LIGHT_POSITIONAL)) {
  1192.             GLfloat PV_dot_dir = - DOT3(light->_VP_inf_norm,
  1193.                                         light->_NormSpotDirection);
  1194.  
  1195.             if (PV_dot_dir > light->_CosCutoff) {
  1196.                double x = PV_dot_dir * (EXP_TABLE_SIZE-1);
  1197.                int k = (int) x;
  1198.                light->_VP_inf_spot_attenuation =
  1199.                   (GLfloat) (light->_SpotExpTable[k][0] +
  1200.                    (x-k)*light->_SpotExpTable[k][1]);
  1201.             }
  1202.             else {
  1203.                light->_VP_inf_spot_attenuation = 0;
  1204.             }
  1205.          }
  1206.       }
  1207.    }
  1208. }
  1209.  
  1210.  
  1211.  
  1212. static void
  1213. update_modelview_scale( struct gl_context *ctx )
  1214. {
  1215.    ctx->_ModelViewInvScale = 1.0F;
  1216.    if (!_math_matrix_is_length_preserving(ctx->ModelviewMatrixStack.Top)) {
  1217.       const GLfloat *m = ctx->ModelviewMatrixStack.Top->inv;
  1218.       GLfloat f = m[2] * m[2] + m[6] * m[6] + m[10] * m[10];
  1219.       if (f < 1e-12) f = 1.0;
  1220.       if (ctx->_NeedEyeCoords)
  1221.          ctx->_ModelViewInvScale = (GLfloat) INV_SQRTF(f);
  1222.       else
  1223.          ctx->_ModelViewInvScale = (GLfloat) SQRTF(f);
  1224.    }
  1225. }
  1226.  
  1227.  
  1228. /**
  1229.  * Bring up to date any state that relies on _NeedEyeCoords.
  1230.  */
  1231. void
  1232. _mesa_update_tnl_spaces( struct gl_context *ctx, GLuint new_state )
  1233. {
  1234.    const GLuint oldneedeyecoords = ctx->_NeedEyeCoords;
  1235.  
  1236.    (void) new_state;
  1237.    ctx->_NeedEyeCoords = GL_FALSE;
  1238.  
  1239.    if (ctx->_ForceEyeCoords ||
  1240.        (ctx->Texture._GenFlags & TEXGEN_NEED_EYE_COORD) ||
  1241.        ctx->Point._Attenuated ||
  1242.        ctx->Light._NeedEyeCoords)
  1243.       ctx->_NeedEyeCoords = GL_TRUE;
  1244.  
  1245.    if (ctx->Light.Enabled &&
  1246.        !_math_matrix_is_length_preserving(ctx->ModelviewMatrixStack.Top))
  1247.       ctx->_NeedEyeCoords = GL_TRUE;
  1248.  
  1249.    /* Check if the truth-value interpretations of the bitfields have
  1250.     * changed:
  1251.     */
  1252.    if (oldneedeyecoords != ctx->_NeedEyeCoords) {
  1253.       /* Recalculate all state that depends on _NeedEyeCoords.
  1254.        */
  1255.       update_modelview_scale(ctx);
  1256.       compute_light_positions( ctx );
  1257.  
  1258.       if (ctx->Driver.LightingSpaceChange)
  1259.          ctx->Driver.LightingSpaceChange( ctx );
  1260.    }
  1261.    else {
  1262.       GLuint new_state2 = ctx->NewState;
  1263.  
  1264.       /* Recalculate that same state only if it has been invalidated
  1265.        * by other statechanges.
  1266.        */
  1267.       if (new_state2 & _NEW_MODELVIEW)
  1268.          update_modelview_scale(ctx);
  1269.  
  1270.       if (new_state2 & (_NEW_LIGHT|_NEW_MODELVIEW))
  1271.          compute_light_positions( ctx );
  1272.    }
  1273. }
  1274.  
  1275.  
  1276. /**
  1277.  * Drivers may need this if the hardware tnl unit doesn't support the
  1278.  * light-in-modelspace optimization.  It's also useful for debugging.
  1279.  */
  1280. void
  1281. _mesa_allow_light_in_model( struct gl_context *ctx, GLboolean flag )
  1282. {
  1283.    ctx->_ForceEyeCoords = !flag;
  1284.    ctx->NewState |= _NEW_POINT; /* one of the bits from
  1285.                                  * _MESA_NEW_NEED_EYE_COORDS.
  1286.                                  */
  1287. }
  1288.  
  1289.  
  1290.  
  1291. /**********************************************************************/
  1292. /*****                      Initialization                        *****/
  1293. /**********************************************************************/
  1294.  
  1295. /**
  1296.  * Initialize the n-th light data structure.
  1297.  *
  1298.  * \param l pointer to the gl_light structure to be initialized.
  1299.  * \param n number of the light.
  1300.  * \note The defaults for light 0 are different than the other lights.
  1301.  */
  1302. static void
  1303. init_light( struct gl_light *l, GLuint n )
  1304. {
  1305.    make_empty_list( l );
  1306.  
  1307.    ASSIGN_4V( l->Ambient, 0.0, 0.0, 0.0, 1.0 );
  1308.    if (n==0) {
  1309.       ASSIGN_4V( l->Diffuse, 1.0, 1.0, 1.0, 1.0 );
  1310.       ASSIGN_4V( l->Specular, 1.0, 1.0, 1.0, 1.0 );
  1311.    }
  1312.    else {
  1313.       ASSIGN_4V( l->Diffuse, 0.0, 0.0, 0.0, 1.0 );
  1314.       ASSIGN_4V( l->Specular, 0.0, 0.0, 0.0, 1.0 );
  1315.    }
  1316.    ASSIGN_4V( l->EyePosition, 0.0, 0.0, 1.0, 0.0 );
  1317.    ASSIGN_3V( l->SpotDirection, 0.0, 0.0, -1.0 );
  1318.    l->SpotExponent = 0.0;
  1319.    _mesa_invalidate_spot_exp_table( l );
  1320.    l->SpotCutoff = 180.0;
  1321.    l->_CosCutoffNeg = -1.0f;
  1322.    l->_CosCutoff = 0.0;         /* KW: -ve values not admitted */
  1323.    l->ConstantAttenuation = 1.0;
  1324.    l->LinearAttenuation = 0.0;
  1325.    l->QuadraticAttenuation = 0.0;
  1326.    l->Enabled = GL_FALSE;
  1327. }
  1328.  
  1329.  
  1330. /**
  1331.  * Initialize the light model data structure.
  1332.  *
  1333.  * \param lm pointer to the gl_lightmodel structure to be initialized.
  1334.  */
  1335. static void
  1336. init_lightmodel( struct gl_lightmodel *lm )
  1337. {
  1338.    ASSIGN_4V( lm->Ambient, 0.2F, 0.2F, 0.2F, 1.0F );
  1339.    lm->LocalViewer = GL_FALSE;
  1340.    lm->TwoSide = GL_FALSE;
  1341.    lm->ColorControl = GL_SINGLE_COLOR;
  1342. }
  1343.  
  1344.  
  1345. /**
  1346.  * Initialize the material data structure.
  1347.  *
  1348.  * \param m pointer to the gl_material structure to be initialized.
  1349.  */
  1350. static void
  1351. init_material( struct gl_material *m )
  1352. {
  1353.    ASSIGN_4V( m->Attrib[MAT_ATTRIB_FRONT_AMBIENT],  0.2F, 0.2F, 0.2F, 1.0F );
  1354.    ASSIGN_4V( m->Attrib[MAT_ATTRIB_FRONT_DIFFUSE],  0.8F, 0.8F, 0.8F, 1.0F );
  1355.    ASSIGN_4V( m->Attrib[MAT_ATTRIB_FRONT_SPECULAR], 0.0F, 0.0F, 0.0F, 1.0F );
  1356.    ASSIGN_4V( m->Attrib[MAT_ATTRIB_FRONT_EMISSION], 0.0F, 0.0F, 0.0F, 1.0F );
  1357.    ASSIGN_4V( m->Attrib[MAT_ATTRIB_FRONT_SHININESS], 0.0F, 0.0F, 0.0F, 0.0F );
  1358.    ASSIGN_4V( m->Attrib[MAT_ATTRIB_FRONT_INDEXES], 0.0F, 1.0F, 1.0F, 0.0F );
  1359.  
  1360.    ASSIGN_4V( m->Attrib[MAT_ATTRIB_BACK_AMBIENT],  0.2F, 0.2F, 0.2F, 1.0F );
  1361.    ASSIGN_4V( m->Attrib[MAT_ATTRIB_BACK_DIFFUSE],  0.8F, 0.8F, 0.8F, 1.0F );
  1362.    ASSIGN_4V( m->Attrib[MAT_ATTRIB_BACK_SPECULAR], 0.0F, 0.0F, 0.0F, 1.0F );
  1363.    ASSIGN_4V( m->Attrib[MAT_ATTRIB_BACK_EMISSION], 0.0F, 0.0F, 0.0F, 1.0F );
  1364.    ASSIGN_4V( m->Attrib[MAT_ATTRIB_BACK_SHININESS], 0.0F, 0.0F, 0.0F, 0.0F );
  1365.    ASSIGN_4V( m->Attrib[MAT_ATTRIB_BACK_INDEXES], 0.0F, 1.0F, 1.0F, 0.0F );
  1366. }
  1367.  
  1368.  
  1369. /**
  1370.  * Initialize all lighting state for the given context.
  1371.  */
  1372. void
  1373. _mesa_init_lighting( struct gl_context *ctx )
  1374. {
  1375.    GLuint i;
  1376.  
  1377.    /* Lighting group */
  1378.    for (i = 0; i < MAX_LIGHTS; i++) {
  1379.       init_light( &ctx->Light.Light[i], i );
  1380.    }
  1381.    make_empty_list( &ctx->Light.EnabledList );
  1382.  
  1383.    init_lightmodel( &ctx->Light.Model );
  1384.    init_material( &ctx->Light.Material );
  1385.    ctx->Light.ShadeModel = GL_SMOOTH;
  1386.    ctx->Light.ProvokingVertex = GL_LAST_VERTEX_CONVENTION_EXT;
  1387.    ctx->Light.Enabled = GL_FALSE;
  1388.    ctx->Light.ColorMaterialFace = GL_FRONT_AND_BACK;
  1389.    ctx->Light.ColorMaterialMode = GL_AMBIENT_AND_DIFFUSE;
  1390.    ctx->Light.ColorMaterialBitmask = _mesa_material_bitmask( ctx,
  1391.                                                GL_FRONT_AND_BACK,
  1392.                                                GL_AMBIENT_AND_DIFFUSE, ~0,
  1393.                                                NULL );
  1394.  
  1395.    ctx->Light.ColorMaterialEnabled = GL_FALSE;
  1396.    ctx->Light.ClampVertexColor = GL_TRUE;
  1397.  
  1398.    /* Lighting miscellaneous */
  1399.    ctx->_ShineTabList = MALLOC_STRUCT( gl_shine_tab );
  1400.    make_empty_list( ctx->_ShineTabList );
  1401.    /* Allocate 10 (arbitrary) shininess lookup tables */
  1402.    for (i = 0 ; i < 10 ; i++) {
  1403.       struct gl_shine_tab *s = MALLOC_STRUCT( gl_shine_tab );
  1404.       s->shininess = -1;
  1405.       s->refcount = 0;
  1406.       insert_at_tail( ctx->_ShineTabList, s );
  1407.    }
  1408.  
  1409.    /* Miscellaneous */
  1410.    ctx->Light._NeedEyeCoords = GL_FALSE;
  1411.    ctx->_NeedEyeCoords = GL_FALSE;
  1412.    ctx->_ForceEyeCoords = GL_FALSE;
  1413.    ctx->_ModelViewInvScale = 1.0;
  1414. }
  1415.  
  1416.  
  1417. /**
  1418.  * Deallocate malloc'd lighting state attached to given context.
  1419.  */
  1420. void
  1421. _mesa_free_lighting_data( struct gl_context *ctx )
  1422. {
  1423.    struct gl_shine_tab *s, *tmps;
  1424.  
  1425.    /* Free lighting shininess exponentiation table */
  1426.    foreach_s( s, tmps, ctx->_ShineTabList ) {
  1427.       free( s );
  1428.    }
  1429.    free( ctx->_ShineTabList );
  1430. }
  1431.