Fix attenuation hardware state handling, inspired by the R200 DDK reference
authorMichel Dänzer <michel@daenzer.net>
Fri, 23 Jan 2004 03:19:47 +0000 (03:19 +0000)
committerMichel Dänzer <michel@daenzer.net>
Fri, 23 Jan 2004 03:19:47 +0000 (03:19 +0000)
driver (our r200 driver basically didn't do this at all, maybe got lost
along the way?)

src/mesa/drivers/dri/r200/r200_context.h
src/mesa/drivers/dri/r200/r200_state.c
src/mesa/drivers/dri/r200/r200_state_init.c
src/mesa/drivers/dri/radeon/radeon_context.h
src/mesa/drivers/dri/radeon/radeon_state.c
src/mesa/drivers/dri/radeon/radeon_state_init.c

index 5de1cb6eedffa8868097c075f9fb7646a0bbbe4d..65ca9ef7622602dce66699ca205aca2dc8ddd7ae 100644 (file)
@@ -399,9 +399,9 @@ struct r200_state_atom {
 #define LIT_DIRECTION_Y            18
 #define LIT_DIRECTION_Z            19
 #define LIT_DIRECTION_W            20
-#define LIT_ATTEN_CONST            21
+#define LIT_ATTEN_QUADRATIC        21
 #define LIT_ATTEN_LINEAR           22
-#define LIT_ATTEN_QUADRATIC        23
+#define LIT_ATTEN_CONST            23
 #define LIT_ATTEN_XXX              24
 #define LIT_CMD_1                  25
 #define LIT_SPOT_DCD               26
@@ -410,7 +410,7 @@ struct r200_state_atom {
 #define LIT_SPOT_CUTOFF            29
 #define LIT_SPECULAR_THRESH        30
 #define LIT_RANGE_CUTOFF           31 /* ? */
-#define LIT_RANGE_ATTEN            32 /* ? */
+#define LIT_ATTEN_CONST_INV        32
 #define LIT_STATE_SIZE             33
 
 /* Fog
index 37da564986d5620cab9ca808415e768953de8275..7ea45f3d788d6ea6ed861609b4556a3da3d94267 100644 (file)
@@ -1104,6 +1104,10 @@ static void r200Lightfv( GLcontext *ctx, GLenum light,
    case GL_CONSTANT_ATTENUATION:
       R200_STATECHANGE(rmesa, lit[p]);
       fcmd[LIT_ATTEN_CONST] = params[0];
+      if ( params[0] == 0.0 )
+        fcmd[LIT_ATTEN_CONST_INV] = FLT_MAX;
+      else
+        fcmd[LIT_ATTEN_CONST_INV] = 1.0 / params[0];
       break;
    case GL_LINEAR_ATTENUATION:
       R200_STATECHANGE(rmesa, lit[p]);
@@ -1117,6 +1121,41 @@ static void r200Lightfv( GLcontext *ctx, GLenum light,
       return;
    }
 
+   /* Set RANGE_ATTEN only when needed */
+   switch (pname) {
+   case GL_POSITION:
+   case GL_CONSTANT_ATTENUATION:
+   case GL_LINEAR_ATTENUATION:
+   case GL_QUADRATIC_ATTENUATION: {
+      GLuint *icmd = (GLuint *)R200_DB_STATE( tcl );
+      GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
+      GLuint atten_flag = ( p&1 ) ? R200_LIGHT_1_ENABLE_RANGE_ATTEN
+                                 : R200_LIGHT_0_ENABLE_RANGE_ATTEN;
+      GLuint atten_const_flag = ( p&1 ) ? R200_LIGHT_1_CONSTANT_RANGE_ATTEN
+                                 : R200_LIGHT_0_CONSTANT_RANGE_ATTEN;
+
+      if ( l->EyePosition[3] == 0.0F ||
+          ( ( fcmd[LIT_ATTEN_CONST] == 0.0 || fcmd[LIT_ATTEN_CONST] == 1.0 ) &&
+            fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) ) {
+        /* Disable attenuation */
+        icmd[idx] &= ~atten_flag;
+      } else {
+        if ( fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) {
+           /* Enable only constant portion of attenuation calculation */
+           icmd[idx] |= ( atten_flag | atten_const_flag );
+        } else {
+           /* Enable full attenuation calculation */
+           icmd[idx] &= ~atten_const_flag;
+           icmd[idx] |= atten_flag;
+        }
+      }
+
+      R200_DB_STATECHANGE( rmesa, &rmesa->hw.tcl );
+      break;
+   }
+   default:
+     break;
+   }
 }
 
                  
index 22ad4e376e7d9cffb843174e735f3e403fe5aa7c..b9fc724f569e283b6988683bbb808f895f73210c 100644 (file)
@@ -683,6 +683,7 @@ void r200InitState( r200ContextPtr rmesa )
                           &l->LinearAttenuation );
       ctx->Driver.Lightfv( ctx, p, GL_QUADRATIC_ATTENUATION, 
                           &l->QuadraticAttenuation );
+      *(float *)&(rmesa->hw.lit[i].cmd[LIT_ATTEN_XXX]) = 0.0;
    }
 
    ctx->Driver.LightModelfv( ctx, GL_LIGHT_MODEL_AMBIENT, 
index 0a32fd8aa3b24306c5800b753ba3c8393a0bfdce..3ce67044f9e494af5ebc2f4df7a40aecbcb5f031 100644 (file)
@@ -340,9 +340,9 @@ struct radeon_state_atom {
 #define LIT_DIRECTION_Y            18
 #define LIT_DIRECTION_Z            19
 #define LIT_DIRECTION_W            20
-#define LIT_ATTEN_CONST            21
+#define LIT_ATTEN_QUADRATIC        21
 #define LIT_ATTEN_LINEAR           22
-#define LIT_ATTEN_QUADRATIC        23
+#define LIT_ATTEN_CONST            23
 #define LIT_ATTEN_XXX              24
 #define LIT_CMD_1                  25
 #define LIT_SPOT_DCD               26
@@ -350,7 +350,7 @@ struct radeon_state_atom {
 #define LIT_SPOT_CUTOFF            28
 #define LIT_SPECULAR_THRESH        29
 #define LIT_RANGE_CUTOFF           30 /* ? */
-#define LIT_RANGE_ATTEN            31 /* ? */
+#define LIT_ATTEN_CONST_INV        31
 #define LIT_STATE_SIZE             32
 
 /* Fog
index e71f5adf271b820e71c6eec3db6590e5141407f8..db198074eee552cfa8ca7ced499b76918780ee8c 100644 (file)
@@ -1101,6 +1101,10 @@ static void radeonLightfv( GLcontext *ctx, GLenum light,
    case GL_CONSTANT_ATTENUATION:
       RADEON_STATECHANGE(rmesa, lit[p]);
       fcmd[LIT_ATTEN_CONST] = params[0];
+      if ( params[0] == 0.0 )
+        fcmd[LIT_ATTEN_CONST_INV] = FLT_MAX;
+      else
+        fcmd[LIT_ATTEN_CONST_INV] = 1.0 / params[0];
       break;
    case GL_LINEAR_ATTENUATION:
       RADEON_STATECHANGE(rmesa, lit[p]);
@@ -1117,23 +1121,34 @@ static void radeonLightfv( GLcontext *ctx, GLenum light,
    /* Set RANGE_ATTEN only when needed */
    switch (pname) {
    case GL_POSITION:
+   case GL_CONSTANT_ATTENUATION:
    case GL_LINEAR_ATTENUATION:
    case GL_QUADRATIC_ATTENUATION:
    {
-      GLuint flag;
+      GLuint *icmd = (GLuint *)RADEON_DB_STATE( tcl );
       GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
+      GLuint atten_flag = ( p&1 ) ? RADEON_LIGHT_1_ENABLE_RANGE_ATTEN
+                                 : RADEON_LIGHT_0_ENABLE_RANGE_ATTEN;
+      GLuint atten_const_flag = ( p&1 ) ? RADEON_LIGHT_1_CONSTANT_RANGE_ATTEN
+                                 : RADEON_LIGHT_0_CONSTANT_RANGE_ATTEN;
+
+      if ( l->EyePosition[3] == 0.0F ||
+          ( ( fcmd[LIT_ATTEN_CONST] == 0.0 || fcmd[LIT_ATTEN_CONST] == 1.0 ) &&
+            fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) ) {
+        /* Disable attenuation */
+        icmd[idx] &= ~atten_flag;
+      } else {
+        if ( fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) {
+           /* Enable only constant portion of attenuation calculation */
+           icmd[idx] |= ( atten_flag | atten_const_flag );
+        } else {
+           /* Enable full attenuation calculation */
+           icmd[idx] &= ~atten_const_flag;
+           icmd[idx] |= atten_flag;
+        }
+      }
 
-      if (p&1) 
-        flag = RADEON_LIGHT_1_ENABLE_RANGE_ATTEN;
-      else
-        flag = RADEON_LIGHT_0_ENABLE_RANGE_ATTEN;
-
-      RADEON_STATECHANGE(rmesa, tcl);
-      if (l->EyePosition[3] != 0.0F &&
-         (l->LinearAttenuation != 0.0F || l->QuadraticAttenuation != 0.0F))
-        rmesa->hw.tcl.cmd[idx] |= flag;
-      else
-        rmesa->hw.tcl.cmd[idx] &= ~flag;
+      RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.tcl );
       break;
    }
    default:
index 2aa8dbe40a77d2dbf60f00a49441e6d599bc2d9e..ceb313a7e712b7b5b4d68423958e3eaa468b9994 100644 (file)
@@ -522,6 +522,7 @@ void radeonInitState( radeonContextPtr rmesa )
                           &l->LinearAttenuation );
       ctx->Driver.Lightfv( ctx, p, GL_QUADRATIC_ATTENUATION, 
                     &l->QuadraticAttenuation );
+      *(float *)&(rmesa->hw.lit[i].cmd[LIT_ATTEN_XXX]) = 0.0;
    }
 
    ctx->Driver.LightModelfv( ctx, GL_LIGHT_MODEL_AMBIENT,