mesa: refactor: move glReadPixels code into new readpix.c file
[mesa.git] / src / mesa / main / context.c
index 72c85de7ba2a13ac419705b1899d941e0f254c8e..aa9d11299961a1c31f73d40b2365974e1c92867d 100644 (file)
@@ -6,9 +6,9 @@
 
 /*
  * Mesa 3-D graphics library
- * Version:  6.5
+ * Version:  7.1
  *
- * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2007  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"),
 #include "fog.h"
 #include "framebuffer.h"
 #include "get.h"
-#include "glthread.h"
-#include "glapioffsets.h"
 #include "histogram.h"
 #include "hint.h"
 #include "hash.h"
-#include "atifragshader.h"
 #include "light.h"
 #include "lines.h"
 #include "macros.h"
 #include "matrix.h"
-#include "occlude.h"
 #include "pixel.h"
 #include "points.h"
 #include "polygon.h"
-#if FEATURE_NV_vertex_program || FEATURE_NV_fragment_program
-#include "program.h"
-#endif
+#include "queryobj.h"
 #include "rastpos.h"
 #include "simple_list.h"
 #include "state.h"
 #include "varray.h"
 #include "version.h"
 #include "vtxfmt.h"
+#include "glapi/glthread.h"
+#if FEATURE_NV_vertex_program || FEATURE_NV_fragment_program
+#include "shader/program.h"
+#endif
+#include "shader/shader_api.h"
+#include "shader/atifragshader.h"
 #if _HAVE_FULL_GL
 #include "math/m_translate.h"
 #include "math/m_matrix.h"
 #include "math/m_xform.h"
 #include "math/mathmod.h"
 #endif
-#include "shader_api.h"
 
 #ifdef USE_SPARC_ASM
 #include "sparc/sparc.h"
@@ -150,169 +149,7 @@ int MESA_DEBUG_FLAGS = 0;
 /* ubyte -> float conversion */
 GLfloat _mesa_ubyte_to_float_color_tab[256];
 
-static void
-free_shared_state( GLcontext *ctx, struct gl_shared_state *ss );
-
-
-/**********************************************************************/
-/** \name OpenGL SI-style interface (new in Mesa 3.5)
- *
- * \if subset
- * \note Most of these functions are never called in the Mesa subset.
- * \endif
- */
-/*@{*/
-
-/**
- * Destroy context callback.
- * 
- * \param gc context.
- * \return GL_TRUE on success, or GL_FALSE on failure.
- * 
- * \ifnot subset
- * Called by window system/device driver (via __GLexports::destroyCurrent) when
- * the rendering context is to be destroyed.
- * \endif
- *
- * Frees the context data and the context structure.
- */
-GLboolean
-_mesa_destroyContext(__GLcontext *gc)
-{
-   if (gc) {
-      _mesa_free_context_data(gc);
-      _mesa_free(gc);
-   }
-   return GL_TRUE;
-}
-
-/**
- * Unbind context callback.
- * 
- * \param gc context.
- * \return GL_TRUE on success, or GL_FALSE on failure.
- *
- * \ifnot subset
- * Called by window system/device driver (via __GLexports::loseCurrent)
- * when the rendering context is made non-current.
- * \endif
- *
- * No-op
- */
-GLboolean
-_mesa_loseCurrent(__GLcontext *gc)
-{
-   /* XXX unbind context from thread */
-   (void) gc;
-   return GL_TRUE;
-}
-
-/**
- * Bind context callback.
- * 
- * \param gc context.
- * \return GL_TRUE on success, or GL_FALSE on failure.
- *
- * \ifnot subset
- * Called by window system/device driver (via __GLexports::makeCurrent)
- * when the rendering context is made current.
- * \endif
- *
- * No-op
- */
-GLboolean
-_mesa_makeCurrent(__GLcontext *gc)
-{
-   /* XXX bind context to thread */
-   (void) gc;
-   return GL_TRUE;
-}
-
-/**
- * Share context callback.
- * 
- * \param gc context.
- * \param gcShare shared context.
- * \return GL_TRUE on success, or GL_FALSE on failure.
- *
- * \ifnot subset
- * Called by window system/device driver (via __GLexports::shareContext)
- * \endif
- *
- * Update the shared context reference count, gl_shared_state::RefCount.
- */
-GLboolean
-_mesa_shareContext(__GLcontext *gc, __GLcontext *gcShare)
-{
-   if (gc && gcShare && gc->Shared && gcShare->Shared) {
-      gc->Shared->RefCount--;
-      if (gc->Shared->RefCount == 0) {
-         free_shared_state(gc, gc->Shared);
-      }
-      gc->Shared = gcShare->Shared;
-      gc->Shared->RefCount++;
-      return GL_TRUE;
-   }
-   else {
-      return GL_FALSE;
-   }
-}
-
-
-#if _HAVE_FULL_GL
-/**
- * Copy context callback.
- */
-GLboolean
-_mesa_copyContext(__GLcontext *dst, const __GLcontext *src, GLuint mask)
-{
-   if (dst && src) {
-      _mesa_copy_context( src, dst, mask );
-      return GL_TRUE;
-   }
-   else {
-      return GL_FALSE;
-   }
-}
-#endif
-
-/** No-op */
-GLboolean
-_mesa_forceCurrent(__GLcontext *gc)
-{
-   (void) gc;
-   return GL_TRUE;
-}
 
-/**
- * Windows/buffer resizing notification callback.
- *
- * \param gc GL context.
- * \return GL_TRUE on success, or GL_FALSE on failure.
- */
-GLboolean
-_mesa_notifyResize(__GLcontext *gc)
-{
-   /* update viewport, resize software buffers, etc. */
-   (void) gc;
-   return GL_TRUE;
-}
-
-/**
- * Window/buffer destruction notification callback.
- *
- * \param gc GL context.
- * 
- * Called when the context's window/buffer is going to be destroyed. 
- *
- * No-op
- */
-void
-_mesa_notifyDestroy(__GLcontext *gc)
-{
-   /* Unbind from it. */
-   (void) gc;
-}
 
 /**
  * Swap buffers notification callback.
@@ -328,105 +165,6 @@ _mesa_notifySwapBuffers(__GLcontext *gc)
    FLUSH_VERTICES( gc, 0 );
 }
 
-/** No-op */
-struct __GLdispatchStateRec *
-_mesa_dispatchExec(__GLcontext *gc)
-{
-   (void) gc;
-   return NULL;
-}
-
-/** No-op */
-void
-_mesa_beginDispatchOverride(__GLcontext *gc)
-{
-   (void) gc;
-}
-
-/** No-op */
-void
-_mesa_endDispatchOverride(__GLcontext *gc)
-{
-   (void) gc;
-}
-
-/**
- * \ifnot subset
- * Setup the exports.  
- *
- * The window system will call these functions when it needs Mesa to do
- * something.
- * 
- * \note Device drivers should override these functions!  For example,
- * the Xlib driver should plug in the XMesa*-style functions into this
- * structure.  The XMesa-style functions should then call the _mesa_*
- * version of these functions.  This is an approximation to OO design
- * (inheritance and virtual functions).
- * \endif
- *
- * \if subset
- * No-op.
- * 
- * \endif
- */
-static void
-_mesa_init_default_exports(__GLexports *exports)
-{
-#if _HAVE_FULL_GL
-    exports->destroyContext = _mesa_destroyContext;
-    exports->loseCurrent = _mesa_loseCurrent;
-    exports->makeCurrent = _mesa_makeCurrent;
-    exports->shareContext = _mesa_shareContext;
-    exports->copyContext = _mesa_copyContext;
-    exports->forceCurrent = _mesa_forceCurrent;
-    exports->notifyResize = _mesa_notifyResize;
-    exports->notifyDestroy = _mesa_notifyDestroy;
-    exports->notifySwapBuffers = _mesa_notifySwapBuffers;
-    exports->dispatchExec = _mesa_dispatchExec;
-    exports->beginDispatchOverride = _mesa_beginDispatchOverride;
-    exports->endDispatchOverride = _mesa_endDispatchOverride;
-#else
-    (void) exports;
-#endif
-}
-
-/**
- * Exported OpenGL SI interface.
- */
-__GLcontext *
-__glCoreCreateContext(__GLimports *imports, __GLcontextModes *modes)
-{
-    GLcontext *ctx;
-
-    ctx = (GLcontext *) (*imports->calloc)(NULL, 1, sizeof(GLcontext));
-    if (ctx == NULL) {
-       return NULL;
-    }
-
-    /* XXX doesn't work at this time */
-    _mesa_initialize_context(ctx, modes, NULL, NULL, NULL);
-    ctx->imports = *imports;
-
-    return ctx;
-}
-
-/**
- * Exported OpenGL SI interface.
- */
-void
-__glCoreNopDispatch(void)
-{
-#if 0
-   /* SI */
-   __gl_dispatch = __glNopDispatchState;
-#else
-   /* Mesa */
-   _glapi_set_dispatch(NULL);
-#endif
-}
-
-/*@}*/
-
 
 /**********************************************************************/
 /** \name GL Visual allocation/destruction                            */
@@ -621,6 +359,8 @@ one_time_init( GLcontext *ctx )
       assert( sizeof(GLint) == 4 );
       assert( sizeof(GLuint) == 4 );
 
+      _mesa_init_sqrt_table();
+
 #if _HAVE_FULL_GL
       _math_init();
 
@@ -678,12 +418,14 @@ alloc_shared_state( GLcontext *ctx )
 #endif
 
 #if FEATURE_ARB_vertex_program
-   ss->DefaultVertexProgram = ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0);
+   ss->DefaultVertexProgram = (struct gl_vertex_program *)
+      ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0);
    if (!ss->DefaultVertexProgram)
       goto cleanup;
 #endif
 #if FEATURE_ARB_fragment_program
-   ss->DefaultFragmentProgram = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
+   ss->DefaultFragmentProgram = (struct gl_fragment_program *)
+      ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
    if (!ss->DefaultFragmentProgram)
       goto cleanup;
 #endif
@@ -724,17 +466,20 @@ 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;
+   ss->Default1DArray = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_1D_ARRAY_EXT);
+   if (!ss->Default1DArray)
+      goto cleanup;
+
+   ss->Default2DArray = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_2D_ARRAY_EXT);
+   if (!ss->Default2DArray)
+      goto cleanup;
+
+   /* 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)
@@ -744,10 +489,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);
@@ -758,12 +502,10 @@ alloc_shared_state( GLcontext *ctx )
       _mesa_DeleteHashTable(ss->Programs);
 #endif
 #if FEATURE_ARB_vertex_program
-   if (ss->DefaultVertexProgram)
-      ctx->Driver.DeleteProgram(ctx, ss->DefaultVertexProgram);
+   _mesa_reference_vertprog(ctx, &ss->DefaultVertexProgram, NULL);
 #endif
 #if FEATURE_ARB_fragment_program
-   if (ss->DefaultFragmentProgram)
-      ctx->Driver.DeleteProgram(ctx, ss->DefaultFragmentProgram);
+   _mesa_reference_fragprog(ctx, &ss->DefaultFragmentProgram, NULL);
 #endif
 #if FEATURE_ATI_fragment_shader
    if (ss->DefaultFragmentShader)
@@ -799,8 +541,13 @@ alloc_shared_state( GLcontext *ctx )
       (*ctx->Driver.DeleteTexture)(ctx, ss->DefaultCubeMap);
    if (ss->DefaultRect)
       (*ctx->Driver.DeleteTexture)(ctx, ss->DefaultRect);
-   if (ss)
-      _mesa_free(ss);
+   if (ss->Default1DArray)
+      (*ctx->Driver.DeleteTexture)(ctx, ss->Default1DArray);
+   if (ss->Default2DArray)
+      (*ctx->Driver.DeleteTexture)(ctx, ss->Default2DArray);
+
+   _mesa_free(ss);
+
    return GL_FALSE;
 }
 
@@ -835,6 +582,8 @@ delete_program_cb(GLuint id, void *data, void *userData)
 {
    struct gl_program *prog = (struct gl_program *) data;
    GLcontext *ctx = (GLcontext *) userData;
+   ASSERT(prog->RefCount == 1); /* should only be referenced by hash table */
+   prog->RefCount = 0;  /* now going away */
    ctx->Driver.DeleteProgram(ctx, prog);
 }
 
@@ -872,6 +621,21 @@ delete_arrayobj_cb(GLuint id, void *data, void *userData)
    _mesa_delete_array_object(ctx, arrayObj);
 }
 
+/**
+ * Callback for freeing shader program data. Call it before delete_shader_cb
+ * to avoid memory access error.
+ */
+static void
+free_shader_program_data_cb(GLuint id, void *data, void *userData)
+{
+   GLcontext *ctx = (GLcontext *) userData;
+   struct gl_shader_program *shProg = (struct gl_shader_program *) data;
+
+   if (shProg->Type == GL_SHADER_PROGRAM_MESA) {
+       _mesa_free_shader_program_data(ctx, shProg);
+   }
+}
+
 /**
  * Callback for deleting shader and shader programs objects.
  * Called by _mesa_HashDeleteAll().
@@ -886,11 +650,44 @@ delete_shader_cb(GLuint id, void *data, void *userData)
    }
    else {
       struct gl_shader_program *shProg = (struct gl_shader_program *) data;
-      ASSERT(shProg->Type == GL_SHADER_PROGRAM);
+      ASSERT(shProg->Type == GL_SHADER_PROGRAM_MESA);
       _mesa_free_shader_program(ctx, shProg);
    }
 }
 
+/**
+ * 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;
+
+   /* NOTE: Delete should always be defined but there are two reports
+    * of it being NULL (bugs 13507, 14293).  Work-around for now.
+    */
+   if (fb->Delete)
+      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 */
+   if (rb->Delete)
+      rb->Delete(rb);
+}
+
+
 
 /**
  * Deallocate a shared state object and all children structures.
@@ -913,29 +710,21 @@ 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 FEATURE_ARB_shader_objects
+   _mesa_HashWalk(ss->ShaderObjects, free_shader_program_data_cb, ctx);
+   _mesa_HashDeleteAll(ss->ShaderObjects, delete_shader_cb, ctx);
+   _mesa_DeleteHashTable(ss->ShaderObjects);
+#endif
 
 #if defined(FEATURE_NV_vertex_program) || defined(FEATURE_NV_fragment_program)
    _mesa_HashDeleteAll(ss->Programs, delete_program_cb, ctx);
    _mesa_DeleteHashTable(ss->Programs);
 #endif
 #if FEATURE_ARB_vertex_program
-   _mesa_delete_program(ctx, ss->DefaultVertexProgram);
+   _mesa_reference_vertprog(ctx, &ss->DefaultVertexProgram, NULL);
 #endif
 #if FEATURE_ARB_fragment_program
-   _mesa_delete_program(ctx, ss->DefaultFragmentProgram);
+   _mesa_reference_fragprog(ctx, &ss->DefaultFragmentProgram, NULL);
 #endif
 
 #if FEATURE_ATI_fragment_shader
@@ -952,16 +741,30 @@ free_shared_state( GLcontext *ctx, struct gl_shared_state *ss )
    _mesa_HashDeleteAll(ss->ArrayObjects, delete_arrayobj_cb, ctx);
    _mesa_DeleteHashTable(ss->ArrayObjects);
 
-#if FEATURE_ARB_shader_objects
-   _mesa_HashDeleteAll(ss->ShaderObjects, delete_shader_cb, ctx);
-   _mesa_DeleteHashTable(ss->ShaderObjects);
-#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);
+   ctx->Driver.DeleteTexture(ctx, ss->Default1DArray);
+   ctx->Driver.DeleteTexture(ctx, ss->Default2DArray);
+   /* all other textures */
+   _mesa_HashDeleteAll(ss->TexObjects, delete_texture_cb, ctx);
+   _mesa_DeleteHashTable(ss->TexObjects);
+
    _glthread_DESTROY_MUTEX(ss->Mutex);
 
    _mesa_free(ss);
@@ -982,7 +785,7 @@ _mesa_init_current(GLcontext *ctx)
    }
 
    /* redo special cases: */
-   ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_WEIGHT], 1.0, 0.0, 0.0, 1.0 );
+   ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_WEIGHT], 1.0, 0.0, 0.0, 0.0 );
    ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_NORMAL], 0.0, 0.0, 1.0, 1.0 );
    ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_COLOR0], 1.0, 1.0, 1.0, 1.0 );
    ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_COLOR1], 0.0, 0.0, 0.0, 1.0 );
@@ -1029,6 +832,7 @@ _mesa_init_constants(GLcontext *ctx)
    ctx->Const.Max3DTextureLevels = MAX_3D_TEXTURE_LEVELS;
    ctx->Const.MaxCubeTextureLevels = MAX_CUBE_TEXTURE_LEVELS;
    ctx->Const.MaxTextureRectSize = MAX_TEXTURE_RECT_SIZE;
+   ctx->Const.MaxArrayTextureLayers = MAX_ARRAY_TEXTURE_LAYERS;
    ctx->Const.MaxTextureCoordUnits = MAX_TEXTURE_COORD_UNITS;
    ctx->Const.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
    ctx->Const.MaxTextureUnits = MIN2(ctx->Const.MaxTextureCoordUnits,
@@ -1062,10 +866,10 @@ _mesa_init_constants(GLcontext *ctx)
    ctx->Const.VertexProgram.MaxTexInstructions = 0;
    ctx->Const.VertexProgram.MaxTexIndirections = 0;
    ctx->Const.VertexProgram.MaxAttribs = MAX_NV_VERTEX_PROGRAM_INPUTS;
-   ctx->Const.VertexProgram.MaxTemps = MAX_NV_VERTEX_PROGRAM_TEMPS;
+   ctx->Const.VertexProgram.MaxTemps = MAX_PROGRAM_TEMPS;
    ctx->Const.VertexProgram.MaxParameters = MAX_NV_VERTEX_PROGRAM_PARAMS;
    ctx->Const.VertexProgram.MaxLocalParams = MAX_PROGRAM_LOCAL_PARAMS;
-   ctx->Const.VertexProgram.MaxEnvParams = MAX_NV_VERTEX_PROGRAM_PARAMS;
+   ctx->Const.VertexProgram.MaxEnvParams = MAX_PROGRAM_ENV_PARAMS;
    ctx->Const.VertexProgram.MaxAddressRegs = MAX_VERTEX_PROGRAM_ADDRESS_REGS;
    ctx->Const.VertexProgram.MaxUniformComponents = 4 * MAX_UNIFORMS;
    init_natives(&ctx->Const.VertexProgram);
@@ -1077,10 +881,10 @@ _mesa_init_constants(GLcontext *ctx)
    ctx->Const.FragmentProgram.MaxTexInstructions = MAX_FRAGMENT_PROGRAM_TEX_INSTRUCTIONS;
    ctx->Const.FragmentProgram.MaxTexIndirections = MAX_FRAGMENT_PROGRAM_TEX_INDIRECTIONS;
    ctx->Const.FragmentProgram.MaxAttribs = MAX_NV_FRAGMENT_PROGRAM_INPUTS;
-   ctx->Const.FragmentProgram.MaxTemps = MAX_NV_FRAGMENT_PROGRAM_TEMPS;
+   ctx->Const.FragmentProgram.MaxTemps = MAX_PROGRAM_TEMPS;
    ctx->Const.FragmentProgram.MaxParameters = MAX_NV_FRAGMENT_PROGRAM_PARAMS;
    ctx->Const.FragmentProgram.MaxLocalParams = MAX_PROGRAM_LOCAL_PARAMS;
-   ctx->Const.FragmentProgram.MaxEnvParams = MAX_NV_FRAGMENT_PROGRAM_PARAMS;
+   ctx->Const.FragmentProgram.MaxEnvParams = MAX_PROGRAM_ENV_PARAMS;
    ctx->Const.FragmentProgram.MaxAddressRegs = MAX_FRAGMENT_PROGRAM_ADDRESS_REGS;
    ctx->Const.FragmentProgram.MaxUniformComponents = 4 * MAX_UNIFORMS;
    init_natives(&ctx->Const.FragmentProgram);
@@ -1180,6 +984,7 @@ init_attrib_groups(GLcontext *ctx)
    _mesa_init_debug( ctx );
    _mesa_init_display_list( ctx );
    _mesa_init_eval( ctx );
+   _mesa_init_fbobjects( ctx );
    _mesa_init_feedback( ctx );
    _mesa_init_fog( ctx );
    _mesa_init_histogram( ctx );
@@ -1210,7 +1015,28 @@ init_attrib_groups(GLcontext *ctx)
    /* Miscellaneous */
    ctx->NewState = _NEW_ALL;
    ctx->ErrorValue = (GLenum) GL_NO_ERROR;
-   ctx->_Facing = 0;
+
+   return GL_TRUE;
+}
+
+
+/**
+ * Update default objects in a GL context with respect to shared state.
+ *
+ * \param ctx GL context.
+ *
+ * Removes references to old default objects, (texture objects, program
+ * objects, etc.) and changes to reference those from the current shared
+ * state.
+ */
+static GLboolean
+update_default_objects(GLcontext *ctx)
+{
+   assert(ctx);
+
+   _mesa_update_default_objects_program(ctx);
+   _mesa_update_default_objects_texture(ctx);
+   _mesa_update_default_objects_buffer_objects(ctx);
 
    return GL_TRUE;
 }
@@ -1224,7 +1050,7 @@ init_attrib_groups(GLcontext *ctx)
 static int
 generic_nop(void)
 {
-   _mesa_problem(NULL, "User called no-op dispatch function (an unsupported extension function?)");
+   _mesa_warning(NULL, "User called no-op dispatch function (an unsupported extension function?)");
    return 0;
 }
 
@@ -1292,14 +1118,6 @@ _mesa_initialize_context(GLcontext *ctx,
    assert(driverFunctions->NewTextureObject);
    assert(driverFunctions->FreeTexImageData);
 
-   /* If the driver wants core Mesa to use special imports, it'll have to
-    * override these defaults.
-    */
-   _mesa_init_default_imports( &(ctx->imports), driverContext );
-
-   /* initialize the exports (Mesa functions called by the window system) */
-   _mesa_init_default_exports( &(ctx->exports) );
-
    /* misc one-time initializations */
    one_time_init(ctx);
 
@@ -1355,14 +1173,16 @@ _mesa_initialize_context(GLcontext *ctx,
    ctx->TnlModule.SwapCount = 0;
 #endif
 
+   ctx->FragmentProgram._MaintainTexEnvProgram
+      = (_mesa_getenv("MESA_TEX_PROG") != NULL);
+   ctx->FragmentProgram._UseTexEnvProgram = ctx->FragmentProgram._MaintainTexEnvProgram;
+
    ctx->VertexProgram._MaintainTnlProgram
       = (_mesa_getenv("MESA_TNL_PROG") != NULL);
-   if (ctx->VertexProgram._MaintainTnlProgram)
+   if (ctx->VertexProgram._MaintainTnlProgram) {
       /* this is required... */
       ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE;
-   else
-      ctx->FragmentProgram._MaintainTexEnvProgram
-         = (_mesa_getenv("MESA_TEX_PROG") != NULL);
+   }
 
    ctx->FirstTimeCurrent = GL_TRUE;
 
@@ -1420,18 +1240,28 @@ _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);
-   }
-   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 (!_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);
    }
 
+   /* 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_reference_vertprog(ctx, &ctx->VertexProgram.Current, NULL);
+   _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, NULL);
+   _mesa_reference_vertprog(ctx, &ctx->VertexProgram._TnlProgram, NULL);
+
+   _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, NULL);
+   _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, NULL);
+   _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram, NULL);
+
+   _mesa_free_attrib_data(ctx);
    _mesa_free_lighting_data( ctx );
    _mesa_free_eval_data( ctx );
    _mesa_free_texture_data( ctx );
@@ -1463,6 +1293,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);
+   }
 }
 
 
@@ -1609,9 +1444,9 @@ _mesa_copy_context( const GLcontext *src, GLcontext *dst, GLuint mask )
  * Check if the given context can render into the given framebuffer
  * by checking visual attributes.
  *
- * XXX this may go away someday because we're moving toward more freedom
- * in binding contexts to drawables with different visual attributes.
- * The GL_EXT_f_b_o extension is prompting some of that.
+ * Most of these tests could go away because Mesa is now pretty flexible
+ * in terms of mixing rendering contexts with framebuffers.  As long
+ * as RGB vs. CI mode agree, we're probably good.
  *
  * \return GL_TRUE if compatible, GL_FALSE otherwise.
  */
@@ -1645,8 +1480,11 @@ check_compatible(const GLcontext *ctx, const GLframebuffer *buffer)
       return GL_FALSE;
    if (ctxvis->blueMask && ctxvis->blueMask != bufvis->blueMask)
       return GL_FALSE;
+#if 0
+   /* disabled (see bug 11161) */
    if (ctxvis->depthBits && ctxvis->depthBits != bufvis->depthBits)
       return GL_FALSE;
+#endif
    if (ctxvis->stencilBits && ctxvis->stencilBits != bufvis->stencilBits)
       return GL_FALSE;
 
@@ -1691,8 +1529,6 @@ void
 _mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer,
                     GLframebuffer *readBuffer )
 {
-   GET_CURRENT_CONTEXT(oldCtx);
-
    if (MESA_VERBOSE & VERBOSE_API)
       _mesa_debug(newCtx, "_mesa_make_current()\n");
 
@@ -1713,39 +1549,10 @@ _mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer,
       }
    }
 
-#if 0 /** XXX enable this someday */
-   if (oldCtx && oldCtx != newCtx) {
-      /* unbind old context's draw/read buffers */
-      if (oldCtx->DrawBuffer && oldCtx->DrawBuffer->Name == 0) {
-         oldCtx->DrawBuffer->RefCount--;
-         oldCtx->DrawBuffer = NULL;
-      }
-      if (oldCtx->ReadBuffer && oldCtx->ReadBuffer->Name == 0) {
-         oldCtx->ReadBuffer->RefCount--;
-         oldCtx->ReadBuffer = NULL;
-      }
-      if (oldCtx->WinSysDrawBuffer) {
-         ASSERT(oldCtx->WinSysDrawBuffer->Name == 0);
-         oldCtx->WinSysDrawBuffer->RefCount--;
-         oldCtx->WinSysDrawBuffer = NULL;
-      }
-      if (oldCtx->WinSysReadBuffer) {
-         ASSERT(oldCtx->WinSysReadBuffer->Name == 0);
-         oldCtx->WinSysReadBuffer->RefCount--;
-         oldCtx->WinSysReadBuffer = NULL;
-      }
-   }
-#endif
-
    /* We used to call _glapi_check_multithread() here.  Now do it in drivers */
    _glapi_set_context((void *) newCtx);
    ASSERT(_mesa_get_current_context() == newCtx);
 
-   if (oldCtx) {
-      _mesa_unreference_framebuffer(&oldCtx->WinSysDrawBuffer);
-      _mesa_unreference_framebuffer(&oldCtx->WinSysReadBuffer);
-   }
-         
    if (!newCtx) {
       _glapi_set_dispatch(NULL);  /* none current */
    }
@@ -1771,6 +1578,9 @@ _mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer,
             _mesa_reference_framebuffer(&newCtx->ReadBuffer, readBuffer);
          }
 
+         /* XXX only set this flag if we're really changing the draw/read
+          * framebuffer bindings.
+          */
         newCtx->NewState |= _NEW_BUFFERS;
 
 #if 1
@@ -1838,12 +1648,18 @@ GLboolean
 _mesa_share_state(GLcontext *ctx, GLcontext *ctxToShare)
 {
    if (ctx && ctxToShare && ctx->Shared && ctxToShare->Shared) {
-      ctx->Shared->RefCount--;
-      if (ctx->Shared->RefCount == 0) {
-         free_shared_state(ctx, ctx->Shared);
-      }
+      struct gl_shared_state *oldSharedState = ctx->Shared;
+
       ctx->Shared = ctxToShare->Shared;
       ctx->Shared->RefCount++;
+
+      update_default_objects(ctx);
+
+      oldSharedState->RefCount--;
+      if (oldSharedState->RefCount == 0) {
+         free_shared_state(ctx, oldSharedState);
+      }
+
       return GL_TRUE;
    }
    else {