Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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