mesa: fix signed/unsigned sscanf() warning in _mesa_override_glsl_version()
[mesa.git] / src / mesa / main / light.c
index 0af647e13c04bf0584b8295c625a0518ebbfd6e3..c27cf1dd38b0a44661506c0037478426c4aea82c 100644 (file)
@@ -1,8 +1,9 @@
 /*
  * Mesa 3-D graphics library
- * Version:  7.0
+ * Version:  7.5
  *
- * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
+ * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -53,11 +54,47 @@ _mesa_ShadeModel( GLenum mode )
 
    FLUSH_VERTICES(ctx, _NEW_LIGHT);
    ctx->Light.ShadeModel = mode;
+   if (mode == GL_FLAT)
+      ctx->_TriangleCaps |= DD_FLATSHADE;
+   else
+      ctx->_TriangleCaps &= ~DD_FLATSHADE;
+
    if (ctx->Driver.ShadeModel)
       ctx->Driver.ShadeModel( ctx, mode );
 }
 
 
+/**
+ * Set the provoking vertex (the vertex which specifies the prim's
+ * color when flat shading) to either the first or last vertex of the
+ * triangle or line.
+ */
+void GLAPIENTRY
+_mesa_ProvokingVertexEXT(GLenum mode)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (MESA_VERBOSE&VERBOSE_API)
+      _mesa_debug(ctx, "glProvokingVertexEXT 0x%x\n", mode);
+
+   switch (mode) {
+   case GL_FIRST_VERTEX_CONVENTION_EXT:
+   case GL_LAST_VERTEX_CONVENTION_EXT:
+      break;
+   default:
+      _mesa_error(ctx, GL_INVALID_ENUM, "glProvokingVertexEXT(0x%x)", mode);
+      return;
+   }
+
+   if (ctx->Light.ProvokingVertex == mode)
+      return;
+
+   FLUSH_VERTICES(ctx, _NEW_LIGHT);
+   ctx->Light.ProvokingVertex = mode;
+}
+
+
 /**
  * Helper function called by _mesa_Lightfv and _mesa_PopAttrib to set
  * per-light state.
@@ -66,7 +103,7 @@ _mesa_ShadeModel( GLenum mode )
  * Also, all error checking should have already been done.
  */
 void
-_mesa_light(GLcontext *ctx, GLuint lnum, GLenum pname, const GLfloat *params)
+_mesa_light(struct gl_context *ctx, GLuint lnum, GLenum pname, const GLfloat *params)
 {
    struct gl_light *light;
 
@@ -105,10 +142,10 @@ _mesa_light(GLcontext *ctx, GLuint lnum, GLenum pname, const GLfloat *params)
       break;
    case GL_SPOT_DIRECTION:
       /* NOTE: Direction already transformed by inverse ModelView! */
-      if (TEST_EQ_3V(light->EyeDirection, params))
+      if (TEST_EQ_3V(light->SpotDirection, params))
         return;
       FLUSH_VERTICES(ctx, _NEW_LIGHT);
-      COPY_3V(light->EyeDirection, params);
+      COPY_3V(light->SpotDirection, params);
       break;
    case GL_SPOT_EXPONENT:
       ASSERT(params[0] >= 0.0);
@@ -125,7 +162,7 @@ _mesa_light(GLcontext *ctx, GLuint lnum, GLenum pname, const GLfloat *params)
          return;
       FLUSH_VERTICES(ctx, _NEW_LIGHT);
       light->SpotCutoff = params[0];
-      light->_CosCutoffNeg = (GLfloat) (_mesa_cos(light->SpotCutoff * DEG2RAD));
+      light->_CosCutoffNeg = (GLfloat) (cos(light->SpotCutoff * DEG2RAD));
       if (light->_CosCutoffNeg < 0)
          light->_CosCutoff = 0;
       else
@@ -169,7 +206,10 @@ _mesa_light(GLcontext *ctx, GLuint lnum, GLenum pname, const GLfloat *params)
 void GLAPIENTRY
 _mesa_Lightf( GLenum light, GLenum pname, GLfloat param )
 {
-   _mesa_Lightfv( light, pname, &param );
+   GLfloat fparam[4];
+   fparam[0] = param;
+   fparam[1] = fparam[2] = fparam[3] = 0.0F;
+   _mesa_Lightfv( light, pname, fparam );
 }
 
 
@@ -179,6 +219,7 @@ _mesa_Lightfv( GLenum light, GLenum pname, const GLfloat *params )
    GET_CURRENT_CONTEXT(ctx);
    GLint i = (GLint) (light - GL_LIGHT0);
    GLfloat temp[4];
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    if (i < 0 || i >= (GLint) ctx->Const.MaxLights) {
       _mesa_error( ctx, GL_INVALID_ENUM, "glLight(light=0x%x)", light );
@@ -202,7 +243,7 @@ _mesa_Lightfv( GLenum light, GLenum pname, const GLfloat *params )
       if (_math_matrix_is_dirty(ctx->ModelviewMatrixStack.Top)) {
         _math_matrix_analyse(ctx->ModelviewMatrixStack.Top);
       }
-      TRANSFORM_NORMAL(temp, params, ctx->ModelviewMatrixStack.Top->inv);
+      TRANSFORM_DIRECTION(temp, params, ctx->ModelviewMatrixStack.Top->m);
       params = temp;
       break;
    case GL_SPOT_EXPONENT:
@@ -247,7 +288,10 @@ _mesa_Lightfv( GLenum light, GLenum pname, const GLfloat *params )
 void GLAPIENTRY
 _mesa_Lighti( GLenum light, GLenum pname, GLint param )
 {
-   _mesa_Lightiv( light, pname, &param );
+   GLint iparam[4];
+   iparam[0] = param;
+   iparam[1] = iparam[2] = iparam[3] = 0;
+   _mesa_Lightiv( light, pname, iparam );
 }
 
 
@@ -319,7 +363,7 @@ _mesa_GetLightfv( GLenum light, GLenum pname, GLfloat *params )
          COPY_4V( params, ctx->Light.Light[l].EyePosition );
          break;
       case GL_SPOT_DIRECTION:
-         COPY_3V( params, ctx->Light.Light[l].EyeDirection );
+         COPY_3V( params, ctx->Light.Light[l].SpotDirection );
          break;
       case GL_SPOT_EXPONENT:
          params[0] = ctx->Light.Light[l].SpotExponent;
@@ -381,9 +425,9 @@ _mesa_GetLightiv( GLenum light, GLenum pname, GLint *params )
          params[3] = (GLint) ctx->Light.Light[l].EyePosition[3];
          break;
       case GL_SPOT_DIRECTION:
-         params[0] = (GLint) ctx->Light.Light[l].EyeDirection[0];
-         params[1] = (GLint) ctx->Light.Light[l].EyeDirection[1];
-         params[2] = (GLint) ctx->Light.Light[l].EyeDirection[2];
+         params[0] = (GLint) ctx->Light.Light[l].SpotDirection[0];
+         params[1] = (GLint) ctx->Light.Light[l].SpotDirection[1];
+         params[2] = (GLint) ctx->Light.Light[l].SpotDirection[2];
          break;
       case GL_SPOT_EXPONENT:
          params[0] = (GLint) ctx->Light.Light[l].SpotExponent;
@@ -441,6 +485,10 @@ _mesa_LightModelfv( GLenum pname, const GLfloat *params )
            return;
         FLUSH_VERTICES(ctx, _NEW_LIGHT);
         ctx->Light.Model.TwoSide = newbool;
+         if (ctx->Light.Enabled && ctx->Light.Model.TwoSide)
+            ctx->_TriangleCaps |= DD_TRI_LIGHT_TWOSIDE;
+         else
+            ctx->_TriangleCaps &= ~DD_TRI_LIGHT_TWOSIDE;
          break;
       case GL_LIGHT_MODEL_COLOR_CONTROL:
          if (params[0] == (GLfloat) GL_SINGLE_COLOR)
@@ -486,7 +534,7 @@ _mesa_LightModeliv( GLenum pname, const GLint *params )
          break;
       default:
          /* Error will be caught later in gl_LightModelfv */
-         ;
+         ASSIGN_4V(fparam, 0.0F, 0.0F, 0.0F, 0.0F);
    }
    _mesa_LightModelfv( pname, fparam );
 }
@@ -495,14 +543,20 @@ _mesa_LightModeliv( GLenum pname, const GLint *params )
 void GLAPIENTRY
 _mesa_LightModeli( GLenum pname, GLint param )
 {
-   _mesa_LightModeliv( pname, &param );
+   GLint iparam[4];
+   iparam[0] = param;
+   iparam[1] = iparam[2] = iparam[3] = 0;
+   _mesa_LightModeliv( pname, iparam );
 }
 
 
 void GLAPIENTRY
 _mesa_LightModelf( GLenum pname, GLfloat param )
 {
-   _mesa_LightModelfv( pname, &param );
+   GLfloat fparam[4];
+   fparam[0] = param;
+   fparam[1] = fparam[2] = fparam[3] = 0.0F;
+   _mesa_LightModelfv( pname, fparam );
 }
 
 
@@ -515,7 +569,7 @@ _mesa_LightModelf( GLenum pname, GLfloat param )
  * of the targeted material values.
  */
 GLuint
-_mesa_material_bitmask( GLcontext *ctx, GLenum face, GLenum pname,
+_mesa_material_bitmask( struct gl_context *ctx, GLenum face, GLenum pname,
                         GLuint legal, const char *where )
 {
    GLuint bitmask = 0;
@@ -545,7 +599,7 @@ _mesa_material_bitmask( GLcontext *ctx, GLenum face, GLenum pname,
          bitmask |= MAT_BIT_FRONT_INDEXES  | MAT_BIT_BACK_INDEXES;
          break;
       default:
-         _mesa_error( ctx, GL_INVALID_ENUM, where );
+         _mesa_error( ctx, GL_INVALID_ENUM, "%s", where );
          return 0;
    }
 
@@ -556,12 +610,12 @@ _mesa_material_bitmask( GLcontext *ctx, GLenum face, GLenum pname,
       bitmask &= BACK_MATERIAL_BITS;
    }
    else if (face != GL_FRONT_AND_BACK) {
-      _mesa_error( ctx, GL_INVALID_ENUM, where );
+      _mesa_error( ctx, GL_INVALID_ENUM, "%s", where );
       return 0;
    }
 
    if (bitmask & ~legal) {
-      _mesa_error( ctx, GL_INVALID_ENUM, where );
+      _mesa_error( ctx, GL_INVALID_ENUM, "%s", where );
       return 0;
    }
 
@@ -589,12 +643,12 @@ _mesa_copy_materials( struct gl_material *dst,
 /* Update derived values following a change in ctx->Light.Material
  */
 void
-_mesa_update_material( GLcontext *ctx, GLuint bitmask )
+_mesa_update_material( struct gl_context *ctx, GLuint bitmask )
 {
    struct gl_light *light, *list = &ctx->Light.EnabledList;
    GLfloat (*mat)[4] = ctx->Light.Material.Attrib;
 
-   if (MESA_VERBOSE&VERBOSE_IMMEDIATE
+   if (MESA_VERBOSE & VERBOSE_MATERIAL
       _mesa_debug(ctx, "_mesa_update_material, mask 0x%x\n", bitmask);
 
    if (!bitmask)
@@ -674,7 +728,7 @@ _mesa_update_material( GLcontext *ctx, GLuint bitmask )
  * set by glColorMaterial().
  */
 void
-_mesa_update_color_material( GLcontext *ctx, const GLfloat color[4] )
+_mesa_update_color_material( struct gl_context *ctx, const GLfloat color[4] )
 {
    GLuint bitmask = ctx->Light.ColorMaterialBitmask;
    struct gl_material *mat = &ctx->Light.Material;
@@ -896,7 +950,7 @@ validate_spot_exp_table( struct gl_light *l )
 
    for (i = EXP_TABLE_SIZE - 1; i > 0 ;i--) {
       if (clamp == 0) {
-        tmp = _mesa_pow(i / (GLdouble) (EXP_TABLE_SIZE - 1), exponent);
+        tmp = pow(i / (GLdouble) (EXP_TABLE_SIZE - 1), exponent);
         if (tmp < FLT_MIN * 100.0) {
            tmp = 0.0;
            clamp = 1;
@@ -918,7 +972,7 @@ validate_spot_exp_table( struct gl_light *l )
  * by keeping a MRU cache of shine tables for various shine values.
  */
 void
-_mesa_invalidate_shine_table( GLcontext *ctx, GLuint side )
+_mesa_invalidate_shine_table( struct gl_context *ctx, GLuint side )
 {
    ASSERT(side < 2);
    if (ctx->_ShineTable[side])
@@ -928,7 +982,7 @@ _mesa_invalidate_shine_table( GLcontext *ctx, GLuint side )
 
 
 static void
-validate_shine_table( GLcontext *ctx, GLuint side, GLfloat shininess )
+validate_shine_table( struct gl_context *ctx, GLuint side, GLfloat shininess )
 {
    struct gl_shine_tab *list = ctx->_ShineTabList;
    struct gl_shine_tab *s;
@@ -958,7 +1012,7 @@ validate_shine_table( GLcontext *ctx, GLuint side, GLfloat shininess )
             GLdouble t, x = j / (GLfloat) (SHINE_TABLE_SIZE - 1);
             if (x < 0.005) /* underflow check */
                x = 0.005;
-            t = _mesa_pow(x, shininess);
+            t = pow(x, shininess);
            if (t > 1e-20)
               m[j] = (GLfloat) t;
            else
@@ -980,7 +1034,7 @@ validate_shine_table( GLcontext *ctx, GLuint side, GLfloat shininess )
 
 
 void
-_mesa_validate_all_lighting_tables( GLcontext *ctx )
+_mesa_validate_all_lighting_tables( struct gl_context *ctx )
 {
    GLuint i;
    GLfloat shininess;
@@ -1006,7 +1060,7 @@ _mesa_validate_all_lighting_tables( GLcontext *ctx )
  * source and material ambient, diffuse and specular coefficients.
  */
 void
-_mesa_update_lighting( GLcontext *ctx )
+_mesa_update_lighting( struct gl_context *ctx )
 {
    struct gl_light *light;
    ctx->Light._NeedEyeCoords = GL_FALSE;
@@ -1039,31 +1093,22 @@ _mesa_update_lighting( GLcontext *ctx )
     * FLUSH_UPDATE_CURRENT, as when any outstanding material changes
     * are flushed, they will update the derived state at that time.
     */
-   if (ctx->Visual.rgbMode) {
-      if (ctx->Light.Model.TwoSide)
-        _mesa_update_material( ctx, 
-                               MAT_BIT_FRONT_EMISSION |
-                               MAT_BIT_FRONT_AMBIENT |
-                               MAT_BIT_FRONT_DIFFUSE | 
-                               MAT_BIT_FRONT_SPECULAR |
-                               MAT_BIT_BACK_EMISSION |
-                               MAT_BIT_BACK_AMBIENT |
-                               MAT_BIT_BACK_DIFFUSE | 
-                               MAT_BIT_BACK_SPECULAR);
-      else
-        _mesa_update_material( ctx, 
-                               MAT_BIT_FRONT_EMISSION |
-                               MAT_BIT_FRONT_AMBIENT |
-                               MAT_BIT_FRONT_DIFFUSE | 
-                               MAT_BIT_FRONT_SPECULAR);
-   }
-   else {
-      static const GLfloat ci[3] = { .30F, .59F, .11F };
-      foreach(light, &ctx->Light.EnabledList) {
-        light->_dli = DOT3(ci, light->Diffuse);
-        light->_sli = DOT3(ci, light->Specular);
-      }
-   }
+   if (ctx->Light.Model.TwoSide)
+      _mesa_update_material(ctx,
+                           MAT_BIT_FRONT_EMISSION |
+                           MAT_BIT_FRONT_AMBIENT |
+                           MAT_BIT_FRONT_DIFFUSE |
+                           MAT_BIT_FRONT_SPECULAR |
+                           MAT_BIT_BACK_EMISSION |
+                           MAT_BIT_BACK_AMBIENT |
+                           MAT_BIT_BACK_DIFFUSE |
+                           MAT_BIT_BACK_SPECULAR);
+   else
+      _mesa_update_material(ctx,
+                           MAT_BIT_FRONT_EMISSION |
+                           MAT_BIT_FRONT_AMBIENT |
+                           MAT_BIT_FRONT_DIFFUSE |
+                           MAT_BIT_FRONT_SPECULAR);
 }
 
 
@@ -1078,7 +1123,7 @@ _mesa_update_lighting( GLcontext *ctx )
  * Also update on lighting space changes.
  */
 static void
-compute_light_positions( GLcontext *ctx )
+compute_light_positions( struct gl_context *ctx )
 {
    struct gl_light *light;
    static const GLfloat eye_z[3] = { 0, 0, 1 };
@@ -1119,27 +1164,33 @@ compute_light_positions( GLcontext *ctx )
       }
       else {
          /* positional light w/ homogeneous coordinate, divide by W */
-         GLfloat wInv = 1.0 / light->_Position[3];
+         GLfloat wInv = (GLfloat)1.0 / light->_Position[3];
          light->_Position[0] *= wInv;
          light->_Position[1] *= wInv;
          light->_Position[2] *= wInv;
       }
 
       if (light->_Flags & LIGHT_SPOT) {
+         /* Note: we normalize the spot direction now */
+
         if (ctx->_NeedEyeCoords) {
-           COPY_3V( light->_NormDirection, light->EyeDirection );
+           COPY_3V( light->_NormSpotDirection, light->SpotDirection );
+            NORMALIZE_3FV( light->_NormSpotDirection );
         }
          else {
-           TRANSFORM_NORMAL( light->_NormDirection,
-                             light->EyeDirection,
+            GLfloat spotDir[3];
+            COPY_3V(spotDir, light->SpotDirection);
+            NORMALIZE_3FV(spotDir);
+           TRANSFORM_NORMAL( light->_NormSpotDirection,
+                             spotDir,
                              ctx->ModelviewMatrixStack.Top->m);
         }
 
-        NORMALIZE_3FV( light->_NormDirection );
+        NORMALIZE_3FV( light->_NormSpotDirection );
 
         if (!(light->_Flags & LIGHT_POSITIONAL)) {
            GLfloat PV_dot_dir = - DOT3(light->_VP_inf_norm,
-                                       light->_NormDirection);
+                                       light->_NormSpotDirection);
 
            if (PV_dot_dir > light->_CosCutoff) {
               double x = PV_dot_dir * (EXP_TABLE_SIZE-1);
@@ -1159,7 +1210,7 @@ compute_light_positions( GLcontext *ctx )
 
 
 static void
-update_modelview_scale( GLcontext *ctx )
+update_modelview_scale( struct gl_context *ctx )
 {
    ctx->_ModelViewInvScale = 1.0F;
    if (!_math_matrix_is_length_preserving(ctx->ModelviewMatrixStack.Top)) {
@@ -1178,7 +1229,7 @@ update_modelview_scale( GLcontext *ctx )
  * Bring up to date any state that relies on _NeedEyeCoords.
  */
 void
-_mesa_update_tnl_spaces( GLcontext *ctx, GLuint new_state )
+_mesa_update_tnl_spaces( struct gl_context *ctx, GLuint new_state )
 {
    const GLuint oldneedeyecoords = ctx->_NeedEyeCoords;
 
@@ -1208,15 +1259,15 @@ _mesa_update_tnl_spaces( GLcontext *ctx, GLuint new_state )
         ctx->Driver.LightingSpaceChange( ctx );
    }
    else {
-      GLuint new_state = ctx->NewState;
+      GLuint new_state2 = ctx->NewState;
 
       /* Recalculate that same state only if it has been invalidated
        * by other statechanges.
        */
-      if (new_state & _NEW_MODELVIEW)
+      if (new_state2 & _NEW_MODELVIEW)
         update_modelview_scale(ctx);
 
-      if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW))
+      if (new_state2 & (_NEW_LIGHT|_NEW_MODELVIEW))
         compute_light_positions( ctx );
    }
 }
@@ -1227,7 +1278,7 @@ _mesa_update_tnl_spaces( GLcontext *ctx, GLuint new_state )
  * light-in-modelspace optimization.  It's also useful for debugging.
  */
 void
-_mesa_allow_light_in_model( GLcontext *ctx, GLboolean flag )
+_mesa_allow_light_in_model( struct gl_context *ctx, GLboolean flag )
 {
    ctx->_ForceEyeCoords = !flag;
    ctx->NewState |= _NEW_POINT;        /* one of the bits from
@@ -1263,7 +1314,7 @@ init_light( struct gl_light *l, GLuint n )
       ASSIGN_4V( l->Specular, 0.0, 0.0, 0.0, 1.0 );
    }
    ASSIGN_4V( l->EyePosition, 0.0, 0.0, 1.0, 0.0 );
-   ASSIGN_3V( l->EyeDirection, 0.0, 0.0, -1.0 );
+   ASSIGN_3V( l->SpotDirection, 0.0, 0.0, -1.0 );
    l->SpotExponent = 0.0;
    _mesa_invalidate_spot_exp_table( l );
    l->SpotCutoff = 180.0;
@@ -1319,7 +1370,7 @@ init_material( struct gl_material *m )
  * Initialize all lighting state for the given context.
  */
 void
-_mesa_init_lighting( GLcontext *ctx )
+_mesa_init_lighting( struct gl_context *ctx )
 {
    GLuint i;
 
@@ -1332,6 +1383,7 @@ _mesa_init_lighting( GLcontext *ctx )
    init_lightmodel( &ctx->Light.Model );
    init_material( &ctx->Light.Material );
    ctx->Light.ShadeModel = GL_SMOOTH;
+   ctx->Light.ProvokingVertex = GL_LAST_VERTEX_CONVENTION_EXT;
    ctx->Light.Enabled = GL_FALSE;
    ctx->Light.ColorMaterialFace = GL_FRONT_AND_BACK;
    ctx->Light.ColorMaterialMode = GL_AMBIENT_AND_DIFFUSE;
@@ -1357,7 +1409,7 @@ _mesa_init_lighting( GLcontext *ctx )
    /* Miscellaneous */
    ctx->Light._NeedEyeCoords = GL_FALSE;
    ctx->_NeedEyeCoords = GL_FALSE;
-   ctx->_ForceEyeCoords = GL_TRUE;
+   ctx->_ForceEyeCoords = GL_FALSE;
    ctx->_ModelViewInvScale = 1.0;
 }
 
@@ -1366,13 +1418,13 @@ _mesa_init_lighting( GLcontext *ctx )
  * Deallocate malloc'd lighting state attached to given context.
  */
 void
-_mesa_free_lighting_data( GLcontext *ctx )
+_mesa_free_lighting_data( struct gl_context *ctx )
 {
    struct gl_shine_tab *s, *tmps;
 
    /* Free lighting shininess exponentiation table */
    foreach_s( s, tmps, ctx->_ShineTabList ) {
-      _mesa_free( s );
+      free( s );
    }
-   _mesa_free( ctx->_ShineTabList );
+   free( ctx->_ShineTabList );
 }