pingou / rpms / mesa

Forked from rpms/mesa 6 years ago
Clone
Blob Blame History Raw
Brian (21):
      added md5 sums
      fix even-sized point positioning (bug 11874)
      Merge branch 'mesa_7_0_branch' of git+ssh://brianp@git.freedesktop.org/git/mesa/mesa into mesa_7_0_branch
      fix bug 9962 (vbo splitting) as in trunk
      initial 7.0.2 notes
      fix swizzle error test (bug 11881)
      fix potential NULL dereference (bug 11880)
      remove SHELL line, replace -e test with new logic (Daniel Stone)
      fix potential NULL dereference (bug 11879)
      move free() after dereference (bug 11878)
      fix byte swap bug for GLuint stencil indexes (bug 11909)
      fix link to 7.0.1 relnotes
      Implement mutex/locking around texture object reference counting.
      free any render/framebuffers left in hash tables when freeing shared state
      Add PCI IDs for the G33, Q33, and Q35 chipsets.
      added more i915/945 chipsets
      fix blending/banding bug
      Fix a few more problems with freeing FBOs/textures during context destruction.
      added some temporary texobj ref counting debug output
      more tex obj ref count debugging (temporary)
      Added _mesa_free_attrib_data() to free anything left in the attribute stack upon context destruction.

Dan Torop (1):
      fix spantmp2 READ_RGBA inline asm (#11931)

Michel Dänzer (1):
      i915tex: Make sure pitch is aligned properly for render-to-texture.

Wang Zhenyu (1):
      i915tex: Add support for 945GME

diff --git a/Makefile b/Makefile
index 3cab262..56efa83 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,5 @@
 # Top-level Mesa makefile
 
-SHELL = /bin/bash
-
 TOP = .
 
 SUBDIRS = src progs
@@ -156,7 +154,7 @@ sunos5-v9 \
 sunos5-v9-static \
 sunos5-v9-cc-g++ \
 ultrix-gcc:
-	@ if [ -e configs/current ] ; then \
+	@ if test -f configs/current || test -L configs/current ; then \
 		echo "Please run 'make realclean' before changing configs" ; \
 		exit 1 ; \
 	fi
diff --git a/docs/news.html b/docs/news.html
index 1f66d4e..e5f2adb 100644
--- a/docs/news.html
+++ b/docs/news.html
@@ -13,7 +13,7 @@
 
 <h2>August 3, 2007</h2>
 <p>
-<a href="relnotes-7.0.html">Mesa 7.0.1</a> is released.
+<a href="relnotes-7.0.1.html">Mesa 7.0.1</a> is released.
 This is a bug-fix release.
 </p>
 
diff --git a/docs/relnotes-7.0.1.html b/docs/relnotes-7.0.1.html
index 47ee162..02713ad 100644
--- a/docs/relnotes-7.0.1.html
+++ b/docs/relnotes-7.0.1.html
@@ -17,6 +17,15 @@ Mesa 7.0.1 is a stable release with bug fixes since version 7.0.
 
 <h2>MD5 checksums</h2>
 <pre>
+db55141a44b902fcc61d9265b7862c06  MesaLib-7.0.1.tar.gz
+c056abd763e899114bf745c9eedbf9ad  MesaLib-7.0.1.tar.bz2
+ecc2637547fae2b38271ae362d013afa  MesaLib-7.0.1.zip
+b85a4a5be4e829f4a1165e4514b13183  MesaDemos-7.0.1.tar.gz
+3b66b3268df12ca8a6c4e0c4c457912c  MesaDemos-7.0.1.tar.bz2
+b1c18006f16e44e80fea66774c59b391  MesaDemos-7.0.1.zip
+b87a69986839ae43ce12fc8e3dc1ebb4  MesaGLUT-7.0.1.tar.gz
+25f30d0c1651997b4412366ba0572f7f  MesaGLUT-7.0.1.tar.bz2
+676ee6682a6ce78a5540554fd975c03e  MesaGLUT-7.0.1.zip
 </pre>
 
 
diff --git a/docs/relnotes-7.0.2.html b/docs/relnotes-7.0.2.html
new file mode 100644
index 0000000..f1fd3d2
--- /dev/null
+++ b/docs/relnotes-7.0.2.html
@@ -0,0 +1,70 @@
+<HTML>
+
+<TITLE>Mesa Release Notes</TITLE>
+
+<head><link rel="stylesheet" type="text/css" href="mesa.css"></head>
+
+<BODY>
+
+<body bgcolor="#eeeeee">
+
+<H1>Mesa 7.0.2 Release Notes / (TBD) 2007</H1>
+
+<p>
+Mesa 7.0.2 is a stable release with bug fixes since version 7.0.
+</p>
+
+
+<h2>MD5 checksums</h2>
+<pre>
+</pre>
+
+
+<h2>New features</h2>
+<ul>
+</ul>
+
+<h2>Bug fixes</h2>
+<ul>
+<li>Fixed a vertex buffer wrapping issue (bug 9962)
+<li>Added mutex protection around texture object reference counters
+<li>Added checking/support for additional chips in the i915/i945 family
+(see 11978)
+<li>Fixed a blending/banding issue (bug 11931)
+</ul>
+
+
+<h2>Changes</h2>
+<ul>
+</ul>
+
+
+<h2>To Do (someday) items</h2>
+<ul>
+<li>Switch to freeglut
+<li>Fix linux-glide target/driver.
+<li>Improved lambda and derivative calculation for frag progs.
+</ul>
+
+
+<h2>Driver Status</h2>
+
+<pre>
+Driver			Status
+----------------------	----------------------
+DRI drivers		varies with the driver
+XMesa/GLX (on Xlib)	implements OpenGL 2.1
+OSMesa (off-screen)	implements OpenGL 2.1
+Windows/Win32		implements OpenGL 2.1
+Glide (3dfx Voodoo1/2)	implements OpenGL 1.3
+SVGA			unsupported
+Wind River UGL		unsupported
+DJGPP			unsupported
+GGI			unsupported
+BeOS			unsupported
+Allegro			unsupported
+D3D			unsupported
+</pre>
+
+</body>
+</html>
diff --git a/docs/relnotes.html b/docs/relnotes.html
index 9a978d9..7464f5c 100644
--- a/docs/relnotes.html
+++ b/docs/relnotes.html
@@ -20,6 +20,7 @@ The release notes summarize what's new or changed in each Mesa release.
 </p>
 
 <UL>
+<LI><A HREF="relnotes-7.0.2.html">7.0.2 release notes</A>
 <LI><A HREF="relnotes-7.0.1.html">7.0.1 release notes</A>
 <LI><A HREF="relnotes-7.0.html">7.0 release notes</A>
 <LI><A HREF="relnotes-6.5.3.html">6.5.3 release notes</A>
diff --git a/src/mesa/drivers/dri/common/spantmp2.h b/src/mesa/drivers/dri/common/spantmp2.h
index 50f3cf5..53f5f84 100644
--- a/src/mesa/drivers/dri/common/spantmp2.h
+++ b/src/mesa/drivers/dri/common/spantmp2.h
@@ -114,7 +114,7 @@
     do {                                                                \
         GLuint p = *(volatile GLuint *) GET_PTR(_x, _y);                \
        __asm__ __volatile__( "bswap	%0; rorl $8, %0"                \
-				: "=r" (p) : "r" (p) );                 \
+				: "=r" (p) : "0" (p) );                 \
        ((GLuint *)rgba)[0] = p;                                         \
     } while (0)
 # elif defined( MESA_BIG_ENDIAN )
diff --git a/src/mesa/drivers/dri/i810/i810screen.c b/src/mesa/drivers/dri/i810/i810screen.c
index f64c10a..f8cf050 100644
--- a/src/mesa/drivers/dri/i810/i810screen.c
+++ b/src/mesa/drivers/dri/i810/i810screen.c
@@ -288,8 +288,8 @@ i810InitDriver(__DRIscreenPrivate *sPriv)
 	      i810Screen->depth.handle,
 	      i810Screen->depth.size,
 	      (drmAddress *)&i810Screen->depth.map) != 0) {
-      FREE(i810Screen);
       drmUnmap(i810Screen->back.map, i810Screen->back.size);
+      FREE(i810Screen);
       sPriv->private = NULL;
       __driUtilMessage("i810InitDriver: drmMap (2) failed");
       return GL_FALSE;
diff --git a/src/mesa/drivers/dri/i915/i915_texstate.c b/src/mesa/drivers/dri/i915/i915_texstate.c
index 9f0c949..a19d4b6 100644
--- a/src/mesa/drivers/dri/i915/i915_texstate.c
+++ b/src/mesa/drivers/dri/i915/i915_texstate.c
@@ -491,12 +491,19 @@ static void i915SetTexImages( i915ContextPtr i915,
       abort();
    }
 
-
-   if (i915->intel.intelScreen->deviceID == PCI_CHIP_I945_G ||
-       i915->intel.intelScreen->deviceID == PCI_CHIP_I945_GM)
-      i945LayoutTextureImages( i915, tObj );	 
-   else
-      i915LayoutTextureImages( i915, tObj );
+   switch (i915->intel.intelScreen->deviceID) {
+   case PCI_CHIP_I945_G:
+   case PCI_CHIP_I945_GM:
+   case PCI_CHIP_I945_GME:
+   case PCI_CHIP_G33_G:
+   case PCI_CHIP_Q33_G:
+   case PCI_CHIP_Q35_G:
+       i945LayoutTextureImages( i915, tObj );
+       break;
+   default:
+       i915LayoutTextureImages( i915, tObj );
+       break;
+   }
 
    t->Setup[I915_TEXREG_MS3] = 
       (((tObj->Image[0][t->intel.base.firstLevel]->Height - 1) << MS3_HEIGHT_SHIFT) |
diff --git a/src/mesa/drivers/dri/i915/intel_context.c b/src/mesa/drivers/dri/i915/intel_context.c
index e1e7cdb..bb5ce64 100644
--- a/src/mesa/drivers/dri/i915/intel_context.c
+++ b/src/mesa/drivers/dri/i915/intel_context.c
@@ -123,6 +123,14 @@ const GLubyte *intelGetString( GLcontext *ctx, GLenum name )
 	 chipset = "Intel(R) 945G"; break;
       case PCI_CHIP_I945_GM:
 	 chipset = "Intel(R) 945GM"; break;
+      case PCI_CHIP_I945_GME:
+	 chipset = "Intel(R) 945GME"; break;
+      case PCI_CHIP_G33_G:
+	 chipset = "Intel(R) G33"; break;
+      case PCI_CHIP_Q35_G:
+	 chipset = "Intel(R) Q35"; break;
+      case PCI_CHIP_Q33_G:
+	 chipset = "Intel(R) Q33"; break;
       default:
 	 chipset = "Unknown Intel Chipset"; break;
       }
diff --git a/src/mesa/drivers/dri/i915/intel_context.h b/src/mesa/drivers/dri/i915/intel_context.h
index 05195e7..50e6178 100644
--- a/src/mesa/drivers/dri/i915/intel_context.h
+++ b/src/mesa/drivers/dri/i915/intel_context.h
@@ -454,6 +454,10 @@ extern int INTEL_DEBUG;
 #define PCI_CHIP_I915_GM		0x2592
 #define PCI_CHIP_I945_G			0x2772
 #define PCI_CHIP_I945_GM		0x27A2
+#define PCI_CHIP_I945_GME		0x27AE
+#define PCI_CHIP_G33_G			0x29C2
+#define PCI_CHIP_Q35_G			0x29B2
+#define PCI_CHIP_Q33_G			0x29D2
 
 
 /* ================================================================
diff --git a/src/mesa/drivers/dri/i915/intel_screen.c b/src/mesa/drivers/dri/i915/intel_screen.c
index 67e176a..ca8610b 100644
--- a/src/mesa/drivers/dri/i915/intel_screen.c
+++ b/src/mesa/drivers/dri/i915/intel_screen.c
@@ -514,6 +514,10 @@ static GLboolean intelCreateContext( const __GLcontextModes *mesaVis,
    case PCI_CHIP_I915_GM:
    case PCI_CHIP_I945_G:
    case PCI_CHIP_I945_GM:
+   case PCI_CHIP_I945_GME:
+   case PCI_CHIP_G33_G:
+   case PCI_CHIP_Q35_G:
+   case PCI_CHIP_Q33_G:
       return i915CreateContext( mesaVis, driContextPriv, 
 			       sharedContextPrivate );
  
diff --git a/src/mesa/drivers/dri/i915/intel_tex.c b/src/mesa/drivers/dri/i915/intel_tex.c
index 98ddc79..5bd2806 100644
--- a/src/mesa/drivers/dri/i915/intel_tex.c
+++ b/src/mesa/drivers/dri/i915/intel_tex.c
@@ -677,7 +677,11 @@ static void intelUploadTexImage( intelContextPtr intel,
    /* Time for another vtbl entry:
     */
    else if (intel->intelScreen->deviceID == PCI_CHIP_I945_G ||
-            intel->intelScreen->deviceID == PCI_CHIP_I945_GM) {
+            intel->intelScreen->deviceID == PCI_CHIP_I945_GM ||
+            intel->intelScreen->deviceID == PCI_CHIP_I945_GME ||
+            intel->intelScreen->deviceID == PCI_CHIP_G33_G ||
+            intel->intelScreen->deviceID == PCI_CHIP_Q33_G ||
+            intel->intelScreen->deviceID == PCI_CHIP_Q35_G) {
       GLuint row_len = image->Width * image->TexFormat->TexelBytes;
       GLubyte *dst = (GLubyte *)(t->BufAddr + offset);
       GLubyte *src = (GLubyte *)image->Data;
diff --git a/src/mesa/drivers/dri/i915tex/intel_context.c b/src/mesa/drivers/dri/i915tex/intel_context.c
index 093b3b4..40ea756 100644
--- a/src/mesa/drivers/dri/i915tex/intel_context.c
+++ b/src/mesa/drivers/dri/i915tex/intel_context.c
@@ -130,6 +130,18 @@ intelGetString(GLcontext * ctx, GLenum name)
       case PCI_CHIP_I945_GM:
          chipset = "Intel(R) 945GM";
          break;
+      case PCI_CHIP_I945_GME:
+         chipset = "Intel(R) 945GME";
+         break;
+      case PCI_CHIP_G33_G:
+	 chipset = "Intel(R) G33";
+	 break;
+      case PCI_CHIP_Q35_G:
+	 chipset = "Intel(R) Q35";
+	 break;
+      case PCI_CHIP_Q33_G:
+	 chipset = "Intel(R) Q33";
+	 break;
       default:
          chipset = "Unknown Intel Chipset";
          break;
diff --git a/src/mesa/drivers/dri/i915tex/intel_context.h b/src/mesa/drivers/dri/i915tex/intel_context.h
index bcbbb12..5fc8eb3 100644
--- a/src/mesa/drivers/dri/i915tex/intel_context.h
+++ b/src/mesa/drivers/dri/i915tex/intel_context.h
@@ -385,6 +385,10 @@ extern int INTEL_DEBUG;
 #define PCI_CHIP_I915_GM		0x2592
 #define PCI_CHIP_I945_G			0x2772
 #define PCI_CHIP_I945_GM		0x27A2
+#define PCI_CHIP_I945_GME		0x27AE
+#define PCI_CHIP_G33_G			0x29C2
+#define PCI_CHIP_Q35_G			0x29B2
+#define PCI_CHIP_Q33_G			0x29D2
 
 
 /* ================================================================
diff --git a/src/mesa/drivers/dri/i915tex/intel_mipmap_tree.c b/src/mesa/drivers/dri/i915tex/intel_mipmap_tree.c
index 8e83028..6c28543 100644
--- a/src/mesa/drivers/dri/i915tex/intel_mipmap_tree.c
+++ b/src/mesa/drivers/dri/i915tex/intel_mipmap_tree.c
@@ -79,6 +79,10 @@ intel_miptree_create(struct intel_context *intel,
    switch (intel->intelScreen->deviceID) {
    case PCI_CHIP_I945_G:
    case PCI_CHIP_I945_GM:
+   case PCI_CHIP_I945_GME:
+   case PCI_CHIP_G33_G:
+   case PCI_CHIP_Q33_G:
+   case PCI_CHIP_Q35_G:
       ok = i945_miptree_layout(mt);
       break;
    case PCI_CHIP_I915_G:
@@ -93,9 +97,19 @@ intel_miptree_create(struct intel_context *intel,
       break;
    }
 
-   if (ok)
+   if (ok) {
+      if (!mt->compressed) {
+	 /* XXX: Align pitch to multiple of 64 bytes for now to allow
+	  * render-to-texture to work in all cases. This should probably be
+	  * replaced at some point by some scheme to only do this when really
+	  * necessary.
+	  */
+	 mt->pitch = ((mt->pitch * cpp + 63) & ~63) / cpp;
+      }
+
       mt->region = intel_region_alloc(intel->intelScreen,
                                       mt->cpp, mt->pitch, mt->total_height);
+   }
 
    if (!mt->region) {
       free(mt);
diff --git a/src/mesa/drivers/dri/i915tex/intel_screen.c b/src/mesa/drivers/dri/i915tex/intel_screen.c
index 5e6df81..2acdead 100644
--- a/src/mesa/drivers/dri/i915tex/intel_screen.c
+++ b/src/mesa/drivers/dri/i915tex/intel_screen.c
@@ -752,6 +752,10 @@ intelCreateContext(const __GLcontextModes * mesaVis,
    case PCI_CHIP_I915_GM:
    case PCI_CHIP_I945_G:
    case PCI_CHIP_I945_GM:
+   case PCI_CHIP_I945_GME:
+   case PCI_CHIP_G33_G:
+   case PCI_CHIP_Q35_G:
+   case PCI_CHIP_Q33_G:
       return i915CreateContext(mesaVis, driContextPriv, sharedContextPrivate);
 
    default:
diff --git a/src/mesa/drivers/dri/unichrome/via_context.c b/src/mesa/drivers/dri/unichrome/via_context.c
index 4d25d32..7c73877 100644
--- a/src/mesa/drivers/dri/unichrome/via_context.c
+++ b/src/mesa/drivers/dri/unichrome/via_context.c
@@ -733,14 +733,15 @@ void viaXMesaWindowMoved(struct via_context *vmesa)
 {
    __DRIdrawablePrivate *const drawable = vmesa->driDrawable;
    __DRIdrawablePrivate *const readable = vmesa->driReadable;
-   struct via_renderbuffer *const draw_buffer = 
-     (struct via_renderbuffer *) drawable->driverPrivate;
-   struct via_renderbuffer *const read_buffer =
-     (struct via_renderbuffer *) readable->driverPrivate;
+   struct via_renderbuffer * draw_buffer;
+   struct via_renderbuffer * read_buffer;
    GLuint bytePerPixel = vmesa->viaScreen->bitsPerPixel >> 3;
 
    if (!drawable)
       return;
+
+   draw_buffer =  (struct via_renderbuffer *) drawable->driverPrivate;
+   read_buffer =  (struct via_renderbuffer *) readable->driverPrivate;
    
    switch (vmesa->glCtx->DrawBuffer->_ColorDrawBufferMask[0]) {
    case BUFFER_BIT_BACK_LEFT: 
diff --git a/src/mesa/main/attrib.c b/src/mesa/main/attrib.c
index 0b821cf..df40b88 100644
--- a/src/mesa/main/attrib.c
+++ b/src/mesa/main/attrib.c
@@ -342,6 +342,12 @@ _mesa_PushAttrib(GLbitfield mask)
       /* Bump the texture object reference counts so that they don't
        * inadvertantly get deleted.
        */
+#ifdef DEBUG
+      printf("%lu: MESA PUSH TEX ATTRIB, INCR REF COUNT BY %d\n",
+             _glthread_GetID(),
+             ctx->Const.MaxTextureUnits);
+#endif
+
       for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
 	 ctx->Texture.Unit[u].Current1D->RefCount++;
 	 ctx->Texture.Unit[u].Current2D->RefCount++;
@@ -349,6 +355,7 @@ _mesa_PushAttrib(GLbitfield mask)
 	 ctx->Texture.Unit[u].CurrentCubeMap->RefCount++;
 	 ctx->Texture.Unit[u].CurrentRect->RefCount++;
       }
+
       attr = MALLOC_STRUCT( gl_texture_attrib );
       MEMCPY( attr, &ctx->Texture, sizeof(struct gl_texture_attrib) );
       /* copy state of the currently bound texture objects */
@@ -792,6 +799,11 @@ pop_texture_group(GLcontext *ctx, const struct gl_texture_attrib *texAttrib)
     * wouldn't inadvertantly get deleted while they were still referenced
     * inside the attribute state stack.
     */
+#ifdef DEBUG
+   printf("%lu: MESA POP TEX ATTRIB, DECR REF COUNT BY %d\n",
+          _glthread_GetID(),
+          ctx->Const.MaxTextureUnits);
+#endif
    for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
       ctx->Texture.Unit[u].Current1D->RefCount--;
       ctx->Texture.Unit[u].Current2D->RefCount--;
@@ -1401,6 +1413,84 @@ _mesa_PopClientAttrib(void)
 }
 
 
+static struct gl_texture_object *
+get_texobj(GLcontext *ctx, GLenum target, GLuint name)
+{
+   struct gl_texture_object *texObj;
+   if (name) {
+      texObj = _mesa_lookup_texture(ctx, name);
+   }
+   else {
+      switch (target) {
+      case GL_TEXTURE_1D:
+         texObj = ctx->Shared->Default1D;
+         break;
+      case GL_TEXTURE_2D:
+         texObj = ctx->Shared->Default2D;
+         break;
+      case GL_TEXTURE_3D:
+         texObj = ctx->Shared->Default3D;
+         break;
+      case GL_TEXTURE_CUBE_MAP_ARB:
+         texObj = ctx->Shared->DefaultCubeMap;
+         break;
+      case GL_TEXTURE_RECTANGLE_NV:
+         texObj = ctx->Shared->DefaultRect;
+         break;
+      default:
+         abort();
+      }
+   }
+   return texObj;
+}
+
+
+void
+_mesa_free_attrib_data(GLcontext *ctx)
+{
+#ifdef DEBUG
+   printf("%lu: MESA FREEING ATTRIB STACK DATA\n",
+          _glthread_GetID());
+#endif
+   while (ctx->AttribStackDepth > 0) {
+      struct gl_attrib_node *attr, *next;
+
+      ctx->AttribStackDepth--;
+      attr = ctx->AttribStack[ctx->AttribStackDepth];
+
+      while (attr) {
+         struct gl_texture_attrib *texAttrib
+            = (struct gl_texture_attrib *) attr->data;
+         GLuint u;
+
+         for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
+            struct gl_texture_unit *unit = &texAttrib->Unit[u];
+            struct gl_texture_object *texObj;
+            texObj = get_texobj(ctx, GL_TEXTURE_1D, unit->Saved1D.Name);
+            MESA_REF_TEXOBJ(&texObj, NULL);
+            texObj = get_texobj(ctx, GL_TEXTURE_2D, unit->Saved2D.Name);
+            MESA_REF_TEXOBJ(&texObj, NULL);
+            texObj = get_texobj(ctx, GL_TEXTURE_3D, unit->Saved3D.Name);
+            MESA_REF_TEXOBJ(&texObj, NULL);
+            texObj = get_texobj(ctx, GL_TEXTURE_CUBE_MAP, unit->SavedCubeMap.Name);
+            MESA_REF_TEXOBJ(&texObj, NULL);
+            texObj = get_texobj(ctx, GL_TEXTURE_RECTANGLE_NV, unit->SavedRect.Name);
+            MESA_REF_TEXOBJ(&texObj, NULL);
+         }
+
+         next = attr->next;
+         _mesa_free(attr->data);
+         _mesa_free(attr);
+         attr = next;
+      }
+   }
+#ifdef DEBUG
+   printf("%lu: MESA DONE FREEING ATTRIB STACK DATA\n",
+          _glthread_GetID());
+#endif
+}
+
+
 void _mesa_init_attrib( GLcontext *ctx )
 {
    /* Renderer and client attribute stacks */
diff --git a/src/mesa/main/attrib.h b/src/mesa/main/attrib.h
index 09d7519..ea28859 100644
--- a/src/mesa/main/attrib.h
+++ b/src/mesa/main/attrib.h
@@ -58,10 +58,14 @@ _mesa_PopClientAttrib( void );
 extern void 
 _mesa_init_attrib( GLcontext *ctx );
 
+extern void 
+_mesa_free_attrib_data( GLcontext *ctx );
+
 #else
 
 /** No-op */
 #define _mesa_init_attrib( c ) ((void)0)
+#define _mesa_free_attrib_data( c ) ((void)0)
 
 #endif
 
diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c
index e067840..64f3a7f 100644
--- a/src/mesa/main/context.c
+++ b/src/mesa/main/context.c
@@ -467,17 +467,12 @@ alloc_shared_state( GLcontext *ctx )
    if (!ss->DefaultRect)
       goto cleanup;
 
-   /* Effectively bind the default textures to all texture units */
-   ss->Default1D->RefCount += MAX_TEXTURE_IMAGE_UNITS;
-   ss->Default2D->RefCount += MAX_TEXTURE_IMAGE_UNITS;
-   ss->Default3D->RefCount += MAX_TEXTURE_IMAGE_UNITS;
-   ss->DefaultCubeMap->RefCount += MAX_TEXTURE_IMAGE_UNITS;
-   ss->DefaultRect->RefCount += MAX_TEXTURE_IMAGE_UNITS;
+   /* sanity check */
+   assert(ss->Default1D->RefCount == 1);
 
    _glthread_INIT_MUTEX(ss->TexMutex);
    ss->TextureStateStamp = 0;
 
-
 #if FEATURE_EXT_framebuffer_object
    ss->FrameBuffers = _mesa_NewHashTable();
    if (!ss->FrameBuffers)
@@ -487,10 +482,9 @@ alloc_shared_state( GLcontext *ctx )
       goto cleanup;
 #endif
 
-
    return GL_TRUE;
 
- cleanup:
+cleanup:
    /* Ran out of memory at some point.  Free everything and return NULL */
    if (ss->DisplayList)
       _mesa_DeleteHashTable(ss->DisplayList);
@@ -567,6 +561,10 @@ delete_texture_cb(GLuint id, void *data, void *userData)
 {
    struct gl_texture_object *texObj = (struct gl_texture_object *) data;
    GLcontext *ctx = (GLcontext *) userData;
+#ifdef DEBUG
+   printf("MESA TEX DELETE %p (%u) from DestroyContext\n",
+          (void *) texObj, texObj->Name);
+#endif
    ctx->Driver.DeleteTexture(ctx, texObj);
 }
 
@@ -634,6 +632,33 @@ delete_shader_cb(GLuint id, void *data, void *userData)
    }
 }
 
+/**
+ * Callback for deleting a framebuffer object.  Called by _mesa_HashDeleteAll()
+ */
+static void
+delete_framebuffer_cb(GLuint id, void *data, void *userData)
+{
+   struct gl_framebuffer *fb = (struct gl_framebuffer *) data;
+   /* The fact that the framebuffer is in the hashtable means its refcount
+    * is one, but we're removing from the hashtable now.  So clear refcount.
+    */
+   /*assert(fb->RefCount == 1);*/
+   fb->RefCount = 0;
+   fb->Delete(fb);
+}
+
+/**
+ * Callback for deleting a renderbuffer object. Called by _mesa_HashDeleteAll()
+ */
+static void
+delete_renderbuffer_cb(GLuint id, void *data, void *userData)
+{
+   struct gl_renderbuffer *rb = (struct gl_renderbuffer *) data;
+   rb->RefCount = 0;  /* see comment for FBOs above */
+   rb->Delete(rb);
+}
+
+
 
 /**
  * Deallocate a shared state object and all children structures.
@@ -656,20 +681,6 @@ free_shared_state( GLcontext *ctx, struct gl_shared_state *ss )
    _mesa_HashDeleteAll(ss->DisplayList, delete_displaylist_cb, ctx);
    _mesa_DeleteHashTable(ss->DisplayList);
 
-   /*
-    * Free texture objects
-    */
-   ASSERT(ctx->Driver.DeleteTexture);
-   /* the default textures */
-   ctx->Driver.DeleteTexture(ctx, ss->Default1D);
-   ctx->Driver.DeleteTexture(ctx, ss->Default2D);
-   ctx->Driver.DeleteTexture(ctx, ss->Default3D);
-   ctx->Driver.DeleteTexture(ctx, ss->DefaultCubeMap);
-   ctx->Driver.DeleteTexture(ctx, ss->DefaultRect);
-   /* all other textures */
-   _mesa_HashDeleteAll(ss->TexObjects, delete_texture_cb, ctx);
-   _mesa_DeleteHashTable(ss->TexObjects);
-
 #if defined(FEATURE_NV_vertex_program) || defined(FEATURE_NV_fragment_program)
    _mesa_HashDeleteAll(ss->Programs, delete_program_cb, ctx);
    _mesa_DeleteHashTable(ss->Programs);
@@ -701,10 +712,27 @@ free_shared_state( GLcontext *ctx, struct gl_shared_state *ss )
 #endif
 
 #if FEATURE_EXT_framebuffer_object
+   _mesa_HashDeleteAll(ss->FrameBuffers, delete_framebuffer_cb, ctx);
    _mesa_DeleteHashTable(ss->FrameBuffers);
+   _mesa_HashDeleteAll(ss->RenderBuffers, delete_renderbuffer_cb, ctx);
    _mesa_DeleteHashTable(ss->RenderBuffers);
 #endif
 
+   /*
+    * Free texture objects (after FBOs since some textures might have
+    * been bound to FBOs).
+    */
+   ASSERT(ctx->Driver.DeleteTexture);
+   /* the default textures */
+   ctx->Driver.DeleteTexture(ctx, ss->Default1D);
+   ctx->Driver.DeleteTexture(ctx, ss->Default2D);
+   ctx->Driver.DeleteTexture(ctx, ss->Default3D);
+   ctx->Driver.DeleteTexture(ctx, ss->DefaultCubeMap);
+   ctx->Driver.DeleteTexture(ctx, ss->DefaultRect);
+   /* all other textures */
+   _mesa_HashDeleteAll(ss->TexObjects, delete_texture_cb, ctx);
+   _mesa_DeleteHashTable(ss->TexObjects);
+
    _glthread_DESTROY_MUTEX(ss->Mutex);
 
    _mesa_free(ss);
@@ -1157,18 +1185,27 @@ _mesa_create_context(const GLvisual *visual,
 void
 _mesa_free_context_data( GLcontext *ctx )
 {
-   /* if we're destroying the current context, unbind it first */
-   if (ctx == _mesa_get_current_context()) {
-      _mesa_make_current(NULL, NULL, NULL);
+   if (!_mesa_get_current_context()){
+      /* No current context, but we may need one in order to delete
+       * texture objs, etc.  So temporarily bind the context now.
+       */
+      _mesa_make_current(ctx, NULL, NULL);
    }
-   else {
-      /* unreference WinSysDraw/Read buffers */
-      _mesa_unreference_framebuffer(&ctx->WinSysDrawBuffer);
-      _mesa_unreference_framebuffer(&ctx->WinSysReadBuffer);
-      _mesa_unreference_framebuffer(&ctx->DrawBuffer);
-      _mesa_unreference_framebuffer(&ctx->ReadBuffer);
+
+   if (ctx->AttribStackDepth > 0) {
+#ifdef DEBUG
+      printf("%lu: MESA: DESTROY CONTEXT WITH NON-EMPTRY ATTRIB STACK!\n",
+             _glthread_GetID());
+#endif
    }
 
+   /* unreference WinSysDraw/Read buffers */
+   _mesa_unreference_framebuffer(&ctx->WinSysDrawBuffer);
+   _mesa_unreference_framebuffer(&ctx->WinSysReadBuffer);
+   _mesa_unreference_framebuffer(&ctx->DrawBuffer);
+   _mesa_unreference_framebuffer(&ctx->ReadBuffer);
+
+   _mesa_free_attrib_data(ctx);
    _mesa_free_lighting_data( ctx );
    _mesa_free_eval_data( ctx );
    _mesa_free_texture_data( ctx );
@@ -1200,6 +1237,11 @@ _mesa_free_context_data( GLcontext *ctx )
 
    if (ctx->Extensions.String)
       _mesa_free((void *) ctx->Extensions.String);
+
+   /* unbind the context if it's currently bound */
+   if (ctx == _mesa_get_current_context()) {
+      _mesa_make_current(NULL, NULL, NULL);
+   }
 }
 
 
diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c
index eac2f78..f0e413b 100644
--- a/src/mesa/main/fbobject.c
+++ b/src/mesa/main/fbobject.c
@@ -150,22 +150,18 @@ _mesa_remove_attachment(GLcontext *ctx, struct gl_renderbuffer_attachment *att)
 {
    if (att->Type == GL_TEXTURE) {
       ASSERT(att->Texture);
-      att->Texture->RefCount--;
-      if (att->Texture->RefCount == 0) {
-	 ctx->Driver.DeleteTexture(ctx, att->Texture);
+      if (ctx->Driver.FinishRenderTexture) {
+         /* tell driver we're done rendering to this texobj */
+         ctx->Driver.FinishRenderTexture(ctx, att);
       }
-      else {
-         /* tell driver that we're done rendering to this texture. */
-         if (ctx->Driver.FinishRenderTexture) {
-            ctx->Driver.FinishRenderTexture(ctx, att);
-         }
-      }
-      att->Texture = NULL;
+      MESA_REF_TEXOBJ(&att->Texture, NULL); /* unbind */
+      ASSERT(!att->Texture);
    }
    if (att->Type == GL_TEXTURE || att->Type == GL_RENDERBUFFER_EXT) {
       ASSERT(att->Renderbuffer);
       ASSERT(!att->Texture);
-      _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
+      _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); /* unbind */
+      ASSERT(!att->Renderbuffer);
    }
    att->Type = GL_NONE;
    att->Complete = GL_TRUE;
@@ -191,8 +187,8 @@ _mesa_set_texture_attachment(GLcontext *ctx,
       /* new attachment */
       _mesa_remove_attachment(ctx, att);
       att->Type = GL_TEXTURE;
-      att->Texture = texObj;
-      texObj->RefCount++;
+      assert(!att->Texture);
+      MESA_REF_TEXOBJ(&att->Texture, texObj);
    }
 
    /* always update these fields */
diff --git a/src/mesa/main/framebuffer.c b/src/mesa/main/framebuffer.c
index 1fd31a5..09f0994 100644
--- a/src/mesa/main/framebuffer.c
+++ b/src/mesa/main/framebuffer.c
@@ -38,6 +38,7 @@
 #include "fbobject.h"
 #include "framebuffer.h"
 #include "renderbuffer.h"
+#include "texobj.h"
 
 
 
@@ -190,17 +191,11 @@ _mesa_free_framebuffer_data(struct gl_framebuffer *fb)
          _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
       }
       if (att->Texture) {
-         /* render to texture */
-         att->Texture->RefCount--;
-         if (att->Texture->RefCount == 0) {
-            GET_CURRENT_CONTEXT(ctx);
-            if (ctx) {
-               ctx->Driver.DeleteTexture(ctx, att->Texture);
-            }
-         }
+         MESA_REF_TEXOBJ(&att->Texture, NULL);
       }
+      ASSERT(!att->Renderbuffer);
+      ASSERT(!att->Texture);
       att->Type = GL_NONE;
-      att->Texture = NULL;
    }
 
    /* unbind _Depth/_StencilBuffer to decr ref counts */
diff --git a/src/mesa/main/image.c b/src/mesa/main/image.c
index 803f478..d7a96f7 100644
--- a/src/mesa/main/image.c
+++ b/src/mesa/main/image.c
@@ -3794,7 +3794,7 @@ _mesa_pack_stencil_span( const GLcontext *ctx, GLuint n,
          GLint *dst = (GLint *) dest;
          GLuint i;
          for (i=0;i<n;i++) {
-            *dst++ = (GLint) source[i];
+            dst[i] = (GLint) source[i];
          }
          if (dstPacking->SwapBytes) {
             _mesa_swap4( (GLuint *) dst, n );
diff --git a/src/mesa/main/texobj.c b/src/mesa/main/texobj.c
index 56d816e..fa14d91 100644
--- a/src/mesa/main/texobj.c
+++ b/src/mesa/main/texobj.c
@@ -154,8 +154,18 @@ _mesa_delete_texture_object( GLcontext *ctx, struct gl_texture_object *texObj )
 {
    GLuint i, face;
 
+#ifdef DEBUG
+   printf("%lu: MESA TEX DELETE %p (%u) REF COUNT = %d\n",
+          _glthread_GetID(),
+          (void*) texObj, texObj->Name, texObj->RefCount);
+#endif
    (void) ctx;
 
+   /* Set Target to an invalid value.  With some assertions elsewhere
+    * we can try to detect possible use of deleted textures.
+    */
+   texObj->Target = 0x99;
+
    _mesa_free_colortable_data(&texObj->Palette);
 
    /* free the texture images */
@@ -220,6 +230,106 @@ _mesa_copy_texture_object( struct gl_texture_object *dest,
 
 
 /**
+ * Check if the given texture object is valid by examining its Target field.
+ * For debugging only.
+ */
+static GLboolean
+valid_texture_object(const struct gl_texture_object *tex)
+{
+   switch (tex->Target) {
+   case 0:
+   case GL_TEXTURE_1D:
+   case GL_TEXTURE_2D:
+   case GL_TEXTURE_3D:
+   case GL_TEXTURE_CUBE_MAP_ARB:
+   case GL_TEXTURE_RECTANGLE_NV:
+      return GL_TRUE;
+   case 0x99:
+      _mesa_problem(NULL, "invalid reference to a deleted texture object");
+      return GL_FALSE;
+   default:
+      _mesa_problem(NULL, "invalid texture object Target value");
+      return GL_FALSE;
+   }
+}
+
+
+/**
+ * Reference (or unreference) a texture object.
+ * If '*ptr', decrement *ptr's refcount (and delete if it becomes zero).
+ * If 'tex' is non-null, increment its refcount.
+ */
+void
+_mesa_reference_texobj(struct gl_texture_object **ptr,
+                       struct gl_texture_object *tex,
+                       const char *where)
+{
+   assert(ptr);
+   if (*ptr == tex) {
+      /* no change */
+      return;
+   }
+
+   if (*ptr) {
+      /* Unreference the old texture */
+      GLboolean deleteFlag = GL_FALSE;
+      struct gl_texture_object *oldTex = *ptr;
+
+      assert(valid_texture_object(oldTex));
+
+      _glthread_LOCK_MUTEX(oldTex->Mutex);
+      ASSERT(oldTex->RefCount > 0);
+      oldTex->RefCount--;
+
+#ifdef DEBUG
+      printf("%lu: MESA TEX REF DECR %p (%u) to %d from %s\n",
+             _glthread_GetID(),
+             (void*) oldTex, oldTex->Name, oldTex->RefCount, where);
+#endif
+
+      deleteFlag = (oldTex->RefCount == 0);
+      _glthread_UNLOCK_MUTEX(oldTex->Mutex);
+
+      if (deleteFlag) {
+         GET_CURRENT_CONTEXT(ctx);
+         if (ctx)
+            ctx->Driver.DeleteTexture(ctx, oldTex);
+         else
+            _mesa_problem(NULL, "Unable to delete texture, no context");
+      }
+
+      *ptr = NULL;
+   }
+   assert(!*ptr);
+
+   if (tex) {
+      /* reference new texture */
+      assert(valid_texture_object(tex));
+      _glthread_LOCK_MUTEX(tex->Mutex);
+      if (tex->RefCount == 0) {
+         /* this texture's being deleted (look just above) */
+         /* Not sure this can every really happen.  Warn if it does. */
+         _mesa_problem(NULL, "referencing deleted texture object");
+         *ptr = NULL;
+      }
+      else {
+         tex->RefCount++;
+
+#ifdef DEBUG
+         printf("%lu: MESA TEX REF INCR %p (%u) to %d from %s\n",
+                _glthread_GetID(),
+                (void*) tex, tex->Name, tex->RefCount, where);
+#endif
+
+         *ptr = tex;
+      }
+      _glthread_UNLOCK_MUTEX(tex->Mutex);
+   }
+}
+
+
+
+/**
  * Report why a texture object is incomplete.  
  *
  * \param t texture object.
@@ -620,8 +730,7 @@ unbind_texobj_from_fbo(GLcontext *ctx, struct gl_texture_object *texObj)
 
 /**
  * Check if the given texture object is bound to any texture image units and
- * unbind it if so.
- * XXX all RefCount accesses should be protected by a mutex.
+ * unbind it if so (revert to default textures).
  */
 static void
 unbind_texobj_from_texunits(GLcontext *ctx, struct gl_texture_object *texObj)
@@ -630,34 +739,20 @@ unbind_texobj_from_texunits(GLcontext *ctx, struct gl_texture_object *texObj)
 
    for (u = 0; u < MAX_TEXTURE_IMAGE_UNITS; u++) {
       struct gl_texture_unit *unit = &ctx->Texture.Unit[u];
-      struct gl_texture_object **curr = NULL;
-
       if (texObj == unit->Current1D) {
-         curr = &unit->Current1D;
-         unit->Current1D = ctx->Shared->Default1D;
+         MESA_REF_TEXOBJ(&unit->Current1D, ctx->Shared->Default1D);
       }
       else if (texObj == unit->Current2D) {
-         curr = &unit->Current2D;
-         unit->Current2D = ctx->Shared->Default2D;
+         MESA_REF_TEXOBJ(&unit->Current2D, ctx->Shared->Default2D);
       }
       else if (texObj == unit->Current3D) {
-         curr = &unit->Current3D;
-         unit->Current3D = ctx->Shared->Default3D;
+         MESA_REF_TEXOBJ(&unit->Current3D, ctx->Shared->Default3D);
       }
       else if (texObj == unit->CurrentCubeMap) {
-         curr = &unit->CurrentCubeMap;
-         unit->CurrentCubeMap = ctx->Shared->DefaultCubeMap;
+         MESA_REF_TEXOBJ(&unit->CurrentCubeMap, ctx->Shared->DefaultCubeMap);
       }
       else if (texObj == unit->CurrentRect) {
-         curr = &unit->CurrentRect;
-         unit->CurrentRect = ctx->Shared->DefaultRect;
-      }
-
-      if (curr) {
-         (*curr)->RefCount++;
-         texObj->RefCount--;
-         if (texObj == unit->_Current)
-            unit->_Current = *curr;
+         MESA_REF_TEXOBJ(&unit->CurrentRect, ctx->Shared->DefaultRect);
       }
    }
 }
@@ -693,8 +788,6 @@ _mesa_DeleteTextures( GLsizei n, const GLuint *textures)
             = _mesa_lookup_texture(ctx, textures[i]);
 
          if (delObj) {
-	    GLboolean deleted;
-
 	    _mesa_lock_texture(ctx, delObj);
 
             /* Check if texture is bound to any framebuffer objects.
@@ -704,10 +797,12 @@ _mesa_DeleteTextures( GLsizei n, const GLuint *textures)
             unbind_texobj_from_fbo(ctx, delObj);
 
             /* Check if this texture is currently bound to any texture units.
-             * If so, unbind it and decrement the reference count.
+             * If so, unbind it.
              */
             unbind_texobj_from_texunits(ctx, delObj);
 
+	    _mesa_unlock_texture(ctx, delObj);
+
             ctx->NewState |= _NEW_TEXTURE;
 
             /* The texture _name_ is now free for re-use.
@@ -717,23 +812,10 @@ _mesa_DeleteTextures( GLsizei n, const GLuint *textures)
             _mesa_HashRemove(ctx->Shared->TexObjects, delObj->Name);
             _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
 
-            /* The actual texture object will not be freed until it's no
-             * longer bound in any context.
-             * XXX all RefCount accesses should be protected by a mutex.
+            /* Unreference the texobj.  If refcount hits zero, the texture
+             * will be deleted.
              */
-            delObj->RefCount--;
-	    deleted = (delObj->RefCount == 0);
-	    _mesa_unlock_texture(ctx, delObj);
-
-	    /* We know that refcount went to zero above, so this is
-	     * the only pointer left to delObj, so we don't have to
-	     * worry about locking any more:
-	     */
-            if (deleted) {
-               ASSERT(delObj->Name != 0); /* Never delete default tex objs */
-               ASSERT(ctx->Driver.DeleteTexture);
-               (*ctx->Driver.DeleteTexture)(ctx, delObj);
-            }
+            MESA_REF_TEXOBJ(&delObj, NULL);
          }
       }
    }
@@ -761,7 +843,6 @@ _mesa_BindTexture( GLenum target, GLuint texName )
    GET_CURRENT_CONTEXT(ctx);
    const GLuint unit = ctx->Texture.CurrentUnit;
    struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
-   struct gl_texture_object *oldTexObj;
    struct gl_texture_object *newTexObj = NULL;
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
@@ -770,48 +851,6 @@ _mesa_BindTexture( GLenum target, GLuint texName )
                   _mesa_lookup_enum_by_nr(target), (GLint) texName);
 
    /*
-    * Get pointer to currently bound texture object (oldTexObj)
-    */
-   switch (target) {
-      case GL_TEXTURE_1D:
-         oldTexObj = texUnit->Current1D;
-         break;
-      case GL_TEXTURE_2D:
-         oldTexObj = texUnit->Current2D;
-         break;
-      case GL_TEXTURE_3D:
-         oldTexObj = texUnit->Current3D;
-         break;
-      case GL_TEXTURE_CUBE_MAP_ARB:
-         if (!ctx->Extensions.ARB_texture_cube_map) {
-            _mesa_error( ctx, GL_INVALID_ENUM, "glBindTexture(target)" );
-            return;
-         }
-         oldTexObj = texUnit->CurrentCubeMap;
-         break;
-      case GL_TEXTURE_RECTANGLE_NV:
-         if (!ctx->Extensions.NV_texture_rectangle) {
-            _mesa_error( ctx, GL_INVALID_ENUM, "glBindTexture(target)" );
-            return;
-         }
-         oldTexObj = texUnit->CurrentRect;
-         break;
-      default:
-         _mesa_error( ctx, GL_INVALID_ENUM, "glBindTexture(target)" );
-         return;
-   }
-
-   if (oldTexObj->Name == texName) {
-      /* XXX this might be wrong.  If the texobj is in use by another
-       * context and a texobj parameter was changed, this might be our
-       * only chance to update this context's hardware state.
-       * Note that some applications re-bind the same texture a lot so we
-       * want to handle that case quickly.
-       */
-      return;   /* rebinding the same texture- no change */
-   }
-
-   /*
     * Get pointer to new texture object (newTexObj)
     */
    if (texName == 0) {
@@ -879,28 +918,30 @@ _mesa_BindTexture( GLenum target, GLuint texName )
       newTexObj->Target = target;
    }
 
-   /* XXX all RefCount accesses should be protected by a mutex. */
-   newTexObj->RefCount++;
+   assert(valid_texture_object(newTexObj));
 
-   /* do the actual binding, but first flush outstanding vertices:
-    */
+   /* flush before changing binding */
    FLUSH_VERTICES(ctx, _NEW_TEXTURE);
 
+   /* Do the actual binding.  The refcount on the previously bound
+    * texture object will be decremented.  It'll be deleted if the
+    * count hits zero.
+    */
    switch (target) {
       case GL_TEXTURE_1D:
-         texUnit->Current1D = newTexObj;
+         MESA_REF_TEXOBJ(&texUnit->Current1D, newTexObj);
          break;
       case GL_TEXTURE_2D:
-         texUnit->Current2D = newTexObj;
+         MESA_REF_TEXOBJ(&texUnit->Current2D, newTexObj);
          break;
       case GL_TEXTURE_3D:
-         texUnit->Current3D = newTexObj;
+         MESA_REF_TEXOBJ(&texUnit->Current3D, newTexObj);
          break;
       case GL_TEXTURE_CUBE_MAP_ARB:
-         texUnit->CurrentCubeMap = newTexObj;
+         MESA_REF_TEXOBJ(&texUnit->CurrentCubeMap, newTexObj);
          break;
       case GL_TEXTURE_RECTANGLE_NV:
-         texUnit->CurrentRect = newTexObj;
+         MESA_REF_TEXOBJ(&texUnit->CurrentRect, newTexObj);
          break;
       default:
          _mesa_problem(ctx, "bad target in BindTexture");
@@ -910,18 +951,6 @@ _mesa_BindTexture( GLenum target, GLuint texName )
    /* Pass BindTexture call to device driver */
    if (ctx->Driver.BindTexture)
       (*ctx->Driver.BindTexture)( ctx, target, newTexObj );
-
-   /* Decrement the reference count on the old texture and check if it's
-    * time to delete it.
-    */
-   /* XXX all RefCount accesses should be protected by a mutex. */
-   oldTexObj->RefCount--;
-   ASSERT(oldTexObj->RefCount >= 0);
-   if (oldTexObj->RefCount == 0) {
-      ASSERT(oldTexObj->Name != 0);
-      ASSERT(ctx->Driver.DeleteTexture);
-      (*ctx->Driver.DeleteTexture)( ctx, oldTexObj );
-   }
 }
 
 
diff --git a/src/mesa/main/texobj.h b/src/mesa/main/texobj.h
index ec7cf8c..78e7933 100644
--- a/src/mesa/main/texobj.h
+++ b/src/mesa/main/texobj.h
@@ -57,6 +57,14 @@ extern void
 _mesa_copy_texture_object( struct gl_texture_object *dest,
                            const struct gl_texture_object *src );
 
+#define MESA_REF_TEXOBJ(PTR, TEX) \
+   _mesa_reference_texobj(PTR, TEX, __FUNCTION__)
+
+extern void
+_mesa_reference_texobj(struct gl_texture_object **ptr,
+                       struct gl_texture_object *tex,
+                       const char *where);
+
 extern void
 _mesa_test_texobj_completeness( const GLcontext *ctx,
                                 struct gl_texture_object *obj );
diff --git a/src/mesa/main/texstate.c b/src/mesa/main/texstate.c
index 1b45eae..c4b678b 100644
--- a/src/mesa/main/texstate.c
+++ b/src/mesa/main/texstate.c
@@ -63,31 +63,6 @@ static const struct gl_tex_env_combine_state default_combine_state = {
 };
 
 
-/**
- * Copy a texture binding.  Helper used by _mesa_copy_texture_state().
- */
-static void
-copy_texture_binding(const GLcontext *ctx,
-                     struct gl_texture_object **dst,
-                     struct gl_texture_object *src)
-{
-   /* only copy if names differ (per OpenGL SI) */
-   if ((*dst)->Name != src->Name) {
-      /* unbind/delete dest binding which we're changing */
-      (*dst)->RefCount--;
-      if ((*dst)->RefCount == 0) {
-         /* time to delete this texture object */
-         ASSERT((*dst)->Name != 0);
-         ASSERT(ctx->Driver.DeleteTexture);
-         /* XXX cast-away const, unfortunately */
-         (*ctx->Driver.DeleteTexture)((GLcontext *) ctx, *dst);
-      }
-      /* make new binding, incrementing ref count */
-      *dst = src;
-      src->RefCount++;
-   }
-}
-
 
 /**
  * Used by glXCopyContext to copy texture state from one context to another.
@@ -144,16 +119,16 @@ _mesa_copy_texture_state( const GLcontext *src, GLcontext *dst )
       /* copy texture object bindings, not contents of texture objects */
       _mesa_lock_context_textures(dst);
 
-      copy_texture_binding(src, &dst->Texture.Unit[i].Current1D,
-                           src->Texture.Unit[i].Current1D);
-      copy_texture_binding(src, &dst->Texture.Unit[i].Current2D,
-                           src->Texture.Unit[i].Current2D);
-      copy_texture_binding(src, &dst->Texture.Unit[i].Current3D,
-                           src->Texture.Unit[i].Current3D);
-      copy_texture_binding(src, &dst->Texture.Unit[i].CurrentCubeMap,
-                           src->Texture.Unit[i].CurrentCubeMap);
-      copy_texture_binding(src, &dst->Texture.Unit[i].CurrentRect,
-                           src->Texture.Unit[i].CurrentRect);
+      MESA_REF_TEXOBJ(&dst->Texture.Unit[i].Current1D,
+                             src->Texture.Unit[i].Current1D);
+      MESA_REF_TEXOBJ(&dst->Texture.Unit[i].Current2D,
+                             src->Texture.Unit[i].Current2D);
+      MESA_REF_TEXOBJ(&dst->Texture.Unit[i].Current3D,
+                             src->Texture.Unit[i].Current3D);
+      MESA_REF_TEXOBJ(&dst->Texture.Unit[i].CurrentCubeMap,
+                             src->Texture.Unit[i].CurrentCubeMap);
+      MESA_REF_TEXOBJ(&dst->Texture.Unit[i].CurrentRect,
+                             src->Texture.Unit[i].CurrentRect);
 
       _mesa_unlock_context_textures(dst);
    }
@@ -3032,6 +3007,8 @@ alloc_proxy_textures( GLcontext *ctx )
    if (!ctx->Texture.ProxyRect)
       goto cleanup;
 
+   assert(ctx->Texture.Proxy1D->RefCount == 1);
+
    return GL_TRUE;
 
  cleanup:
@@ -3087,11 +3064,12 @@ init_texture_unit( GLcontext *ctx, GLuint unit )
    ASSIGN_4V( texUnit->EyePlaneR, 0.0, 0.0, 0.0, 0.0 );
    ASSIGN_4V( texUnit->EyePlaneQ, 0.0, 0.0, 0.0, 0.0 );
 
-   texUnit->Current1D = ctx->Shared->Default1D;
-   texUnit->Current2D = ctx->Shared->Default2D;
-   texUnit->Current3D = ctx->Shared->Default3D;
-   texUnit->CurrentCubeMap = ctx->Shared->DefaultCubeMap;
-   texUnit->CurrentRect = ctx->Shared->DefaultRect;
+   /* initialize current texture object ptrs to the shared default objects */
+   MESA_REF_TEXOBJ(&texUnit->Current1D, ctx->Shared->Default1D);
+   MESA_REF_TEXOBJ(&texUnit->Current2D, ctx->Shared->Default2D);
+   MESA_REF_TEXOBJ(&texUnit->Current3D, ctx->Shared->Default3D);
+   MESA_REF_TEXOBJ(&texUnit->CurrentCubeMap, ctx->Shared->DefaultCubeMap);
+   MESA_REF_TEXOBJ(&texUnit->CurrentRect, ctx->Shared->DefaultRect);
 }
 
 
@@ -3106,21 +3084,20 @@ _mesa_init_texture(GLcontext *ctx)
    assert(MAX_TEXTURE_LEVELS >= MAX_3D_TEXTURE_LEVELS);
    assert(MAX_TEXTURE_LEVELS >= MAX_CUBE_TEXTURE_LEVELS);
 
-   /* Effectively bind the default textures to all texture units */
-   ctx->Shared->Default1D->RefCount += MAX_TEXTURE_UNITS;
-   ctx->Shared->Default2D->RefCount += MAX_TEXTURE_UNITS;
-   ctx->Shared->Default3D->RefCount += MAX_TEXTURE_UNITS;
-   ctx->Shared->DefaultCubeMap->RefCount += MAX_TEXTURE_UNITS;
-   ctx->Shared->DefaultRect->RefCount += MAX_TEXTURE_UNITS;
-
    /* Texture group */
    ctx->Texture.CurrentUnit = 0;      /* multitexture */
    ctx->Texture._EnabledUnits = 0;
-   for (i=0; i<MAX_TEXTURE_UNITS; i++)
-      init_texture_unit( ctx, i );
    ctx->Texture.SharedPalette = GL_FALSE;
    _mesa_init_colortable(&ctx->Texture.Palette);
 
+   for (i = 0; i < MAX_TEXTURE_UNITS; i++)
+      init_texture_unit( ctx, i );
+
+   /* After we're done initializing the context's texture state the default
+    * texture objects' refcounts should be at least MAX_TEXTURE_UNITS + 1.
+    */
+   assert(ctx->Shared->Default1D->RefCount >= MAX_TEXTURE_UNITS + 1);
+
    _mesa_TexEnvProgramCacheInit( ctx );
 
    /* Allocate proxy textures */
@@ -3132,12 +3109,22 @@ _mesa_init_texture(GLcontext *ctx)
 
 
 /**
- * Free dynamically-allocted texture data attached to the given context.
+ * Free dynamically-allocated texture data attached to the given context.
  */
 void
 _mesa_free_texture_data(GLcontext *ctx)
 {
-   GLuint i;
+   GLuint u;
+
+   /* unreference current textures */
+   for (u = 0; u < MAX_TEXTURE_IMAGE_UNITS; u++) {
+      struct gl_texture_unit *unit = ctx->Texture.Unit + u;
+      MESA_REF_TEXOBJ(&unit->Current1D, NULL);
+      MESA_REF_TEXOBJ(&unit->Current2D, NULL);
+      MESA_REF_TEXOBJ(&unit->Current3D, NULL);
+      MESA_REF_TEXOBJ(&unit->CurrentCubeMap, NULL);
+      MESA_REF_TEXOBJ(&unit->CurrentRect, NULL);
+   }
 
    /* Free proxy texture objects */
    (ctx->Driver.DeleteTexture)(ctx,  ctx->Texture.Proxy1D );
@@ -3146,8 +3133,8 @@ _mesa_free_texture_data(GLcontext *ctx)
    (ctx->Driver.DeleteTexture)(ctx,  ctx->Texture.ProxyCubeMap );
    (ctx->Driver.DeleteTexture)(ctx,  ctx->Texture.ProxyRect );
 
-   for (i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++)
-      _mesa_free_colortable_data( &ctx->Texture.Unit[i].ColorTable );
+   for (u = 0; u < MAX_TEXTURE_IMAGE_UNITS; u++)
+      _mesa_free_colortable_data( &ctx->Texture.Unit[u].ColorTable );
 
    _mesa_TexEnvProgramCacheDestroy( ctx );
 }
diff --git a/src/mesa/shader/atifragshader.c b/src/mesa/shader/atifragshader.c
index 4727c1a..854c911 100644
--- a/src/mesa/shader/atifragshader.c
+++ b/src/mesa/shader/atifragshader.c
@@ -440,7 +440,7 @@ _mesa_PassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle)
       _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(coord)");
       return;
    }
-   if ((swizzle < GL_SWIZZLE_STR_ATI) && (swizzle > GL_SWIZZLE_STQ_DQ_ATI)) {
+   if (!(swizzle >= GL_SWIZZLE_STR_ATI) && (swizzle <= GL_SWIZZLE_STQ_DQ_ATI)) {
       _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(swizzle)");
       return;
    }
@@ -513,7 +513,7 @@ _mesa_SampleMapATI(GLuint dst, GLuint interp, GLenum swizzle)
       _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(interp)");
       return;
    }
-   if ((swizzle < GL_SWIZZLE_STR_ATI) && (swizzle > GL_SWIZZLE_STQ_DQ_ATI)) {
+   if (!(swizzle >= GL_SWIZZLE_STR_ATI) && (swizzle <= GL_SWIZZLE_STQ_DQ_ATI)) {
       _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(swizzle)");
       return;
    }
diff --git a/src/mesa/shader/shader_api.c b/src/mesa/shader/shader_api.c
index b794e30..06d24b4 100644
--- a/src/mesa/shader/shader_api.c
+++ b/src/mesa/shader/shader_api.c
@@ -378,7 +378,7 @@ _mesa_attach_shader(GLcontext *ctx, GLuint program, GLuint shader)
    struct gl_shader_program *shProg
       = _mesa_lookup_shader_program(ctx, program);
    struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
-   const GLuint n = shProg->NumShaders;
+   GLuint n;
    GLuint i;
 
    if (!shProg || !sh) {
@@ -387,6 +387,8 @@ _mesa_attach_shader(GLcontext *ctx, GLuint program, GLuint shader)
       return;
    }
 
+   n = shProg->NumShaders;
+
    for (i = 0; i < n; i++) {
       if (shProg->Shaders[i] == sh) {
          /* already attached */
@@ -548,7 +550,7 @@ _mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader)
 {
    struct gl_shader_program *shProg
       = _mesa_lookup_shader_program(ctx, program);
-   const GLuint n = shProg->NumShaders;
+   GLuint n;
    GLuint i, j;
 
    if (!shProg) {
@@ -557,6 +559,8 @@ _mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader)
       return;
    }
 
+   n = shProg->NumShaders;
+
    for (i = 0; i < n; i++) {
       if (shProg->Shaders[i]->Name == shader) {
          /* found it */
diff --git a/src/mesa/swrast/s_pointtemp.h b/src/mesa/swrast/s_pointtemp.h
index dddc2f7..9436464 100644
--- a/src/mesa/swrast/s_pointtemp.h
+++ b/src/mesa/swrast/s_pointtemp.h
@@ -217,9 +217,9 @@ NAME ( GLcontext *ctx, const SWvertex *vert )
       }
       else {
          /* even size */
-         xmin = (GLint) vert->win[0] - iRadius + 1;
+         xmin = (GLint) vert->win[0] - iRadius;
          xmax = xmin + iSize - 1;
-         ymin = (GLint) vert->win[1] - iRadius + 1;
+         ymin = (GLint) vert->win[1] - iRadius;
          ymax = ymin + iSize - 1;
       }
 #endif /*SMOOTH*/
diff --git a/src/mesa/vbo/vbo_split_copy.c b/src/mesa/vbo/vbo_split_copy.c
index e142dde..b71a935 100644
--- a/src/mesa/vbo/vbo_split_copy.c
+++ b/src/mesa/vbo/vbo_split_copy.c
@@ -129,6 +129,13 @@ static GLuint attr_size( const struct gl_client_array *array )
  */
 static GLboolean check_flush( struct copy_context *copy )
 {
+   GLenum mode = copy->dstprim[copy->dstprim_nr].mode;
+
+   if (GL_TRIANGLE_STRIP == mode &&
+       copy->dstelt_nr & 1) { /* see bug9962 */
+      return GL_FALSE;
+   }
+
    if (copy->dstbuf_nr + 4 > copy->dstbuf_size)
       return GL_TRUE;
 
@@ -458,7 +465,7 @@ static void replay_init( struct copy_context *copy )
       dst->StrideB = copy->vertex_size;
       dst->Ptr = copy->dstbuf + offset;
       dst->Enabled = GL_TRUE;
-      dst->Normalized = GL_TRUE;
+      dst->Normalized = src->Normalized;
       dst->BufferObj = ctx->Array.NullBufferObj;
       dst->_MaxElement = copy->dstbuf_size; /* may be less! */