added Window-isms previously in gl.h
[mesa.git] / src / mesa / main / light.c
index cc396f85a50d2e0ce50f893c5cb3a7464164b330..a6696b1e1ae9d4b7d08237026624b3b41f2cce99 100644 (file)
@@ -1,10 +1,10 @@
-/* $Id: light.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+/* $Id: light.c,v 1.12 2000/01/31 23:33:53 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
- * Version:  3.1
+ * Version:  3.3
  * 
- * Copyright (C) 1999  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2000  Brian Paul   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"),
  */
 
 
-
-
-
 #ifdef PC_HEADER
 #include "all.h"
 #else
-#include <assert.h>
-#include <float.h>
-#include <math.h>
-#include <stdlib.h>
-#include <stdio.h>
+#include "glheader.h"
 #include "context.h"
 #include "enums.h"
 #include "light.h"
 #include "macros.h"
 #include "matrix.h"
+#include "mem.h"
 #include "mmath.h"
 #include "simple_list.h"
 #include "types.h"
 #include "vb.h"
 #include "xform.h"
-#ifdef XFree86Server
-#include "GL/xf86glx.h"
-#endif
 #endif
 
 
+/* XXX this is a bit of a hack needed for compilation within XFree86 */
+#ifndef FLT_MIN
+#define FLT_MIN 1e-37
+#endif
+
 
-void gl_ShadeModel( GLcontext *ctx, GLenum mode )
+void
+_mesa_ShadeModel( GLenum mode )
 {
+   GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glShadeModel");
 
    if (MESA_VERBOSE & VERBOSE_API)
       fprintf(stderr, "glShadeModel %s\n", gl_lookup_enum_by_nr(mode));
 
-   switch (mode) {
-      case GL_FLAT:
-      case GL_SMOOTH:
-         if (ctx->Light.ShadeModel!=mode) {
-            ctx->Light.ShadeModel = mode;
-           ctx->TriangleCaps ^= DD_FLATSHADE;
-            ctx->NewState |= NEW_RASTER_OPS;
-         }
-         break;
-      default:
-         gl_error( ctx, GL_INVALID_ENUM, "glShadeModel" );
+   if (mode == GL_FLAT || mode == GL_SMOOTH) {
+      if (ctx->Light.ShadeModel != mode) {
+         ctx->Light.ShadeModel = mode;
+         if (ctx->Light.ShadeModel == GL_FLAT)
+            SET_BITS(ctx->TriangleCaps, DD_FLATSHADE);
+         else
+            CLEAR_BITS(ctx->TriangleCaps, DD_FLATSHADE);
+         ctx->NewState |= NEW_RASTER_OPS;
+         if (ctx->Driver.ShadeModel) 
+            (*ctx->Driver.ShadeModel)( ctx, mode );
+      }
+   }
+   else {
+      gl_error( ctx, GL_INVALID_ENUM, "glShadeModel" );
    }
-
-   if (ctx->Driver.ShadeModel) 
-      (*ctx->Driver.ShadeModel)( ctx, mode );
 }
 
 
 
-void gl_Lightfv( GLcontext *ctx,
-                 GLenum light, GLenum pname, const GLfloat *params,
-                 GLint nparams )
+void
+_mesa_Lightf( GLenum light, GLenum pname, GLfloat param )
 {
-   GLint l;
+   _mesa_Lightfv( light, pname, &param );
+}
+
 
-   (void) nparams;
+void
+_mesa_Lightfv( GLenum light, GLenum pname, const GLfloat *params )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   GLint l;
+   GLint nParams;
 
    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glLight");
 
    l = (GLint) (light - GL_LIGHT0);
 
-   if (l<0 || l>=MAX_LIGHTS) {
+   if (l < 0 || l >= MAX_LIGHTS) {
       gl_error( ctx, GL_INVALID_ENUM, "glLight" );
       return;
    }
@@ -99,18 +103,22 @@ void gl_Lightfv( GLcontext *ctx,
    switch (pname) {
       case GL_AMBIENT:
          COPY_4V( ctx->Light.Light[l].Ambient, params );
+         nParams = 4;
          break;
       case GL_DIFFUSE:
          COPY_4V( ctx->Light.Light[l].Diffuse, params );
+         nParams = 4;
          break;
       case GL_SPECULAR:
          COPY_4V( ctx->Light.Light[l].Specular, params );
+         nParams = 4;
          break;
       case GL_POSITION:
         /* transform position by ModelView matrix */
         TRANSFORM_POINT( ctx->Light.Light[l].EyePosition, 
                          ctx->ModelView.m,
                           params );
+         nParams = 4;
          break;
       case GL_SPOT_DIRECTION:
         /* transform direction by inverse modelview */
@@ -120,6 +128,7 @@ void gl_Lightfv( GLcontext *ctx,
         TRANSFORM_NORMAL( ctx->Light.Light[l].EyeDirection,
                           params,
                           ctx->ModelView.inv );
+         nParams = 3;
          break;
       case GL_SPOT_EXPONENT:
          if (params[0]<0.0 || params[0]>128.0) {
@@ -130,6 +139,7 @@ void gl_Lightfv( GLcontext *ctx,
             ctx->Light.Light[l].SpotExponent = params[0];
             gl_compute_spot_exp_table( &ctx->Light.Light[l] );
          }
+         nParams = 1;
          break;
       case GL_SPOT_CUTOFF:
          if ((params[0]<0.0 || params[0]>90.0) && params[0]!=180.0) {
@@ -140,6 +150,7 @@ void gl_Lightfv( GLcontext *ctx,
          ctx->Light.Light[l].CosCutoff = cos(params[0]*DEG2RAD);
          if (ctx->Light.Light[l].CosCutoff < 0) 
            ctx->Light.Light[l].CosCutoff = 0;
+         nParams = 1;
          break;
       case GL_CONSTANT_ATTENUATION:
          if (params[0]<0.0) {
@@ -147,6 +158,7 @@ void gl_Lightfv( GLcontext *ctx,
             return;
          }
          ctx->Light.Light[l].ConstantAttenuation = params[0];
+         nParams = 1;
          break;
       case GL_LINEAR_ATTENUATION:
          if (params[0]<0.0) {
@@ -154,6 +166,7 @@ void gl_Lightfv( GLcontext *ctx,
             return;
          }
          ctx->Light.Light[l].LinearAttenuation = params[0];
+         nParams = 1;
          break;
       case GL_QUADRATIC_ATTENUATION:
          if (params[0]<0.0) {
@@ -161,20 +174,73 @@ void gl_Lightfv( GLcontext *ctx,
             return;
          }
          ctx->Light.Light[l].QuadraticAttenuation = params[0];
+         nParams = 1;
          break;
       default:
          gl_error( ctx, GL_INVALID_ENUM, "glLight" );
-         break;
+         return;
    }
 
+   if (ctx->Driver.Lightfv)
+      ctx->Driver.Lightfv( ctx, light, pname, params, nParams );
+
    ctx->NewState |= NEW_LIGHTING;
 }
 
 
+void
+_mesa_Lighti( GLenum light, GLenum pname, GLint param )
+{
+   _mesa_Lightiv( light, pname, &param );
+}
+
+
+void
+_mesa_Lightiv( GLenum light, GLenum pname, const GLint *params )
+{
+   GLfloat fparam[4];
+
+   switch (pname) {
+      case GL_AMBIENT:
+      case GL_DIFFUSE:
+      case GL_SPECULAR:
+         fparam[0] = INT_TO_FLOAT( params[0] );
+         fparam[1] = INT_TO_FLOAT( params[1] );
+         fparam[2] = INT_TO_FLOAT( params[2] );
+         fparam[3] = INT_TO_FLOAT( params[3] );
+         break;
+      case GL_POSITION:
+         fparam[0] = (GLfloat) params[0];
+         fparam[1] = (GLfloat) params[1];
+         fparam[2] = (GLfloat) params[2];
+         fparam[3] = (GLfloat) params[3];
+         break;
+      case GL_SPOT_DIRECTION:
+         fparam[0] = (GLfloat) params[0];
+         fparam[1] = (GLfloat) params[1];
+         fparam[2] = (GLfloat) params[2];
+         break;
+      case GL_SPOT_EXPONENT:
+      case GL_SPOT_CUTOFF:
+      case GL_CONSTANT_ATTENUATION:
+      case GL_LINEAR_ATTENUATION:
+      case GL_QUADRATIC_ATTENUATION:
+         fparam[0] = (GLfloat) params[0];
+         break;
+      default:
+         /* error will be caught later in gl_Lightfv */
+         ;
+   }
+
+   _mesa_Lightfv( light, pname, fparam );
+}
+
+
 
-void gl_GetLightfv( GLcontext *ctx,
-                    GLenum light, GLenum pname, GLfloat *params )
+void
+_mesa_GetLightfv( GLenum light, GLenum pname, GLfloat *params )
 {
+   GET_CURRENT_CONTEXT(ctx);
    GLint l = (GLint) (light - GL_LIGHT0);
 
    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetLight");
@@ -223,8 +289,10 @@ void gl_GetLightfv( GLcontext *ctx,
 
 
 
-void gl_GetLightiv( GLcontext *ctx, GLenum light, GLenum pname, GLint *params )
+void
+_mesa_GetLightiv( GLenum light, GLenum pname, GLint *params )
 {
+   GET_CURRENT_CONTEXT(ctx);
    GLint l = (GLint) (light - GL_LIGHT0);
 
    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetLight");
@@ -292,9 +360,11 @@ void gl_GetLightiv( GLcontext *ctx, GLenum light, GLenum pname, GLint *params )
 /**********************************************************************/
 
 
-void gl_LightModelfv( GLcontext *ctx, GLenum pname, const GLfloat *params )
+void
+_mesa_LightModelfv( GLenum pname, const GLfloat *params )
 {
-   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glLightModel");
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glLightModelfv");
 
    switch (pname) {
       case GL_LIGHT_MODEL_AMBIENT:
@@ -313,23 +383,71 @@ void gl_LightModelfv( GLcontext *ctx, GLenum pname, const GLfloat *params )
             ctx->Light.Model.TwoSide = GL_TRUE;
          break;
       case GL_LIGHT_MODEL_COLOR_CONTROL:
-        ctx->TriangleCaps &= ~DD_SEPERATE_SPECULAR;
-         if (params[0] == (GLfloat) GL_SINGLE_COLOR) 
+         if (params[0] == (GLfloat) GL_SINGLE_COLOR) {
             ctx->Light.Model.ColorControl = GL_SINGLE_COLOR;
+            CLEAR_BITS(ctx->TriangleCaps, DD_SEPERATE_SPECULAR);
+         }
          else if (params[0] == (GLfloat) GL_SEPARATE_SPECULAR_COLOR) {
             ctx->Light.Model.ColorControl = GL_SEPARATE_SPECULAR_COLOR;
-           ctx->TriangleCaps |= DD_SEPERATE_SPECULAR;
-        } else
+           SET_BITS(ctx->TriangleCaps, DD_SEPERATE_SPECULAR);
+        }
+         else {
             gl_error( ctx, GL_INVALID_ENUM, "glLightModel(param)" );
+         }
+        ctx->NewState |= NEW_RASTER_OPS;
          break;
       default:
          gl_error( ctx, GL_INVALID_ENUM, "glLightModel" );
          break;
    }
+
+   if (ctx->Driver.LightModelfv) 
+      ctx->Driver.LightModelfv( ctx, pname, params );
+
    ctx->NewState |= NEW_LIGHTING;
 }
 
 
+void
+_mesa_LightModeliv( GLenum pname, const GLint *params )
+{
+   GLfloat fparam[4];
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glLightModeliv");
+
+   switch (pname) {
+      case GL_LIGHT_MODEL_AMBIENT:
+         fparam[0] = INT_TO_FLOAT( params[0] );
+         fparam[1] = INT_TO_FLOAT( params[1] );
+         fparam[2] = INT_TO_FLOAT( params[2] );
+         fparam[3] = INT_TO_FLOAT( params[3] );
+         break;
+      case GL_LIGHT_MODEL_LOCAL_VIEWER:
+      case GL_LIGHT_MODEL_TWO_SIDE:
+      case GL_LIGHT_MODEL_COLOR_CONTROL:
+         fparam[0] = (GLfloat) params[0];
+         break;
+      default:
+         /* Error will be caught later in gl_LightModelfv */
+         ;
+   }
+   _mesa_LightModelfv( pname, fparam );
+}
+
+
+void
+_mesa_LightModeli( GLenum pname, GLint param )
+{
+   _mesa_LightModeliv( pname, &param );
+}
+
+
+void
+_mesa_LightModelf( GLenum pname, GLfloat param )
+{
+   _mesa_LightModelfv( pname, &param );
+}
+
 
 
 /********** MATERIAL **********/
@@ -421,6 +539,9 @@ void gl_update_material( GLcontext *ctx,
    if (ctx->Light.ColorMaterialEnabled)
       bitmask &= ~ctx->Light.ColorMaterialBitmask;
 
+   if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
+      fprintf(stderr, "gl_update_material, mask %x\n", bitmask);
+
    if (!bitmask) 
       return;
 
@@ -517,6 +638,26 @@ void gl_update_material( GLcontext *ctx,
       ctx->Light.Material[1].SpecularIndex = src[1].SpecularIndex;
    }
 
+   if (0)
+   {
+      struct gl_material *mat = &ctx->Light.Material[0];
+      fprintf(stderr, "update_mat  emission : %f %f %f\n",
+             mat->Emission[0],
+             mat->Emission[1],
+             mat->Emission[2]);
+      fprintf(stderr, "update_mat  specular : %f %f %f\n",
+             mat->Specular[0],
+             mat->Specular[1],
+             mat->Specular[2]);
+      fprintf(stderr, "update_mat  diffuse : %f %f %f\n",
+             mat->Diffuse[0],
+             mat->Diffuse[1],
+             mat->Diffuse[2]);
+      fprintf(stderr, "update_mat  ambient : %f %f %f\n",
+             mat->Ambient[0],
+             mat->Ambient[1],
+             mat->Ambient[2]);
+   }
 }
 
 
@@ -533,6 +674,10 @@ void gl_update_color_material( GLcontext *ctx,
 
    UBYTE_RGBA_TO_FLOAT_RGBA( color, rgba );
    
+   if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
+      fprintf(stderr, "gl_update_color_material, mask %x\n", bitmask);
+
+
    if (bitmask & FRONT_AMBIENT_BIT) {
       struct gl_material *mat = &ctx->Light.Material[0];
       SUB_3V( tmp, color, mat->Ambient );
@@ -609,13 +754,36 @@ void gl_update_color_material( GLcontext *ctx,
       ACC_3V( ctx->Light.BaseColor[1], tmp );
       COPY_4FV( mat->Emission, color );
    }
+
+   if (0)
+   {
+      struct gl_material *mat = &ctx->Light.Material[0];
+      fprintf(stderr, "update_color_mat  emission : %f %f %f\n",
+             mat->Emission[0],
+             mat->Emission[1],
+             mat->Emission[2]);
+      fprintf(stderr, "update_color_mat  specular : %f %f %f\n",
+             mat->Specular[0],
+             mat->Specular[1],
+             mat->Specular[2]);
+      fprintf(stderr, "update_color_mat  diffuse : %f %f %f\n",
+             mat->Diffuse[0],
+             mat->Diffuse[1],
+             mat->Diffuse[2]);
+      fprintf(stderr, "update_color_mat  ambient : %f %f %f\n",
+             mat->Ambient[0],
+             mat->Ambient[1],
+             mat->Ambient[2]);
+   }
 }
 
 
 
 
-void gl_ColorMaterial( GLcontext *ctx, GLenum face, GLenum mode )
+void
+_mesa_ColorMaterial( GLenum face, GLenum mode )
 {
+   GET_CURRENT_CONTEXT(ctx);
    GLuint bitmask;
    GLuint legal = (FRONT_EMISSION_BIT | BACK_EMISSION_BIT |
                   FRONT_SPECULAR_BIT | BACK_SPECULAR_BIT |
@@ -624,6 +792,11 @@ void gl_ColorMaterial( GLcontext *ctx, GLenum face, GLenum mode )
 
    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glColorMaterial");
 
+   if (MESA_VERBOSE&VERBOSE_API) 
+      fprintf(stderr, "glColorMaterial %s %s\n", 
+             gl_lookup_enum_by_nr(face),
+             gl_lookup_enum_by_nr(mode));
+
    bitmask = gl_material_bitmask( ctx, face, mode, legal, "glColorMaterial" );
 
    if (bitmask != 0) {
@@ -631,16 +804,28 @@ void gl_ColorMaterial( GLcontext *ctx, GLenum face, GLenum mode )
       ctx->Light.ColorMaterialFace = face;
       ctx->Light.ColorMaterialMode = mode;
    }
+
+   if (ctx->Light.ColorMaterialEnabled)
+      gl_update_color_material( ctx, ctx->Current.ByteColor );
 }
 
 
 
+
+void
+_mesa_Materialf( GLenum face, GLenum pname, GLfloat param )
+{
+   _mesa_Materialfv( face, pname, &param );
+}
+
+
 /* KW:  This is now called directly (ie by name) from the glMaterial* 
  *      API functions.
  */
-void gl_Materialfv( GLcontext *ctx,
-                    GLenum face, GLenum pname, const GLfloat *params )
+void
+_mesa_Materialfv( GLenum face, GLenum pname, const GLfloat *params )
 {
+   GET_CURRENT_CONTEXT(ctx);
    struct immediate *IM;
    struct gl_material *mat;
    GLuint bitmask;
@@ -653,14 +838,22 @@ void gl_Materialfv( GLcontext *ctx,
    IM = ctx->input;
    count = IM->Count;
 
+   if (!IM->Material) {
+      IM->Material = 
+        (struct gl_material (*)[2]) MALLOC( sizeof(struct gl_material) * 
+                                            VB_SIZE * 2 );
+      IM->MaterialMask = (GLuint *) MALLOC( sizeof(GLuint) * VB_SIZE );
+   }
+
+
    if (!(IM->Flag[count] & VERT_MATERIAL)) {
       IM->Flag[count] |= VERT_MATERIAL;
-      IM->MaterialMask[count] = 0;
+      IM->MaterialMask[count] = 0;      
    }
 
+
    IM->MaterialMask[count] |= bitmask;
    mat = IM->Material[count];
-   IM->LastMaterial = count;
 
    if (bitmask & FRONT_AMBIENT_BIT) {
       COPY_4FV( mat[0].Ambient, params );
@@ -707,11 +900,48 @@ void gl_Materialfv( GLcontext *ctx,
 }
 
 
+void
+_mesa_Materiali(GLenum face, GLenum pname, GLint param )
+{
+   _mesa_Materialiv(face, pname, &param);
+}
 
 
-void gl_GetMaterialfv( GLcontext *ctx,
-                       GLenum face, GLenum pname, GLfloat *params )
+void
+_mesa_Materialiv(GLenum face, GLenum pname, const GLint *params )
 {
+   GLfloat fparam[4];
+   switch (pname) {
+      case GL_AMBIENT:
+      case GL_DIFFUSE:
+      case GL_SPECULAR:
+      case GL_EMISSION:
+      case GL_AMBIENT_AND_DIFFUSE:
+         fparam[0] = INT_TO_FLOAT( params[0] );
+         fparam[1] = INT_TO_FLOAT( params[1] );
+         fparam[2] = INT_TO_FLOAT( params[2] );
+         fparam[3] = INT_TO_FLOAT( params[3] );
+         break;
+      case GL_SHININESS:
+         fparam[0] = (GLfloat) params[0];
+         break;
+      case GL_COLOR_INDEXES:
+         fparam[0] = (GLfloat) params[0];
+         fparam[1] = (GLfloat) params[1];
+         fparam[2] = (GLfloat) params[2];
+         break;
+      default:
+         /* Error will be caught later in gl_Materialfv */
+         ;
+   }
+   _mesa_Materialfv(face, pname, fparam);
+}
+
+
+void
+_mesa_GetMaterialfv( GLenum face, GLenum pname, GLfloat *params )
+{
+   GET_CURRENT_CONTEXT(ctx);
    GLuint f;
 
    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetMaterialfv");
@@ -754,9 +984,10 @@ void gl_GetMaterialfv( GLcontext *ctx,
 
 
 
-void gl_GetMaterialiv( GLcontext *ctx,
-                       GLenum face, GLenum pname, GLint *params )
+void
+_mesa_GetMaterialiv( GLenum face, GLenum pname, GLint *params )
 {
+   GET_CURRENT_CONTEXT(ctx);
    GLuint f;
 
    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetMaterialiv");
@@ -934,8 +1165,8 @@ void gl_compute_shine_table( GLcontext *ctx, GLuint i, GLfloat shininess )
 
 
 
-
-void gl_reinit_light_attrib( GLcontext *ctx, struct gl_light_attrib *l )
+#if 0
+static void gl_reinit_light_attrib( GLcontext *ctx, struct gl_light_attrib *l )
 {
    GLuint i;
 
@@ -955,7 +1186,7 @@ void gl_reinit_light_attrib( GLcontext *ctx, struct gl_light_attrib *l )
         insert_at_tail( &l->EnabledList, &l->Light[i] );
    }
 }
-
+#endif
 
 
 /*