Support ARB_texture_env_crossbar. Changes the way programs are
[mesa.git] / src / mesa / main / attrib.c
index c34b80a60d0dfe0cb08ab6eea599a6316debb4ee..da6011c1cef883dee88c1ca7a959d763aa3f55d4 100644 (file)
@@ -1,10 +1,8 @@
-/* $Id: attrib.c,v 1.76 2003/01/22 17:58:52 brianp Exp $ */
-
 /*
  * Mesa 3-D graphics library
- * Version:  5.1
+ * Version:  6.3
  *
- * Copyright (C) 1999-2003  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2004  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"),
@@ -30,6 +28,7 @@
 #include "attrib.h"
 #include "blend.h"
 #include "buffers.h"
+#include "bufferobj.h"
 #include "colormac.h"
 #include "colortab.h"
 #include "context.h"
@@ -66,7 +65,7 @@ new_attrib_node( GLbitfield kind )
 }
 
 
-void
+void GLAPIENTRY
 _mesa_PushAttrib(GLbitfield mask)
 {
    struct gl_attrib_node *newnode;
@@ -191,6 +190,7 @@ _mesa_PushAttrib(GLbitfield mask)
       attr->RescaleNormals = ctx->Transform.RescaleNormals;
       attr->Scissor = ctx->Scissor.Enabled;
       attr->Stencil = ctx->Stencil.Enabled;
+      attr->StencilTwoSide = ctx->Stencil.TestTwoSide;
       attr->MultisampleEnabled = ctx->Multisample.Enabled;
       attr->SampleAlphaToCoverage = ctx->Multisample.SampleAlphaToCoverage;
       attr->SampleAlphaToOne = ctx->Multisample.SampleAlphaToOne;
@@ -199,8 +199,8 @@ _mesa_PushAttrib(GLbitfield mask)
       for (i=0; i<MAX_TEXTURE_UNITS; i++) {
          attr->Texture[i] = ctx->Texture.Unit[i].Enabled;
          attr->TexGen[i] = ctx->Texture.Unit[i].TexGenEnabled;
+         attr->TextureColorTable[i] = ctx->Texture.Unit[i].ColorTableEnabled;
       }
-      attr->TextureColorTable = ctx->Texture.ColorTableEnabled;
       /* GL_NV_vertex_program */
       attr->VertexProgram = ctx->VertexProgram.Enabled;
       attr->VertexProgramPointSize = ctx->VertexProgram.PointSizeEnabled;
@@ -503,7 +503,7 @@ pop_enable_group(GLcontext *ctx, const struct gl_enable_attrib *enable)
                    GL_POINT_SMOOTH);
    TEST_AND_UPDATE(ctx->Point.SmoothFlag, enable->PointSmooth,
                    GL_POINT_SMOOTH);
-   if (ctx->Extensions.NV_point_sprite) {
+   if (ctx->Extensions.NV_point_sprite || ctx->Extensions.ARB_point_sprite) {
       TEST_AND_UPDATE(ctx->Point.PointSprite, enable->PointSprite,
                       GL_POINT_SPRITE_NV);
    }
@@ -519,7 +519,9 @@ pop_enable_group(GLcontext *ctx, const struct gl_enable_attrib *enable)
                    GL_POLYGON_STIPPLE);
    TEST_AND_UPDATE(ctx->Scissor.Enabled, enable->Scissor, GL_SCISSOR_TEST);
    TEST_AND_UPDATE(ctx->Stencil.Enabled, enable->Stencil, GL_STENCIL_TEST);
-   /* XXX two-sided stencil */
+   if (ctx->Extensions.EXT_stencil_two_side) {
+      TEST_AND_UPDATE(ctx->Stencil.TestTwoSide, enable->StencilTwoSide, GL_STENCIL_TEST_TWO_SIDE_EXT);
+   }
    TEST_AND_UPDATE(ctx->Multisample.Enabled, enable->MultisampleEnabled,
                    GL_MULTISAMPLE_ARB);
    TEST_AND_UPDATE(ctx->Multisample.SampleAlphaToCoverage,
@@ -534,8 +536,6 @@ pop_enable_group(GLcontext *ctx, const struct gl_enable_attrib *enable)
    TEST_AND_UPDATE(ctx->Multisample.SampleCoverageInvert,
                    enable->SampleCoverageInvert,
                    GL_SAMPLE_COVERAGE_INVERT_ARB);
-   TEST_AND_UPDATE(ctx->Texture.ColorTableEnabled, enable->TextureColorTable,
-                   GL_TEXTURE_COLOR_TABLE_SGI);
    /* GL_NV_vertex_program */
    TEST_AND_UPDATE(ctx->VertexProgram.Enabled,
                    enable->VertexProgram,
@@ -596,6 +596,9 @@ pop_enable_group(GLcontext *ctx, const struct gl_enable_attrib *enable)
                (*ctx->Driver.Enable)( ctx, GL_TEXTURE_GEN_Q, GL_FALSE);
          }
       }
+
+      /* GL_SGI_texture_color_table */
+      ctx->Texture.Unit[i].ColorTableEnabled = enable->TextureColorTable[i];
    }
 
    if (ctx->Driver.ActiveTexture) {
@@ -630,13 +633,7 @@ pop_texture_group(GLcontext *ctx, const struct gl_texture_attrib *texAttrib)
       }
       if (ctx->Extensions.SGI_texture_color_table) {
          _mesa_set_enable(ctx, GL_TEXTURE_COLOR_TABLE_SGI,
-                          texAttrib->ColorTableEnabled);
-         _mesa_ColorTableParameterfv(GL_TEXTURE_COLOR_TABLE_SGI,
-                                     GL_COLOR_TABLE_SCALE_SGI,
-                                     texAttrib->ColorTableScale);
-         _mesa_ColorTableParameterfv(GL_TEXTURE_COLOR_TABLE_SGI,
-                                     GL_COLOR_TABLE_BIAS_SGI,
-                                     texAttrib->ColorTableBias);
+                          unit->ColorTableEnabled);
       }
       _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->EnvMode);
       _mesa_TexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, unit->EnvColor);
@@ -658,38 +655,38 @@ pop_texture_group(GLcontext *ctx, const struct gl_texture_attrib *texAttrib)
       }
       if (ctx->Extensions.EXT_texture_env_combine ||
           ctx->Extensions.ARB_texture_env_combine) {
-         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT,
-                       unit->CombineModeRGB);
-         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT,
-                       unit->CombineModeA);
-         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT,
-                       unit->CombineSourceRGB[0]);
-         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT,
-                       unit->CombineSourceRGB[1]);
-         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT,
-                       unit->CombineSourceRGB[2]);
-         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT,
-                       unit->CombineSourceA[0]);
-         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT,
-                       unit->CombineSourceA[1]);
-         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT,
-                       unit->CombineSourceA[2]);
-         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT,
-                       unit->CombineOperandRGB[0]);
-         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT,
-                       unit->CombineOperandRGB[1]);
-         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT,
-                       unit->CombineOperandRGB[2]);
-         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT,
-                       unit->CombineOperandA[0]);
-         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT,
-                       unit->CombineOperandA[1]);
-         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT,
-                       unit->CombineOperandA[2]);
-         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT,
-                       1 << unit->CombineScaleShiftRGB);
+         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB,
+                       unit->Combine.ModeRGB);
+         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA,
+                       unit->Combine.ModeA);
+         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB,
+                       unit->Combine.SourceRGB[0]);
+         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB,
+                       unit->Combine.SourceRGB[1]);
+         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB,
+                       unit->Combine.SourceRGB[2]);
+         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA,
+                       unit->Combine.SourceA[0]);
+         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA,
+                       unit->Combine.SourceA[1]);
+         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA,
+                       unit->Combine.SourceA[2]);
+         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB,
+                       unit->Combine.OperandRGB[0]);
+         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB,
+                       unit->Combine.OperandRGB[1]);
+         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB,
+                       unit->Combine.OperandRGB[2]);
+         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA,
+                       unit->Combine.OperandA[0]);
+         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA,
+                       unit->Combine.OperandA[1]);
+         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA,
+                       unit->Combine.OperandA[2]);
+         _mesa_TexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE,
+                       1 << unit->Combine.ScaleShiftRGB);
          _mesa_TexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE,
-                       1 << unit->CombineScaleShiftA);
+                       1 << unit->Combine.ScaleShiftA);
       }
 
       /* Restore texture object state */
@@ -789,7 +786,7 @@ pop_texture_group(GLcontext *ctx, const struct gl_texture_attrib *texAttrib)
  * We could at least check if the value to restore equals the current value
  * and then skip the Mesa call.
  */
-void
+void GLAPIENTRY
 _mesa_PopAttrib(void)
 {
    struct gl_attrib_node *attr, *next;
@@ -836,7 +833,13 @@ _mesa_PopAttrib(void)
                                (GLboolean) (color->ColorMask[1] != 0),
                                (GLboolean) (color->ColorMask[2] != 0),
                                (GLboolean) (color->ColorMask[3] != 0));
-               _mesa_DrawBuffer(color->DrawBuffer);
+#if 0
+               _mesa_DrawBuffersARB(ctx->Const.MaxDrawBuffers,
+                                    color->DrawBuffer);
+#else
+               _mesa_drawbuffers(ctx, ctx->Const.MaxDrawBuffers,
+                                 color->DrawBuffer, NULL);
+#endif
                _mesa_set_enable(ctx, GL_ALPHA_TEST, color->AlphaEnabled);
                _mesa_AlphaFunc(color->AlphaFunc, color->AlphaRef);
                _mesa_set_enable(ctx, GL_BLEND, color->BlendEnabled);
@@ -844,7 +847,16 @@ _mesa_PopAttrib(void)
                                           color->BlendDstRGB,
                                           color->BlendSrcA,
                                           color->BlendDstA);
-               _mesa_BlendEquation(color->BlendEquation);
+              /* This special case is because glBlendEquationSeparateEXT
+               * cannot take GL_LOGIC_OP as a parameter.
+               */
+              if ( color->BlendEquationRGB == color->BlendEquationA ) {
+                 _mesa_BlendEquation(color->BlendEquationRGB);
+              }
+              else {
+                 _mesa_BlendEquationSeparateEXT(color->BlendEquationRGB,
+                                                color->BlendEquationA);
+              }
                _mesa_BlendColor(color->BlendColor[0],
                                 color->BlendColor[1],
                                 color->BlendColor[2],
@@ -925,9 +937,8 @@ _mesa_PopAttrib(void)
                /* lighting enable */
                _mesa_set_enable(ctx, GL_LIGHTING, light->Enabled);
                /* per-light state */
-
-              if (ctx->ModelviewMatrixStack.Top->flags & MAT_DIRTY_INVERSE) 
-                 _math_matrix_analyse( ctx->ModelviewMatrixStack.Top );
+               if (ctx->ModelviewMatrixStack.Top->flags & MAT_DIRTY_INVERSE) 
+                  _math_matrix_analyse( ctx->ModelviewMatrixStack.Top );
               
                for (i = 0; i < MAX_LIGHTS; i++) {
                   GLenum lgt = (GLenum) (GL_LIGHT0 + i);
@@ -960,8 +971,8 @@ _mesa_PopAttrib(void)
                _mesa_LightModelf(GL_LIGHT_MODEL_COLOR_CONTROL,
                                  (GLfloat) light->Model.ColorControl);
                /* materials */
-               MEMCPY(ctx->Light.Material, light->Material,
-                      2 * sizeof(struct gl_material));
+               MEMCPY(&ctx->Light.Material, &light->Material,
+                      sizeof(struct gl_material));
                /* shade model */
                _mesa_ShadeModel(light->ShadeModel);
                /* color material */
@@ -986,6 +997,8 @@ _mesa_PopAttrib(void)
             break;
          case GL_PIXEL_MODE_BIT:
             MEMCPY( &ctx->Pixel, attr->data, sizeof(struct gl_pixel_attrib) );
+            /* XXX what other pixel state needs to be set by function calls? */
+            _mesa_ReadBuffer(ctx->Pixel.ReadBuffer);
            ctx->NewState |= _NEW_PIXEL;
             break;
          case GL_POINT_BIT:
@@ -1004,7 +1017,8 @@ _mesa_PopAttrib(void)
                   _mesa_PointParameterfEXT(GL_POINT_FADE_THRESHOLD_SIZE_EXT,
                                            point->Threshold);
                }
-               if (ctx->Extensions.NV_point_sprite) {
+               if (ctx->Extensions.NV_point_sprite
+                  || ctx->Extensions.ARB_point_sprite) {
                   GLuint u;
                   for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
                      _mesa_TexEnvi(GL_POINT_SPRITE_NV, GL_COORD_REPLACE_NV,
@@ -1013,6 +1027,8 @@ _mesa_PopAttrib(void)
                   _mesa_set_enable(ctx, GL_POINT_SPRITE_NV,point->PointSprite);
                   _mesa_PointParameteriNV(GL_POINT_SPRITE_R_MODE_NV,
                                           ctx->Point.SpriteRMode);
+                  _mesa_PointParameterfEXT(GL_POINT_SPRITE_COORD_ORIGIN,
+                                           (GLfloat)ctx->Point.SpriteOrigin);
                }
             }
             break;
@@ -1054,17 +1070,26 @@ _mesa_PopAttrib(void)
             break;
          case GL_STENCIL_BUFFER_BIT:
             {
-               const GLint face = 0; /* XXX stencil two side */
+               GLint face;
                const struct gl_stencil_attrib *stencil;
                stencil = (const struct gl_stencil_attrib *) attr->data;
                _mesa_set_enable(ctx, GL_STENCIL_TEST, stencil->Enabled);
                _mesa_ClearStencil(stencil->Clear);
-               _mesa_StencilFunc(stencil->Function[face], stencil->Ref[face],
-                                 stencil->ValueMask[face]);
-               _mesa_StencilMask(stencil->WriteMask[face]);
-               _mesa_StencilOp(stencil->FailFunc[face],
-                               stencil->ZFailFunc[face],
-                               stencil->ZPassFunc[face]);
+               face = stencil->ActiveFace;
+               if (ctx->Extensions.EXT_stencil_two_side) {
+                  _mesa_set_enable(ctx, GL_STENCIL_TEST_TWO_SIDE_EXT, stencil->TestTwoSide);
+                  face ^= 1;
+               }
+               do {
+                  _mesa_ActiveStencilFaceEXT(face);
+                  _mesa_StencilFunc(stencil->Function[face], stencil->Ref[face],
+                                    stencil->ValueMask[face]);
+                  _mesa_StencilMask(stencil->WriteMask[face]);
+                  _mesa_StencilOp(stencil->FailFunc[face],
+                                  stencil->ZFailFunc[face],
+                                  stencil->ZPassFunc[face]);
+                  face ^= 1;
+               } while (face != (stencil->ActiveFace ^ 1));
             }
             break;
          case GL_TRANSFORM_BIT:
@@ -1073,7 +1098,6 @@ _mesa_PopAttrib(void)
                const struct gl_transform_attrib *xform;
                xform = (const struct gl_transform_attrib *) attr->data;
                _mesa_MatrixMode(xform->MatrixMode);
-
                if (ctx->ProjectionMatrixStack.Top->flags & MAT_DIRTY)
                   _math_matrix_analyse( ctx->ProjectionMatrixStack.Top );
 
@@ -1139,11 +1163,36 @@ _mesa_PopAttrib(void)
 }
 
 
+/**
+ * Helper for incrementing/decrementing vertex buffer object reference
+ * counts when pushing/popping the GL_CLIENT_VERTEX_ARRAY_BIT attribute group.
+ */
+static void
+adjust_buffer_object_ref_counts(struct gl_array_attrib *array, GLint step)
+{
+   GLuint i;
+   array->Vertex.BufferObj->RefCount += step;
+   array->Normal.BufferObj->RefCount += step;
+   array->Color.BufferObj->RefCount += step;
+   array->SecondaryColor.BufferObj->RefCount += step;
+   array->FogCoord.BufferObj->RefCount += step;
+   array->Index.BufferObj->RefCount += step;
+   array->EdgeFlag.BufferObj->RefCount += step;
+   for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++)
+      array->TexCoord[i].BufferObj->RefCount += step;
+   for (i = 0; i < VERT_ATTRIB_MAX; i++)
+      array->VertexAttrib[i].BufferObj->RefCount += step;
+
+   array->ArrayBufferObj->RefCount += step;
+   array->ElementArrayBufferObj->RefCount += step;
+}
+
+
 #define GL_CLIENT_PACK_BIT (1<<20)
 #define GL_CLIENT_UNPACK_BIT (1<<21)
 
 
-void
+void GLAPIENTRY
 _mesa_PushClientAttrib(GLbitfield mask)
 {
    struct gl_attrib_node *newnode;
@@ -1163,6 +1212,10 @@ _mesa_PushClientAttrib(GLbitfield mask)
 
    if (mask & GL_CLIENT_PIXEL_STORE_BIT) {
       struct gl_pixelstore_attrib *attr;
+#if FEATURE_EXT_pixel_buffer_object
+      ctx->Pack.BufferObj->RefCount++;
+      ctx->Unpack.BufferObj->RefCount++;
+#endif
       /* packing attribs */
       attr = MALLOC_STRUCT( gl_pixelstore_attrib );
       MEMCPY( attr, &ctx->Pack, sizeof(struct gl_pixelstore_attrib) );
@@ -1186,6 +1239,8 @@ _mesa_PushClientAttrib(GLbitfield mask)
       newnode->data = attr;
       newnode->next = head;
       head = newnode;
+      /* bump reference counts on buffer objects */
+      adjust_buffer_object_ref_counts(&ctx->Array, 1);
    }
 
    ctx->ClientAttribStack[ctx->ClientAttribStackDepth] = head;
@@ -1195,7 +1250,7 @@ _mesa_PushClientAttrib(GLbitfield mask)
 
 
 
-void
+void GLAPIENTRY
 _mesa_PopClientAttrib(void)
 {
    struct gl_attrib_node *attr, *next;
@@ -1214,18 +1269,34 @@ _mesa_PopClientAttrib(void)
    while (attr) {
       switch (attr->kind) {
          case GL_CLIENT_PACK_BIT:
+#if FEATURE_EXT_pixel_buffer_object
+            ctx->Pack.BufferObj->RefCount--;
+            if (ctx->Pack.BufferObj->RefCount <= 0) {
+               _mesa_remove_buffer_object( ctx, ctx->Pack.BufferObj );
+               (*ctx->Driver.DeleteBuffer)( ctx, ctx->Pack.BufferObj );
+            }
+#endif
             MEMCPY( &ctx->Pack, attr->data,
                     sizeof(struct gl_pixelstore_attrib) );
            ctx->NewState |= _NEW_PACKUNPACK;
             break;
          case GL_CLIENT_UNPACK_BIT:
+#if FEATURE_EXT_pixel_buffer_object
+            ctx->Unpack.BufferObj->RefCount--;
+            if (ctx->Unpack.BufferObj->RefCount <= 0) {
+               _mesa_remove_buffer_object( ctx, ctx->Unpack.BufferObj );
+               (*ctx->Driver.DeleteBuffer)( ctx, ctx->Unpack.BufferObj );
+            }
+#endif
             MEMCPY( &ctx->Unpack, attr->data,
                     sizeof(struct gl_pixelstore_attrib) );
            ctx->NewState |= _NEW_PACKUNPACK;
             break;
          case GL_CLIENT_VERTEX_ARRAY_BIT:
+            adjust_buffer_object_ref_counts(&ctx->Array, -1);
             MEMCPY( &ctx->Array, attr->data,
                    sizeof(struct gl_array_attrib) );
+            /* decrement reference counts on buffer objects */
            ctx->NewState |= _NEW_ARRAY;
             break;
          default:
@@ -1239,3 +1310,11 @@ _mesa_PopClientAttrib(void)
       attr = next;
    }
 }
+
+
+void _mesa_init_attrib( GLcontext *ctx )
+{
+   /* Renderer and client attribute stacks */
+   ctx->AttribStackDepth = 0;
+   ctx->ClientAttribStackDepth = 0;
+}