mesa: Change "BRIAN PAUL" to "THE AUTHORS" in license text.
[mesa.git] / src / mesa / main / attrib.c
index 6f4a91b1f170a5a1c1079b6696d8387de44e93ab..01e99668f6d6e4fe4e96f7e7eacbcf76a032d506 100644 (file)
@@ -18,7 +18,7 @@
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 #include "lines.h"
 #include "macros.h"
 #include "matrix.h"
-#include "mfeatures.h"
 #include "multisample.h"
 #include "points.h"
 #include "polygon.h"
+#include "shared.h"
 #include "scissor.h"
 #include "stencil.h"
 #include "texenv.h"
@@ -58,6 +58,8 @@
 #include "viewport.h"
 #include "mtypes.h"
 #include "main/dispatch.h"
+#include "hash.h"
+#include <stdbool.h>
 
 
 /**
@@ -91,7 +93,6 @@ struct gl_enable_attrib
    GLboolean Map1TextureCoord4;
    GLboolean Map1Vertex3;
    GLboolean Map1Vertex4;
-   GLboolean Map1Attrib[16];  /* GL_NV_vertex_program */
    GLboolean Map2Color4;
    GLboolean Map2Index;
    GLboolean Map2Normal;
@@ -101,7 +102,6 @@ struct gl_enable_attrib
    GLboolean Map2TextureCoord4;
    GLboolean Map2Vertex3;
    GLboolean Map2Vertex4;
-   GLboolean Map2Attrib[16];  /* GL_NV_vertex_program */
 
    GLboolean Normalize;
    GLboolean PixelTexture;
@@ -119,20 +119,25 @@ struct gl_enable_attrib
    GLboolean SampleAlphaToCoverage;   /* GL_ARB_multisample */
    GLboolean SampleAlphaToOne;        /* GL_ARB_multisample */
    GLboolean SampleCoverage;          /* GL_ARB_multisample */
-   GLboolean SampleCoverageInvert;    /* GL_ARB_multisample */
    GLboolean RasterPositionUnclipped; /* GL_IBM_rasterpos_clip */
 
    GLbitfield Texture[MAX_TEXTURE_UNITS];
    GLbitfield TexGen[MAX_TEXTURE_UNITS];
 
-   /* GL_ARB_vertex_program / GL_NV_vertex_program */
+   /* GL_ARB_vertex_program */
    GLboolean VertexProgram;
    GLboolean VertexProgramPointSize;
    GLboolean VertexProgramTwoSide;
 
+   /* GL_ARB_fragment_program */
+   GLboolean FragmentProgram;
+
    /* GL_ARB_point_sprite / GL_NV_point_sprite */
    GLboolean PointSprite;
    GLboolean FragmentShaderATI;
+
+   /* GL_ARB_framebuffer_sRGB / GL_EXT_framebuffer_sRGB */
+   GLboolean sRGBEnabled;
 };
 
 
@@ -163,10 +168,14 @@ struct texture_state
     * deleted while saved in the attribute stack).
     */
    struct gl_texture_object *SavedTexRef[MAX_TEXTURE_UNITS][NUM_TEXTURE_TARGETS];
-};
 
-
-#if FEATURE_attrib_stack
+   /* We need to keep a reference to the shared state.  That's where the
+    * default texture objects are kept.  We don't want that state to be
+    * freed while the attribute stack contains pointers to any default
+    * texture objects.
+    */
+   struct gl_shared_state *SharedRef;
+};
 
 
 /**
@@ -197,7 +206,6 @@ _mesa_PushAttrib(GLbitfield mask)
    struct gl_attrib_node *head;
 
    GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    if (MESA_VERBOSE & VERBOSE_API)
       _mesa_debug(ctx, "glPushAttrib %x\n", (int) mask);
@@ -276,7 +284,6 @@ _mesa_PushAttrib(GLbitfield mask)
       attr->Map1TextureCoord4 = ctx->Eval.Map1TextureCoord4;
       attr->Map1Vertex3 = ctx->Eval.Map1Vertex3;
       attr->Map1Vertex4 = ctx->Eval.Map1Vertex4;
-      memcpy(attr->Map1Attrib, ctx->Eval.Map1Attrib, sizeof(ctx->Eval.Map1Attrib));
       attr->Map2Color4 = ctx->Eval.Map2Color4;
       attr->Map2Index = ctx->Eval.Map2Index;
       attr->Map2Normal = ctx->Eval.Map2Normal;
@@ -286,7 +293,6 @@ _mesa_PushAttrib(GLbitfield mask)
       attr->Map2TextureCoord4 = ctx->Eval.Map2TextureCoord4;
       attr->Map2Vertex3 = ctx->Eval.Map2Vertex3;
       attr->Map2Vertex4 = ctx->Eval.Map2Vertex4;
-      memcpy(attr->Map2Attrib, ctx->Eval.Map2Attrib, sizeof(ctx->Eval.Map2Attrib));
       attr->Normalize = ctx->Transform.Normalize;
       attr->RasterPositionUnclipped = ctx->Transform.RasterPositionUnclipped;
       attr->PointSmooth = ctx->Point.SmoothFlag;
@@ -304,16 +310,22 @@ _mesa_PushAttrib(GLbitfield mask)
       attr->SampleAlphaToCoverage = ctx->Multisample.SampleAlphaToCoverage;
       attr->SampleAlphaToOne = ctx->Multisample.SampleAlphaToOne;
       attr->SampleCoverage = ctx->Multisample.SampleCoverage;
-      attr->SampleCoverageInvert = ctx->Multisample.SampleCoverageInvert;
       for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
          attr->Texture[i] = ctx->Texture.Unit[i].Enabled;
          attr->TexGen[i] = ctx->Texture.Unit[i].TexGenEnabled;
       }
-      /* GL_NV_vertex_program */
+      /* GL_ARB_vertex_program */
       attr->VertexProgram = ctx->VertexProgram.Enabled;
       attr->VertexProgramPointSize = ctx->VertexProgram.PointSizeEnabled;
       attr->VertexProgramTwoSide = ctx->VertexProgram.TwoSideEnabled;
+
+      /* GL_ARB_fragment_program */
+      attr->FragmentProgram = ctx->FragmentProgram.Enabled;
+
       save_attrib_data(&head, GL_ENABLE_BIT, attr);
+
+      /* GL_ARB_framebuffer_sRGB / GL_EXT_framebuffer_sRGB */
+      attr->sRGBEnabled = ctx->Color.sRGBEnabled;
    }
 
    if (mask & GL_EVAL_BIT) {
@@ -384,7 +396,7 @@ _mesa_PushAttrib(GLbitfield mask)
 
    if (mask & GL_POLYGON_STIPPLE_BIT) {
       GLuint *stipple;
-      stipple = (GLuint *) MALLOC( 32*sizeof(GLuint) );
+      stipple = malloc( 32*sizeof(GLuint) );
       memcpy( stipple, ctx->PolygonStipple, 32*sizeof(GLuint) );
       save_attrib_data(&head, GL_POLYGON_STIPPLE_BIT, stipple);
    }
@@ -435,6 +447,8 @@ _mesa_PushAttrib(GLbitfield mask)
          }
       }
 
+      _mesa_reference_shared_state(ctx, &texstate->SharedRef, ctx->Shared);
+
       _mesa_unlock_context_textures(ctx);
 
       save_attrib_data(&head, GL_TEXTURE_BIT, texstate);
@@ -532,10 +546,6 @@ pop_enable_group(struct gl_context *ctx, const struct gl_enable_attrib *enable)
                    GL_MAP1_VERTEX_3);
    TEST_AND_UPDATE(ctx->Eval.Map1Vertex4, enable->Map1Vertex4,
                    GL_MAP1_VERTEX_4);
-   for (i = 0; i < 16; i++) {
-      TEST_AND_UPDATE(ctx->Eval.Map1Attrib[i], enable->Map1Attrib[i],
-                      GL_MAP1_VERTEX_ATTRIB0_4_NV + i);
-   }
 
    TEST_AND_UPDATE(ctx->Eval.Map2Color4, enable->Map2Color4, GL_MAP2_COLOR_4);
    TEST_AND_UPDATE(ctx->Eval.Map2Index, enable->Map2Index, GL_MAP2_INDEX);
@@ -552,10 +562,6 @@ pop_enable_group(struct gl_context *ctx, const struct gl_enable_attrib *enable)
                    GL_MAP2_VERTEX_3);
    TEST_AND_UPDATE(ctx->Eval.Map2Vertex4, enable->Map2Vertex4,
                    GL_MAP2_VERTEX_4);
-   for (i = 0; i < 16; i++) {
-      TEST_AND_UPDATE(ctx->Eval.Map2Attrib[i], enable->Map2Attrib[i],
-                      GL_MAP2_VERTEX_ATTRIB0_4_NV + i);
-   }
 
    TEST_AND_UPDATE(ctx->Eval.AutoNormal, enable->AutoNormal, GL_AUTO_NORMAL);
    TEST_AND_UPDATE(ctx->Transform.Normalize, enable->Normalize, GL_NORMALIZE);
@@ -596,10 +602,7 @@ pop_enable_group(struct gl_context *ctx, const struct gl_enable_attrib *enable)
    TEST_AND_UPDATE(ctx->Multisample.SampleCoverage,
                    enable->SampleCoverage,
                    GL_SAMPLE_COVERAGE_ARB);
-   TEST_AND_UPDATE(ctx->Multisample.SampleCoverageInvert,
-                   enable->SampleCoverageInvert,
-                   GL_SAMPLE_COVERAGE_INVERT_ARB);
-   /* GL_ARB_vertex_program, GL_NV_vertex_program */
+   /* GL_ARB_vertex_program */
    TEST_AND_UPDATE(ctx->VertexProgram.Enabled,
                    enable->VertexProgram,
                    GL_VERTEX_PROGRAM_ARB);
@@ -610,7 +613,14 @@ pop_enable_group(struct gl_context *ctx, const struct gl_enable_attrib *enable)
                    enable->VertexProgramTwoSide,
                    GL_VERTEX_PROGRAM_TWO_SIDE_ARB);
 
-#undef TEST_AND_UPDATE
+   /* GL_ARB_fragment_program */
+   TEST_AND_UPDATE(ctx->FragmentProgram.Enabled,
+                   enable->FragmentProgram,
+                   GL_FRAGMENT_PROGRAM_ARB);
+
+   /* GL_ARB_framebuffer_sRGB / GL_EXT_framebuffer_sRGB */
+   TEST_AND_UPDATE(ctx->Color.sRGBEnabled, enable->sRGBEnabled,
+                   GL_FRAMEBUFFER_SRGB);
 
    /* texture unit enables */
    for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
@@ -618,7 +628,7 @@ pop_enable_group(struct gl_context *ctx, const struct gl_enable_attrib *enable)
       const GLbitfield genEnabled = enable->TexGen[i];
 
       if (ctx->Texture.Unit[i].Enabled != enabled) {
-         _mesa_ActiveTextureARB(GL_TEXTURE0 + i);
+         _mesa_ActiveTexture(GL_TEXTURE0 + i);
 
          _mesa_set_enable(ctx, GL_TEXTURE_1D, !!(enabled & TEXTURE_1D_BIT));
          _mesa_set_enable(ctx, GL_TEXTURE_2D, !!(enabled & TEXTURE_2D_BIT));
@@ -640,7 +650,7 @@ pop_enable_group(struct gl_context *ctx, const struct gl_enable_attrib *enable)
       }
 
       if (ctx->Texture.Unit[i].TexGenEnabled != genEnabled) {
-         _mesa_ActiveTextureARB(GL_TEXTURE0 + i);
+         _mesa_ActiveTexture(GL_TEXTURE0 + i);
          _mesa_set_enable(ctx, GL_TEXTURE_GEN_S, !!(genEnabled & S_BIT));
          _mesa_set_enable(ctx, GL_TEXTURE_GEN_T, !!(genEnabled & T_BIT));
          _mesa_set_enable(ctx, GL_TEXTURE_GEN_R, !!(genEnabled & R_BIT));
@@ -648,7 +658,7 @@ pop_enable_group(struct gl_context *ctx, const struct gl_enable_attrib *enable)
       }
    }
 
-   _mesa_ActiveTextureARB(GL_TEXTURE0 + curTexUnitSave);
+   _mesa_ActiveTexture(GL_TEXTURE0 + curTexUnitSave);
 }
 
 
@@ -666,7 +676,7 @@ pop_texture_group(struct gl_context *ctx, struct texture_state *texstate)
       const struct gl_texture_unit *unit = &texstate->Texture.Unit[u];
       GLuint tgt;
 
-      _mesa_ActiveTextureARB(GL_TEXTURE0_ARB + u);
+      _mesa_ActiveTexture(GL_TEXTURE0_ARB + u);
       _mesa_set_enable(ctx, GL_TEXTURE_1D, !!(unit->Enabled & TEXTURE_1D_BIT));
       _mesa_set_enable(ctx, GL_TEXTURE_2D, !!(unit->Enabled & TEXTURE_2D_BIT));
       _mesa_set_enable(ctx, GL_TEXTURE_3D, !!(unit->Enabled & TEXTURE_3D_BIT));
@@ -684,7 +694,6 @@ pop_texture_group(struct gl_context *ctx, struct texture_state *texstate)
          _mesa_set_enable(ctx, GL_TEXTURE_2D_ARRAY_EXT,
                           !!(unit->Enabled & TEXTURE_2D_ARRAY_BIT));
       }
-
       _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->EnvMode);
       _mesa_TexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, unit->EnvColor);
       _mesa_TexGeni(GL_S, GL_TEXTURE_GEN_MODE, unit->GenS.Mode);
@@ -762,10 +771,16 @@ pop_texture_group(struct gl_context *ctx, struct texture_state *texstate)
                   !ctx->Extensions.MESA_texture_array) {
             continue;
          }
-         else if (obj->Target == GL_TEXTURE_BUFFER)
+         else if (obj->Target == GL_TEXTURE_CUBE_MAP_ARRAY &&
+             !ctx->Extensions.ARB_texture_cube_map_array) {
+            continue;
+         } else if (obj->Target == GL_TEXTURE_BUFFER)
             continue;
          else if (obj->Target == GL_TEXTURE_EXTERNAL_OES)
             continue;
+         else if (obj->Target == GL_TEXTURE_2D_MULTISAMPLE ||
+                  obj->Target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)
+            continue;
 
          target = obj->Target;
 
@@ -790,10 +805,14 @@ pop_texture_group(struct gl_context *ctx, struct texture_state *texstate)
             _mesa_TexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT,
                                 samp->MaxAnisotropy);
          }
-         if (ctx->Extensions.ARB_shadow_ambient) {
-            _mesa_TexParameterf(target, GL_TEXTURE_COMPARE_FAIL_VALUE_ARB,
-                                samp->CompareFailValue);
+         if (ctx->Extensions.ARB_shadow) {
+            _mesa_TexParameteri(target, GL_TEXTURE_COMPARE_MODE,
+                                samp->CompareMode);
+            _mesa_TexParameteri(target, GL_TEXTURE_COMPARE_FUNC,
+                                samp->CompareFunc);
          }
+         if (ctx->Extensions.ARB_depth_texture)
+            _mesa_TexParameteri(target, GL_DEPTH_TEXTURE_MODE, obj->DepthMode);
       }
 
       /* remove saved references to the texture objects */
@@ -802,7 +821,9 @@ pop_texture_group(struct gl_context *ctx, struct texture_state *texstate)
       }
    }
 
-   _mesa_ActiveTextureARB(GL_TEXTURE0_ARB + texstate->Texture.CurrentUnit);
+   _mesa_ActiveTexture(GL_TEXTURE0_ARB + texstate->Texture.CurrentUnit);
+
+   _mesa_reference_shared_state(ctx, &texstate->SharedRef, NULL);
 
    _mesa_unlock_context_textures(ctx);
 }
@@ -823,7 +844,7 @@ _mesa_PopAttrib(void)
 {
    struct gl_attrib_node *attr, *next;
    GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+   FLUSH_VERTICES(ctx, 0);
 
    if (ctx->AttribStackDepth == 0) {
       _mesa_error( ctx, GL_STACK_UNDERFLOW, "glPopAttrib" );
@@ -871,7 +892,7 @@ _mesa_PopAttrib(void)
                else {
                   GLuint i;
                   for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
-                     _mesa_ColorMaskIndexed(i, 
+                     _mesa_ColorMaski(i, 
                                   (GLboolean) (color->ColorMask[i][0] != 0),
                                   (GLboolean) (color->ColorMask[i][1] != 0),
                                   (GLboolean) (color->ColorMask[i][2] != 0),
@@ -902,7 +923,7 @@ _mesa_PopAttrib(void)
                    * to record that error.  Per OpenGL ARB decision.
                    */
                   if (multipleBuffers)
-                     _mesa_DrawBuffersARB(ctx->Const.MaxDrawBuffers,
+                     _mesa_DrawBuffers(ctx->Const.MaxDrawBuffers,
                                           color->DrawBuffer);
                   else
                      _mesa_DrawBuffer(color->DrawBuffer[0]);
@@ -926,18 +947,18 @@ _mesa_PopAttrib(void)
                   /* set blend per buffer */
                   GLuint buf;
                   for (buf = 0; buf < ctx->Const.MaxDrawBuffers; buf++) {
-                     _mesa_BlendFuncSeparatei(buf, color->Blend[buf].SrcRGB,
+                     _mesa_BlendFuncSeparateiARB(buf, color->Blend[buf].SrcRGB,
                                               color->Blend[buf].DstRGB,
                                               color->Blend[buf].SrcA,
                                               color->Blend[buf].DstA);
-                     _mesa_BlendEquationSeparatei(buf,
+                     _mesa_BlendEquationSeparateiARB(buf,
                                                   color->Blend[buf].EquationRGB,
                                                   color->Blend[buf].EquationA);
                   }
                }
                else {
                   /* set same blend modes for all buffers */
-                  _mesa_BlendFuncSeparateEXT(color->Blend[0].SrcRGB,
+                  _mesa_BlendFuncSeparate(color->Blend[0].SrcRGB,
                                              color->Blend[0].DstRGB,
                                              color->Blend[0].SrcA,
                                              color->Blend[0].DstA);
@@ -949,7 +970,7 @@ _mesa_PopAttrib(void)
                      _mesa_BlendEquation(color->Blend[0].EquationRGB);
                   }
                   else {
-                     _mesa_BlendEquationSeparateEXT(
+                     _mesa_BlendEquationSeparate(
                                                  color->Blend[0].EquationRGB,
                                                  color->Blend[0].EquationA);
                   }
@@ -964,8 +985,14 @@ _mesa_PopAttrib(void)
                _mesa_set_enable(ctx, GL_INDEX_LOGIC_OP,
                                 color->IndexLogicOpEnabled);
                _mesa_set_enable(ctx, GL_DITHER, color->DitherFlag);
-               _mesa_ClampColorARB(GL_CLAMP_FRAGMENT_COLOR_ARB, color->ClampFragmentColor);
-               _mesa_ClampColorARB(GL_CLAMP_READ_COLOR_ARB, color->ClampReadColor);
+               if (ctx->Extensions.ARB_color_buffer_float)
+                  _mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR_ARB,
+                                   color->ClampFragmentColor);
+               _mesa_ClampColor(GL_CLAMP_READ_COLOR_ARB, color->ClampReadColor);
+
+               /* GL_ARB_framebuffer_sRGB / GL_EXT_framebuffer_sRGB */
+               if (ctx->Extensions.EXT_framebuffer_sRGB)
+                  _mesa_set_enable(ctx, GL_FRAMEBUFFER_SRGB, color->sRGBEnabled);
             }
             break;
          case GL_CURRENT_BIT:
@@ -1068,7 +1095,7 @@ _mesa_PopAttrib(void)
                      p[0] = l->QuadraticAttenuation;
                      _mesa_light(ctx, i, GL_QUADRATIC_ATTENUATION, p);
                   }
-                }
+               }
                /* light model */
                _mesa_LightModelfv(GL_LIGHT_MODEL_AMBIENT,
                                   light->Model.Ambient);
@@ -1088,7 +1115,10 @@ _mesa_PopAttrib(void)
                /* materials */
                memcpy(&ctx->Light.Material, &light->Material,
                       sizeof(struct gl_material));
-               _mesa_ClampColorARB(GL_CLAMP_VERTEX_COLOR_ARB, light->ClampVertexColor);
+               if (ctx->Extensions.ARB_color_buffer_float) {
+                  _mesa_ClampColor(GL_CLAMP_VERTEX_COLOR_ARB,
+                                   light->ClampVertexColor);
+               }
             }
             break;
          case GL_LINE_BIT:
@@ -1137,8 +1167,11 @@ _mesa_PopAttrib(void)
                   if (ctx->Extensions.NV_point_sprite)
                      _mesa_PointParameteri(GL_POINT_SPRITE_R_MODE_NV,
                                            ctx->Point.SpriteRMode);
-                  _mesa_PointParameterf(GL_POINT_SPRITE_COORD_ORIGIN,
-                                        (GLfloat)ctx->Point.SpriteOrigin);
+
+                  if ((ctx->API == API_OPENGL_COMPAT && ctx->Version >= 20)
+                      || ctx->API == API_OPENGL_CORE)
+                     _mesa_PointParameterf(GL_POINT_SPRITE_COORD_ORIGIN,
+                                           (GLfloat)ctx->Point.SpriteOrigin);
                }
             }
             break;
@@ -1242,7 +1275,6 @@ _mesa_PopAttrib(void)
             }
             break;
          case GL_TEXTURE_BIT:
-            /* Take care of texture object reference counters */
             {
                struct texture_state *texstate
                   = (struct texture_state *) attr->data;
@@ -1262,7 +1294,24 @@ _mesa_PopAttrib(void)
             {
                const struct gl_multisample_attrib *ms;
                ms = (const struct gl_multisample_attrib *) attr->data;
-               _mesa_SampleCoverageARB(ms->SampleCoverageValue,
+
+              TEST_AND_UPDATE(ctx->Multisample.Enabled,
+                              ms->Enabled,
+                              GL_MULTISAMPLE);
+
+              TEST_AND_UPDATE(ctx->Multisample.SampleCoverage,
+                              ms->SampleCoverage,
+                              GL_SAMPLE_COVERAGE);
+
+              TEST_AND_UPDATE(ctx->Multisample.SampleAlphaToCoverage,
+                              ms->SampleAlphaToCoverage,
+                              GL_SAMPLE_ALPHA_TO_COVERAGE);
+
+              TEST_AND_UPDATE(ctx->Multisample.SampleAlphaToOne,
+                              ms->SampleAlphaToOne,
+                              GL_SAMPLE_ALPHA_TO_ONE);
+
+               _mesa_SampleCoverage(ms->SampleCoverageValue,
                                        ms->SampleCoverageInvert);
             }
             break;
@@ -1273,8 +1322,8 @@ _mesa_PopAttrib(void)
       }
 
       next = attr->next;
-      FREE( attr->data );
-      FREE( attr );
+      free(attr->data);
+      free(attr);
       attr = next;
    }
 }
@@ -1320,7 +1369,7 @@ copy_array_object(struct gl_context *ctx,
    /* skip RefCount */
 
    /* In theory must be the same anyway, but on recreate make sure it matches */
-   dest->VBOonly = src->VBOonly;
+   dest->ARBsemantics = src->ARBsemantics;
 
    for (i = 0; i < Elements(src->VertexAttrib); i++)
       _mesa_copy_client_array(ctx, &dest->VertexAttrib[i], &src->VertexAttrib[i]);
@@ -1337,7 +1386,8 @@ copy_array_object(struct gl_context *ctx,
 static void
 copy_array_attrib(struct gl_context *ctx,
                   struct gl_array_attrib *dest,
-                  struct gl_array_attrib *src)
+                  struct gl_array_attrib *src,
+                  bool vbo_deleted)
 {
    /* skip ArrayObj */
    /* skip DefaultArrayObj, Objects */
@@ -1345,11 +1395,15 @@ copy_array_attrib(struct gl_context *ctx,
    dest->LockFirst = src->LockFirst;
    dest->LockCount = src->LockCount;
    dest->PrimitiveRestart = src->PrimitiveRestart;
+   dest->PrimitiveRestartFixedIndex = src->PrimitiveRestartFixedIndex;
+   dest->_PrimitiveRestart = src->_PrimitiveRestart;
    dest->RestartIndex = src->RestartIndex;
+   dest->_RestartIndex = src->_RestartIndex;
    /* skip NewState */
    /* skip RebindArrays */
 
-   copy_array_object(ctx, dest->ArrayObj, src->ArrayObj);
+   if (!vbo_deleted)
+      copy_array_object(ctx, dest->ArrayObj, src->ArrayObj);
 
    /* skip ArrayBufferObj */
    /* skip ElementArrayBufferObj */
@@ -1367,7 +1421,7 @@ save_array_attrib(struct gl_context *ctx,
     * Needs to match value in the object hash. */
    dest->ArrayObj->Name = src->ArrayObj->Name;
    /* And copy all of the rest. */
-   copy_array_attrib(ctx, dest, src);
+   copy_array_attrib(ctx, dest, src, false);
 
    /* Just reference them here */
    _mesa_reference_buffer_object(ctx, &dest->ArrayBufferObj,
@@ -1384,27 +1438,44 @@ restore_array_attrib(struct gl_context *ctx,
                      struct gl_array_attrib *dest,
                      struct gl_array_attrib *src)
 {
-   /* Restore or recreate the array object by its name ... */
-   _mesa_BindVertexArrayAPPLE(src->ArrayObj->Name);
+   /* The ARB_vertex_array_object spec says:
+    *
+    *     "BindVertexArray fails and an INVALID_OPERATION error is generated
+    *     if array is not a name returned from a previous call to
+    *     GenVertexArrays, or if such a name has since been deleted with
+    *     DeleteVertexArrays."
+    *
+    * Therefore popping a deleted VAO cannot magically recreate it.
+    *
+    * The semantics of objects created using APPLE_vertex_array_objects behave
+    * differently.  These objects expect to be recreated by pop.  Alas.
+    */
+   const bool arb_vao = (src->ArrayObj->Name != 0
+                        && src->ArrayObj->ARBsemantics);
 
-   /* ... and restore its content */
-   copy_array_attrib(ctx, dest, src);
+   if (arb_vao && !_mesa_IsVertexArray(src->ArrayObj->Name))
+      return;
+
+   _mesa_BindVertexArrayAPPLE(src->ArrayObj->Name);
 
    /* Restore or recreate the buffer objects by the names ... */
-   _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB,
-                       src->ArrayBufferObj->Name);
-   _mesa_BindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB,
-                       src->ArrayObj->ElementArrayBufferObj->Name);
-
-   /* Better safe than sorry?! */
-   dest->RebindArrays = GL_TRUE;
-
-   /* FIXME: Should some bits in ctx->Array->NewState also be set
-    * FIXME: here?  It seems like it should be set to inclusive-or
-    * FIXME: of the old ArrayObj->_Enabled and the new _Enabled.
-    * ... just do it.
-    */
-   dest->NewState |= src->ArrayObj->_Enabled | dest->ArrayObj->_Enabled;
+   if (!arb_vao
+       || src->ArrayBufferObj->Name == 0
+       || _mesa_IsBuffer(src->ArrayBufferObj->Name)) {
+      /* ... and restore its content */
+      copy_array_attrib(ctx, dest, src, false);
+
+      _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB,
+                         src->ArrayBufferObj->Name);
+   } else {
+      copy_array_attrib(ctx, dest, src, true);
+   }
+
+   if (!arb_vao
+       || src->ArrayObj->ElementArrayBufferObj->Name == 0
+       || _mesa_IsBuffer(src->ArrayObj->ElementArrayBufferObj->Name))
+      _mesa_BindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB,
+                         src->ArrayObj->ElementArrayBufferObj->Name);
 }
 
 /**
@@ -1443,7 +1514,6 @@ _mesa_PushClientAttrib(GLbitfield mask)
    struct gl_attrib_node *head;
 
    GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    if (ctx->ClientAttribStackDepth >= MAX_CLIENT_ATTRIB_STACK_DEPTH) {
       _mesa_error( ctx, GL_STACK_OVERFLOW, "glPushClientAttrib" );
@@ -1488,7 +1558,7 @@ _mesa_PopClientAttrib(void)
    struct gl_attrib_node *node, *next;
 
    GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+   FLUSH_VERTICES(ctx, 0);
 
    if (ctx->ClientAttribStackDepth == 0) {
       _mesa_error( ctx, GL_STACK_UNDERFLOW, "glPopClientAttrib" );
@@ -1507,7 +1577,6 @@ _mesa_PopClientAttrib(void)
                copy_pixelstore(ctx, &ctx->Pack, store);
                _mesa_reference_buffer_object(ctx, &store->BufferObj, NULL);
             }
-           ctx->NewState |= _NEW_PACKUNPACK;
             break;
          case GL_CLIENT_UNPACK_BIT:
             {
@@ -1516,7 +1585,6 @@ _mesa_PopClientAttrib(void)
                copy_pixelstore(ctx, &ctx->Unpack, store);
                _mesa_reference_buffer_object(ctx, &store->BufferObj, NULL);
             }
-           ctx->NewState |= _NEW_PACKUNPACK;
             break;
          case GL_CLIENT_VERTEX_ARRAY_BIT: {
            struct gl_array_attrib * attr =
@@ -1532,26 +1600,13 @@ _mesa_PopClientAttrib(void)
       }
 
       next = node->next;
-      FREE( node->data );
-      FREE( node );
+      free(node->data);
+      free(node);
       node = next;
    }
 }
 
 
-void
-_mesa_init_attrib_dispatch(struct _glapi_table *disp)
-{
-   SET_PopAttrib(disp, _mesa_PopAttrib);
-   SET_PushAttrib(disp, _mesa_PushAttrib);
-   SET_PopClientAttrib(disp, _mesa_PopClientAttrib);
-   SET_PushClientAttrib(disp, _mesa_PushClientAttrib);
-}
-
-
-#endif /* FEATURE_attrib_stack */
-
-
 /**
  * Free any attribute state data that might be attached to the context.
  */
@@ -1574,6 +1629,7 @@ _mesa_free_attrib_data(struct gl_context *ctx)
                   _mesa_reference_texobj(&texstate->SavedTexRef[u][tgt], NULL);
                }
             }
+            _mesa_reference_shared_state(ctx, &texstate->SharedRef, NULL);
          }
          else {
             /* any other chunks of state that requires special handling? */