Merge branch 'xa_branch'
[mesa.git] / src / mesa / main / context.c
index 284c8b1d37bbfe12cd77cebff36ac5a9fb80ef82..b83a5d621face445d4028ada220dc1a34c2839e5 100644 (file)
@@ -96,6 +96,7 @@
 #include "fbobject.h"
 #include "feedback.h"
 #include "fog.h"
+#include "formats.h"
 #include "framebuffer.h"
 #include "hint.h"
 #include "hash.h"
 #if _HAVE_FULL_GL
 #include "math/m_matrix.h"
 #endif
+#include "main/dispatch.h" /* for _gloffset_COUNT */
 
 #ifdef USE_SPARC_ASM
 #include "sparc/sparc.h"
@@ -163,7 +165,7 @@ GLfloat _mesa_ubyte_to_float_color_tab[256];
  * We have to finish any pending rendering.
  */
 void
-_mesa_notifySwapBuffers(__GLcontext *ctx)
+_mesa_notifySwapBuffers(struct gl_context *ctx)
 {
    if (MESA_VERBOSE & VERBOSE_SWAPBUFFERS)
       _mesa_debug(ctx, "SwapBuffers\n");
@@ -180,7 +182,7 @@ _mesa_notifySwapBuffers(__GLcontext *ctx)
 /*@{*/
 
 /**
- * Allocates a GLvisual structure and initializes it via
+ * Allocates a struct gl_config structure and initializes it via
  * _mesa_initialize_visual().
  * 
  * \param dbFlag double buffering
@@ -189,7 +191,8 @@ _mesa_notifySwapBuffers(__GLcontext *ctx)
  * is acceptable but the actual depth type will be GLushort or GLuint as
  * needed.
  * \param stencilBits requested minimum bits per stencil buffer value
- * \param accumRedBits, accumGreenBits, accumBlueBits, accumAlphaBits number of bits per color component in accum buffer.
+ * \param accumRedBits, accumGreenBits, accumBlueBits, accumAlphaBits number
+ * of bits per color component in accum buffer.
  * \param indexBits number of bits per pixel if \p rgbFlag is GL_FALSE
  * \param redBits number of bits per color component in frame buffer for RGB(A)
  * mode.  We always use 8 in core Mesa though.
@@ -198,12 +201,12 @@ _mesa_notifySwapBuffers(__GLcontext *ctx)
  * \param alphaBits same as above.
  * \param numSamples not really used.
  * 
- * \return pointer to new GLvisual or NULL if requested parameters can't be
- * met.
+ * \return pointer to new struct gl_config or NULL if requested parameters
+ * can't be met.
  *
  * \note Need to add params for level and numAuxBuffers (at least)
  */
-GLvisual *
+struct gl_config *
 _mesa_create_visual( GLboolean dbFlag,
                      GLboolean stereoFlag,
                      GLint redBits,
@@ -218,7 +221,7 @@ _mesa_create_visual( GLboolean dbFlag,
                      GLint accumAlphaBits,
                      GLint numSamples )
 {
-   GLvisual *vis = (GLvisual *) calloc(1, sizeof(GLvisual));
+   struct gl_config *vis = CALLOC_STRUCT(gl_config);
    if (vis) {
       if (!_mesa_initialize_visual(vis, dbFlag, stereoFlag,
                                    redBits, greenBits, blueBits, alphaBits,
@@ -233,17 +236,19 @@ _mesa_create_visual( GLboolean dbFlag,
    return vis;
 }
 
+
 /**
- * Makes some sanity checks and fills in the fields of the
- * GLvisual object with the given parameters.  If the caller needs
- * to set additional fields, he should just probably init the whole GLvisual
- * object himself.
+ * Makes some sanity checks and fills in the fields of the struct
+ * gl_config object with the given parameters.  If the caller needs to
+ * set additional fields, he should just probably init the whole
+ * gl_config object himself.
+ *
  * \return GL_TRUE on success, or GL_FALSE on failure.
  *
  * \sa _mesa_create_visual() above for the parameter description.
  */
 GLboolean
-_mesa_initialize_visual( GLvisual *vis,
+_mesa_initialize_visual( struct gl_config *vis,
                          GLboolean dbFlag,
                          GLboolean stereoFlag,
                          GLint redBits,
@@ -296,7 +301,6 @@ _mesa_initialize_visual( GLvisual *vis,
 
    vis->numAuxBuffers = 0;
    vis->level = 0;
-   vis->pixmapMode = 0;
    vis->sampleBuffers = numSamples > 0 ? 1 : 0;
    vis->samples = numSamples;
 
@@ -312,7 +316,7 @@ _mesa_initialize_visual( GLvisual *vis,
  * Frees the visual structure.
  */
 void
-_mesa_destroy_visual( GLvisual *vis )
+_mesa_destroy_visual( struct gl_config *vis )
 {
    free(vis);
 }
@@ -368,6 +372,8 @@ dummy_enum_func(void)
  */
 _glthread_DECLARE_STATIC_MUTEX(OneTimeLock);
 
+
+
 /**
  * Calls all the various one-time-init functions in Mesa.
  *
@@ -378,12 +384,14 @@ _glthread_DECLARE_STATIC_MUTEX(OneTimeLock);
  * \sa _math_init().
  */
 static void
-one_time_init( GLcontext *ctx )
+one_time_init( struct gl_context *ctx )
 {
-   static GLboolean alreadyCalled = GL_FALSE;
-   (void) ctx;
+   static GLbitfield api_init_mask = 0x0;
+
    _glthread_LOCK_MUTEX(OneTimeLock);
-   if (!alreadyCalled) {
+
+   /* truly one-time init */
+   if (!api_init_mask) {
       GLuint i;
 
       /* do some implementation tests */
@@ -396,27 +404,9 @@ one_time_init( GLcontext *ctx )
 
       _mesa_get_cpu_features();
 
-      switch (ctx->API) {
-#if FEATURE_GL
-      case API_OPENGL:
-        _mesa_init_remap_table();
-        break;
-#endif
-#if FEATURE_ES1
-      case API_OPENGLES:
-        _mesa_init_remap_table_es1();
-        break;
-#endif
-#if FEATURE_ES2
-      case API_OPENGLES2:
-        _mesa_init_remap_table_es2();
-        break;
-#endif
-      default:
-        break;
-      }
-
       _mesa_init_sqrt_table();
+
+      /* context dependence is never a one-time thing... */
       _mesa_init_get_hash(ctx);
 
       for (i = 0; i < 256; i++) {
@@ -424,12 +414,31 @@ one_time_init( GLcontext *ctx )
       }
 
 #if defined(DEBUG) && defined(__DATE__) && defined(__TIME__)
-      _mesa_debug(ctx, "Mesa %s DEBUG build %s %s\n",
-                  MESA_VERSION_STRING, __DATE__, __TIME__);
+      if (MESA_VERBOSE != 0) {
+        _mesa_debug(ctx, "Mesa %s DEBUG build %s %s\n",
+                    MESA_VERSION_STRING, __DATE__, __TIME__);
+      }
 #endif
 
-      alreadyCalled = GL_TRUE;
+#ifdef DEBUG
+      _mesa_test_formats();
+#endif
    }
+
+   /* per-API one-time init */
+   if (!(api_init_mask & (1 << ctx->API))) {
+      /*
+       * This is fine as ES does not use the remap table, but it may not be
+       * future-proof.  We cannot always initialize the remap table because
+       * when an app is linked to libGLES*, there are not enough dynamic
+       * entries.
+       */
+      if (ctx->API == API_OPENGL)
+         _mesa_init_remap_table();
+   }
+
+   api_init_mask |= 1 << ctx->API;
+
    _glthread_UNLOCK_MUTEX(OneTimeLock);
 
    /* Hopefully atexit() is widely available.  If not, we may need some
@@ -445,7 +454,7 @@ one_time_init( GLcontext *ctx )
  * Initialize fields of gl_current_attrib (aka ctx->Current.*)
  */
 static void
-_mesa_init_current(GLcontext *ctx)
+_mesa_init_current(struct gl_context *ctx)
 {
    GLuint i;
 
@@ -478,30 +487,26 @@ init_program_limits(GLenum type, struct gl_program_constants *prog)
    prog->MaxTemps = MAX_PROGRAM_TEMPS;
    prog->MaxEnvParams = MAX_PROGRAM_ENV_PARAMS;
    prog->MaxLocalParams = MAX_PROGRAM_LOCAL_PARAMS;
-   prog->MaxUniformComponents = 4 * MAX_UNIFORMS;
+   prog->MaxAddressOffset = MAX_PROGRAM_LOCAL_PARAMS;
 
    switch (type) {
    case GL_VERTEX_PROGRAM_ARB:
       prog->MaxParameters = MAX_VERTEX_PROGRAM_PARAMS;
       prog->MaxAttribs = MAX_NV_VERTEX_PROGRAM_INPUTS;
       prog->MaxAddressRegs = MAX_VERTEX_PROGRAM_ADDRESS_REGS;
+      prog->MaxUniformComponents = 4 * MAX_UNIFORMS;
       break;
    case GL_FRAGMENT_PROGRAM_ARB:
       prog->MaxParameters = MAX_NV_FRAGMENT_PROGRAM_PARAMS;
       prog->MaxAttribs = MAX_NV_FRAGMENT_PROGRAM_INPUTS;
       prog->MaxAddressRegs = MAX_FRAGMENT_PROGRAM_ADDRESS_REGS;
+      prog->MaxUniformComponents = 4 * MAX_UNIFORMS;
       break;
    case MESA_GEOMETRY_PROGRAM:
       prog->MaxParameters = MAX_NV_VERTEX_PROGRAM_PARAMS;
       prog->MaxAttribs = MAX_NV_VERTEX_PROGRAM_INPUTS;
       prog->MaxAddressRegs = MAX_VERTEX_PROGRAM_ADDRESS_REGS;
-
-      prog->MaxGeometryTextureImageUnits = MAX_GEOMETRY_TEXTURE_IMAGE_UNITS;
-      prog->MaxGeometryVaryingComponents = MAX_GEOMETRY_VARYING_COMPONENTS;
-      prog->MaxVertexVaryingComponents = MAX_VERTEX_VARYING_COMPONENTS;
-      prog->MaxGeometryUniformComponents = MAX_GEOMETRY_UNIFORM_COMPONENTS;
-      prog->MaxGeometryOutputVertices = MAX_GEOMETRY_OUTPUT_VERTICES;
-      prog->MaxGeometryTotalOutputComponents = MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS;
+      prog->MaxUniformComponents = MAX_GEOMETRY_UNIFORM_COMPONENTS;
       break;
    default:
       assert(0 && "Bad program type in init_program_limits()");
@@ -518,6 +523,25 @@ init_program_limits(GLenum type, struct gl_program_constants *prog)
    prog->MaxNativeTemps = 0;
    prog->MaxNativeAddressRegs = 0;
    prog->MaxNativeParameters = 0;
+
+   /* Set GLSL datatype range/precision info assuming IEEE float values.
+    * Drivers should override these defaults as needed.
+    */
+   prog->MediumFloat.RangeMin = 127;
+   prog->MediumFloat.RangeMax = 127;
+   prog->MediumFloat.Precision = 23;
+   prog->LowFloat = prog->HighFloat = prog->MediumFloat;
+
+   /* Assume ints are stored as floats for now, since this is the least-common
+    * denominator.  The OpenGL ES spec implies (page 132) that the precision
+    * of integer types should be 0.  Practically speaking, IEEE
+    * single-precision floating point values can only store integers in the
+    * range [-0x01000000, 0x01000000] without loss of precision.
+    */
+   prog->MediumInt.RangeMin = 24;
+   prog->MediumInt.RangeMax = 24;
+   prog->MediumInt.Precision = 0;
+   prog->LowInt = prog->HighInt = prog->MediumInt;
 }
 
 
@@ -527,11 +551,12 @@ init_program_limits(GLenum type, struct gl_program_constants *prog)
  * some of these values (such as number of texture units).
  */
 static void 
-_mesa_init_constants(GLcontext *ctx)
+_mesa_init_constants(struct gl_context *ctx)
 {
    assert(ctx);
 
    /* Constants, may be overriden (usually only reduced) by device drivers */
+   ctx->Const.MaxTextureMbytes = MAX_TEXTURE_MBYTES;
    ctx->Const.MaxTextureLevels = MAX_TEXTURE_LEVELS;
    ctx->Const.Max3DTextureLevels = MAX_3D_TEXTURE_LEVELS;
    ctx->Const.MaxCubeTextureLevels = MAX_CUBE_TEXTURE_LEVELS;
@@ -543,6 +568,7 @@ _mesa_init_constants(GLcontext *ctx)
                                      ctx->Const.MaxTextureImageUnits);
    ctx->Const.MaxTextureMaxAnisotropy = MAX_TEXTURE_MAX_ANISOTROPY;
    ctx->Const.MaxTextureLodBias = MAX_TEXTURE_LOD_BIAS;
+   ctx->Const.MaxTextureBufferSize = 65536;
    ctx->Const.MaxArrayLockSize = MAX_ARRAY_LOCK_SIZE;
    ctx->Const.SubPixelBits = SUB_PIXEL_BITS;
    ctx->Const.MinPointSize = MIN_POINT_SIZE;
@@ -590,14 +616,17 @@ _mesa_init_constants(GLcontext *ctx)
    ctx->Const.MaxCombinedTextureImageUnits = MAX_COMBINED_TEXTURE_IMAGE_UNITS;
    ctx->Const.MaxVarying = MAX_VARYING;
 #endif
+#if FEATURE_ARB_geometry_shader4
+   ctx->Const.MaxGeometryTextureImageUnits = MAX_GEOMETRY_TEXTURE_IMAGE_UNITS;
+   ctx->Const.MaxVertexVaryingComponents = MAX_VERTEX_VARYING_COMPONENTS;
+   ctx->Const.MaxGeometryVaryingComponents = MAX_GEOMETRY_VARYING_COMPONENTS;
+   ctx->Const.MaxGeometryOutputVertices = MAX_GEOMETRY_OUTPUT_VERTICES;
+   ctx->Const.MaxGeometryTotalOutputComponents = MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS;
+#endif
 
    /* Shading language version */
    if (ctx->API == API_OPENGL) {
-#if FEATURE_ARB_shading_language_120
       ctx->Const.GLSLVersion = 120;
-#else
-      ctx->Const.GLSLVersion = 110;
-#endif
    }
    else if (ctx->API == API_OPENGLES2) {
       ctx->Const.GLSLVersion = 100;
@@ -625,6 +654,13 @@ _mesa_init_constants(GLcontext *ctx)
 
    /* GL 3.2: hard-coded for now: */
    ctx->Const.ProfileMask = GL_CONTEXT_COMPATIBILITY_PROFILE_BIT;
+
+   /** GL_EXT_gpu_shader4 */
+   ctx->Const.MinProgramTexelOffset = -8;
+   ctx->Const.MaxProgramTexelOffset = 7;
+
+   /* GL_ARB_robustness */
+   ctx->Const.ResetStrategy = GL_NO_RESET_NOTIFICATION_ARB;
 }
 
 
@@ -633,7 +669,7 @@ _mesa_init_constants(GLcontext *ctx)
  * Only called the first time a context is bound.
  */
 static void
-check_context_limits(GLcontext *ctx)
+check_context_limits(struct gl_context *ctx)
 {
    /* check that we don't exceed the size of various bitfields */
    assert(VERT_RESULT_MAX <=
@@ -708,7 +744,7 @@ check_context_limits(GLcontext *ctx)
  * functions for the more complex data structures.
  */
 static GLboolean
-init_attrib_groups(GLcontext *ctx)
+init_attrib_groups(struct gl_context *ctx)
 {
    assert(ctx);
 
@@ -760,6 +796,7 @@ init_attrib_groups(GLcontext *ctx)
    /* Miscellaneous */
    ctx->NewState = _NEW_ALL;
    ctx->ErrorValue = (GLenum) GL_NO_ERROR;
+   ctx->ResetStatus = (GLenum) GL_NO_ERROR;
    ctx->varying_vp_inputs = ~0;
 
    return GL_TRUE;
@@ -776,7 +813,7 @@ init_attrib_groups(GLcontext *ctx)
  * state.
  */
 static GLboolean
-update_default_objects(GLcontext *ctx)
+update_default_objects(struct gl_context *ctx)
 {
    assert(ctx);
 
@@ -812,10 +849,13 @@ _mesa_alloc_dispatch_table(int size)
     * Mesa we do this to accomodate different versions of libGL and various
     * DRI drivers.
     */
-   GLint numEntries = MAX2(_glapi_get_dispatch_table_size(),
-                           size / sizeof(_glapi_proc));
-   struct _glapi_table *table =
-      (struct _glapi_table *) malloc(numEntries * sizeof(_glapi_proc));
+   GLint numEntries = MAX2(_glapi_get_dispatch_table_size(), _gloffset_COUNT);
+   struct _glapi_table *table;
+
+   /* should never happen, but just in case */
+   numEntries = MAX2(numEntries, size);
+
+   table = (struct _glapi_table *) malloc(numEntries * sizeof(_glapi_proc));
    if (table) {
       _glapi_proc *entry = (_glapi_proc *) table;
       GLint i;
@@ -828,7 +868,7 @@ _mesa_alloc_dispatch_table(int size)
 
 
 /**
- * Initialize a GLcontext struct (rendering context).
+ * Initialize a struct gl_context struct (rendering context).
  *
  * This includes allocating all the other structs and arrays which hang off of
  * the context by pointers.
@@ -855,12 +895,12 @@ _mesa_alloc_dispatch_table(int size)
  * \param driverContext pointer to driver-specific context data
  */
 GLboolean
-_mesa_initialize_context_for_api(GLcontext *ctx,
-                                gl_api api,
-                                const GLvisual *visual,
-                                GLcontext *share_list,
-                                const struct dd_function_table *driverFunctions,
-                                void *driverContext)
+_mesa_initialize_context(struct gl_context *ctx,
+                         gl_api api,
+                         const struct gl_config *visual,
+                         struct gl_context *share_list,
+                         const struct dd_function_table *driverFunctions,
+                         void *driverContext)
 {
    struct gl_shared_state *shared;
    int i;
@@ -948,13 +988,16 @@ _mesa_initialize_context_for_api(GLcontext *ctx,
       ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE;
    }
 
+   /* Mesa core handles all the formats that mesa core knows about.
+    * Drivers will want to override this list with just the formats
+    * they can handle, and confirm that appropriate fallbacks exist in
+    * _mesa_choose_tex_format().
+    */
+   memset(&ctx->TextureFormatSupported, GL_TRUE,
+         sizeof(ctx->TextureFormatSupported));
+
    switch (ctx->API) {
    case API_OPENGL:
-      /* Neutral tnl module stuff */
-      _mesa_init_exec_vtxfmt( ctx ); 
-      ctx->TnlModule.Current = NULL;
-      ctx->TnlModule.SwapCount = 0;
-
 #if FEATURE_dlist
       ctx->Save = _mesa_create_save_table();
       if (!ctx->Save) {
@@ -993,54 +1036,40 @@ _mesa_initialize_context_for_api(GLcontext *ctx,
    return GL_TRUE;
 }
 
-GLboolean
-_mesa_initialize_context(GLcontext *ctx,
-                         const GLvisual *visual,
-                         GLcontext *share_list,
-                         const struct dd_function_table *driverFunctions,
-                         void *driverContext)
-{
-   return _mesa_initialize_context_for_api(ctx,
-                                          API_OPENGL,
-                                          visual,
-                                          share_list,
-                                          driverFunctions,
-                                          driverContext);
-}
 
 /**
- * Allocate and initialize a GLcontext structure.
+ * Allocate and initialize a struct gl_context structure.
  * Note that the driver needs to pass in its dd_function_table here since
  * we need to at least call driverFunctions->NewTextureObject to initialize
  * the rendering context.
  *
  * \param api the GL API type to create the context for
- * \param visual a GLvisual pointer (we copy the struct contents)
+ * \param visual a struct gl_config pointer (we copy the struct contents)
  * \param share_list another context to share display lists with or NULL
  * \param driverFunctions points to the dd_function_table into which the
  *        driver has plugged in all its special functions.
  * \param driverContext points to the device driver's private context state
  * 
- * \return pointer to a new __GLcontextRec or NULL if error.
+ * \return pointer to a new __struct gl_contextRec or NULL if error.
  */
-GLcontext *
-_mesa_create_context_for_api(gl_api api,
-                            const GLvisual *visual,
-                            GLcontext *share_list,
-                            const struct dd_function_table *driverFunctions,
-                            void *driverContext)
+struct gl_context *
+_mesa_create_context(gl_api api,
+                     const struct gl_config *visual,
+                     struct gl_context *share_list,
+                     const struct dd_function_table *driverFunctions,
+                     void *driverContext)
 {
-   GLcontext *ctx;
+   struct gl_context *ctx;
 
    ASSERT(visual);
    /*ASSERT(driverContext);*/
 
-   ctx = (GLcontext *) calloc(1, sizeof(GLcontext));
+   ctx = (struct gl_context *) calloc(1, sizeof(struct gl_context));
    if (!ctx)
       return NULL;
 
-   if (_mesa_initialize_context_for_api(ctx, api, visual, share_list,
-                                       driverFunctions, driverContext)) {
+   if (_mesa_initialize_context(ctx, api, visual, share_list,
+                                driverFunctions, driverContext)) {
       return ctx;
    }
    else {
@@ -1049,27 +1078,16 @@ _mesa_create_context_for_api(gl_api api,
    }
 }
 
-GLcontext *
-_mesa_create_context(const GLvisual *visual,
-                    GLcontext *share_list,
-                    const struct dd_function_table *driverFunctions,
-                    void *driverContext)
-{
-   return _mesa_create_context_for_api(API_OPENGL, visual,
-                                      share_list,
-                                      driverFunctions,
-                                      driverContext);
-}
 
 /**
  * Free the data associated with the given context.
  * 
- * But doesn't free the GLcontext struct itself.
+ * But doesn't free the struct gl_context struct itself.
  *
  * \sa _mesa_initialize_context() and init_attrib_groups().
  */
 void
-_mesa_free_context_data( GLcontext *ctx )
+_mesa_free_context_data( struct gl_context *ctx )
 {
    if (!_mesa_get_current_context()){
       /* No current context, but we may need one in order to delete
@@ -1143,14 +1161,14 @@ _mesa_free_context_data( GLcontext *ctx )
 
 
 /**
- * Destroy a GLcontext structure.
+ * Destroy a struct gl_context structure.
  *
  * \param ctx GL context.
  * 
- * Calls _mesa_free_context_data() and frees the GLcontext structure itself.
+ * Calls _mesa_free_context_data() and frees the gl_context object itself.
  */
 void
-_mesa_destroy_context( GLcontext *ctx )
+_mesa_destroy_context( struct gl_context *ctx )
 {
    if (ctx) {
       _mesa_free_context_data(ctx);
@@ -1173,7 +1191,8 @@ _mesa_destroy_context( GLcontext *ctx )
  * structures.
  */
 void
-_mesa_copy_context( const GLcontext *src, GLcontext *dst, GLuint mask )
+_mesa_copy_context( const struct gl_context *src, struct gl_context *dst,
+                    GLuint mask )
 {
    if (mask & GL_ACCUM_BUFFER_BIT) {
       /* OK to memcpy */
@@ -1292,13 +1311,11 @@ _mesa_copy_context( const GLcontext *src, GLcontext *dst, GLuint mask )
  * \return GL_TRUE if compatible, GL_FALSE otherwise.
  */
 static GLboolean 
-check_compatible(const GLcontext *ctx, const GLframebuffer *buffer)
+check_compatible(const struct gl_context *ctx,
+                 const struct gl_framebuffer *buffer)
 {
-   const GLvisual *ctxvis = &ctx->Visual;
-   const GLvisual *bufvis = &buffer->Visual;
-
-   if (ctxvis == bufvis)
-      return GL_TRUE;
+   const struct gl_config *ctxvis = &ctx->Visual;
+   const struct gl_config *bufvis = &buffer->Visual;
 
    if (buffer == _mesa_get_incomplete_framebuffer())
       return GL_TRUE;
@@ -1341,7 +1358,7 @@ check_compatible(const GLcontext *ctx, const GLframebuffer *buffer)
  * Really, the device driver should totally take care of this.
  */
 static void
-initialize_framebuffer_size(GLcontext *ctx, GLframebuffer *fb)
+initialize_framebuffer_size(struct gl_context *ctx, struct gl_framebuffer *fb)
 {
    GLuint width, height;
    if (ctx->Driver.GetBufferSize) {
@@ -1358,7 +1375,7 @@ initialize_framebuffer_size(GLcontext *ctx, GLframebuffer *fb)
  * Initialize the size if the given width and height are non-zero.
  */
 void
-_mesa_check_init_viewport(GLcontext *ctx, GLuint width, GLuint height)
+_mesa_check_init_viewport(struct gl_context *ctx, GLuint width, GLuint height)
 {
    if (!ctx->ViewportInitialized && width > 0 && height > 0) {
       /* Note: set flag here, before calling _mesa_set_viewport(), to prevent
@@ -1386,9 +1403,12 @@ _mesa_check_init_viewport(GLcontext *ctx, GLuint width, GLuint height)
  * \param readBuffer  the reading framebuffer
  */
 GLboolean
-_mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer,
-                    GLframebuffer *readBuffer )
+_mesa_make_current( struct gl_context *newCtx,
+                    struct gl_framebuffer *drawBuffer,
+                    struct gl_framebuffer *readBuffer )
 {
+   GET_CURRENT_CONTEXT(curCtx);
+
    if (MESA_VERBOSE & VERBOSE_API)
       _mesa_debug(newCtx, "_mesa_make_current()\n");
 
@@ -1409,6 +1429,12 @@ _mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer,
       }
    }
 
+   if (curCtx && 
+      (curCtx->WinSysDrawBuffer || curCtx->WinSysReadBuffer) &&
+       /* make sure this context is valid for flushing */
+      curCtx != newCtx)
+      _mesa_flush(curCtx);
+
    /* We used to call _glapi_check_multithread() here.  Now do it in drivers */
    _glapi_set_context((void *) newCtx);
    ASSERT(_mesa_get_current_context() == newCtx);
@@ -1420,8 +1446,6 @@ _mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer,
       _glapi_set_dispatch(newCtx->CurrentDispatch);
 
       if (drawBuffer && readBuffer) {
-        /* TODO: check if newCtx and buffer's visual match??? */
-
          ASSERT(drawBuffer->Name == 0);
          ASSERT(readBuffer->Name == 0);
          _mesa_reference_framebuffer(&newCtx->WinSysDrawBuffer, drawBuffer);
@@ -1432,22 +1456,12 @@ _mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer,
           * or not bound to a user-created FBO.
           */
          if (!newCtx->DrawBuffer || newCtx->DrawBuffer->Name == 0) {
-            /* KW: merge conflict here, revisit. 
-             */
-            /* fix up the fb fields - these will end up wrong otherwise
-             * if the DRIdrawable changes, and everything relies on them.
-             * This is a bit messy (same as needed in _mesa_BindFramebufferEXT)
-             */
-            unsigned int i;
-            GLenum buffers[MAX_DRAW_BUFFERS];
-
             _mesa_reference_framebuffer(&newCtx->DrawBuffer, drawBuffer);
-
-            for(i = 0; i < newCtx->Const.MaxDrawBuffers; i++) {
-               buffers[i] = newCtx->Color.DrawBuffer[i];
-            }
-
-            _mesa_drawbuffers(newCtx, newCtx->Const.MaxDrawBuffers, buffers, NULL);
+            /* Update the FBO's list of drawbuffers/renderbuffers.
+             * For winsys FBOs this comes from the GL state (which may have
+             * changed since the last time this FBO was bound).
+             */
+            _mesa_update_draw_buffers(newCtx);
          }
          if (!newCtx->ReadBuffer || newCtx->ReadBuffer->Name == 0) {
             _mesa_reference_framebuffer(&newCtx->ReadBuffer, readBuffer);
@@ -1525,7 +1539,7 @@ _mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer,
  * be deleted if nobody else is sharing them.
  */
 GLboolean
-_mesa_share_state(GLcontext *ctx, GLcontext *ctxToShare)
+_mesa_share_state(struct gl_context *ctx, struct gl_context *ctxToShare)
 {
    if (ctx && ctxToShare && ctx->Shared && ctxToShare->Shared) {
       struct gl_shared_state *oldSharedState = ctx->Shared;
@@ -1556,10 +1570,10 @@ _mesa_share_state(GLcontext *ctx, GLcontext *ctxToShare)
  * context.  If you need speed, see the #GET_CURRENT_CONTEXT macro in
  * context.h.
  */
-GLcontext *
+struct gl_context *
 _mesa_get_current_context( void )
 {
-   return (GLcontext *) _glapi_get_context();
+   return (struct gl_context *) _glapi_get_context();
 }
 
 
@@ -1573,10 +1587,10 @@ _mesa_get_current_context( void )
  *
  * \return pointer to dispatch_table.
  *
- * Simply returns __GLcontextRec::CurrentDispatch.
+ * Simply returns __struct gl_contextRec::CurrentDispatch.
  */
 struct _glapi_table *
-_mesa_get_dispatch(GLcontext *ctx)
+_mesa_get_dispatch(struct gl_context *ctx)
 {
    return ctx->CurrentDispatch;
 }
@@ -1602,7 +1616,7 @@ _mesa_get_dispatch(GLcontext *ctx)
  * This is called via _mesa_error().
  */
 void
-_mesa_record_error(GLcontext *ctx, GLenum error)
+_mesa_record_error(struct gl_context *ctx, GLenum error)
 {
    if (!ctx)
       return;
@@ -1622,7 +1636,7 @@ _mesa_record_error(GLcontext *ctx, GLenum error)
  * Flush commands and wait for completion.
  */
 void
-_mesa_finish(GLcontext *ctx)
+_mesa_finish(struct gl_context *ctx)
 {
    FLUSH_CURRENT( ctx, 0 );
    if (ctx->Driver.Finish) {
@@ -1635,7 +1649,7 @@ _mesa_finish(GLcontext *ctx)
  * Flush commands.
  */
 void
-_mesa_flush(GLcontext *ctx)
+_mesa_flush(struct gl_context *ctx)
 {
    FLUSH_CURRENT( ctx, 0 );
    if (ctx->Driver.Flush) {
@@ -1681,7 +1695,7 @@ _mesa_Flush(void)
  * Otherwise we default to MUL/MAD.
  */
 void
-_mesa_set_mvp_with_dp4( GLcontext *ctx,
+_mesa_set_mvp_with_dp4( struct gl_context *ctx,
                         GLboolean flag )
 {
    ctx->mvp_with_dp4 = flag;
@@ -1697,7 +1711,7 @@ _mesa_set_mvp_with_dp4( GLcontext *ctx,
  * \return GL_TRUE if OK to render, GL_FALSE if not
  */
 GLboolean
-_mesa_valid_to_render(GLcontext *ctx, const char *where)
+_mesa_valid_to_render(struct gl_context *ctx, const char *where)
 {
    bool vert_from_glsl_shader = false;
    bool geom_from_glsl_shader = false;
@@ -1707,11 +1721,10 @@ _mesa_valid_to_render(GLcontext *ctx, const char *where)
    if (ctx->NewState)
       _mesa_update_state(ctx);
 
-   if (ctx->Shader.CurrentProgram) {
-      unsigned i;
+   if (ctx->Shader.CurrentVertexProgram) {
+      vert_from_glsl_shader = true;
 
-      /* using shaders */
-      if (!ctx->Shader.CurrentProgram->LinkStatus) {
+      if (!ctx->Shader.CurrentVertexProgram->LinkStatus) {
          _mesa_error(ctx, GL_INVALID_OPERATION,
                      "%s(shader not linked)", where);
          return GL_FALSE;
@@ -1719,27 +1732,57 @@ _mesa_valid_to_render(GLcontext *ctx, const char *where)
 #if 0 /* not normally enabled */
       {
          char errMsg[100];
-         if (!_mesa_validate_shader_program(ctx, ctx->Shader.CurrentProgram,
+         if (!_mesa_validate_shader_program(ctx,
+                                           ctx->Shader.CurrentVertexProgram,
                                             errMsg)) {
             _mesa_warning(ctx, "Shader program %u is invalid: %s",
-                          ctx->Shader.CurrentProgram->Name, errMsg);
+                          ctx->Shader.CurrentVertexProgram->Name, errMsg);
          }
       }
 #endif
+   }
 
-      /* Figure out which shader stages are provided by the GLSL program.  For
-       * any stages that are not provided, the corresponding assembly shader
-       * target will be validated below.
-       */
-      for (i = 0; i < ctx->Shader.CurrentProgram->_NumLinkedShaders; i++) {
-        switch (ctx->Shader.CurrentProgram->_LinkedShaders[i]->Type) {
-        case GL_VERTEX_SHADER: vert_from_glsl_shader = true; break;
-        case GL_GEOMETRY_SHADER_ARB: geom_from_glsl_shader = true; break;
-        case GL_FRAGMENT_SHADER: frag_from_glsl_shader = true; break;
-        }
+   if (ctx->Shader.CurrentGeometryProgram) {
+      geom_from_glsl_shader = true;
+
+      if (!ctx->Shader.CurrentGeometryProgram->LinkStatus) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "%s(shader not linked)", where);
+         return GL_FALSE;
+      }
+#if 0 /* not normally enabled */
+      {
+         char errMsg[100];
+         if (!_mesa_validate_shader_program(ctx,
+                                           ctx->Shader.CurrentGeometryProgram,
+                                            errMsg)) {
+            _mesa_warning(ctx, "Shader program %u is invalid: %s",
+                          ctx->Shader.CurrentGeometryProgram->Name, errMsg);
+         }
       }
+#endif
    }
 
+   if (ctx->Shader.CurrentFragmentProgram) {
+      frag_from_glsl_shader = true;
+
+      if (!ctx->Shader.CurrentFragmentProgram->LinkStatus) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "%s(shader not linked)", where);
+         return GL_FALSE;
+      }
+#if 0 /* not normally enabled */
+      {
+         char errMsg[100];
+         if (!_mesa_validate_shader_program(ctx,
+                                           ctx->Shader.CurrentFragmentProgram,
+                                            errMsg)) {
+            _mesa_warning(ctx, "Shader program %u is invalid: %s",
+                          ctx->Shader.CurrentFragmentProgram->Name, errMsg);
+         }
+      }
+#endif
+   }
 
    /* Any shader stages that are not supplied by the GLSL shader and have
     * assembly shaders enabled must now be validated.
@@ -1754,12 +1797,23 @@ _mesa_valid_to_render(GLcontext *ctx, const char *where)
    /* FINISHME: If GL_NV_geometry_program4 is ever supported, the current
     * FINISHME: geometry program should validated here.
     */
+   (void) geom_from_glsl_shader;
 
-   if (!frag_from_glsl_shader
-       && ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                 "%s(fragment program not valid)", where);
-      return GL_FALSE;
+   if (!frag_from_glsl_shader) {
+      if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) {
+        _mesa_error(ctx, GL_INVALID_OPERATION,
+                    "%s(fragment program not valid)", where);
+        return GL_FALSE;
+      }
+
+      /* If drawing to integer-valued color buffers, there must be an
+       * active fragment shader (GL_EXT_texture_integer).
+       */
+      if (ctx->DrawBuffer && ctx->DrawBuffer->_IntegerColor) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "%s(integer format but no fragment shader)", where);
+         return GL_FALSE;
+      }
    }
 
    if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
@@ -1770,26 +1824,51 @@ _mesa_valid_to_render(GLcontext *ctx, const char *where)
 
 #ifdef DEBUG
    if (ctx->Shader.Flags & GLSL_LOG) {
-      struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
-      if (shProg) {
-         if (!shProg->_Used) {
-            /* This is the first time this shader is being used.
-             * Append shader's constants/uniforms to log file.
-             */
-            GLuint i;
-            for (i = 0; i < shProg->NumShaders; i++) {
-               struct gl_shader *sh = shProg->Shaders[i];
-               if (sh->Type == GL_VERTEX_SHADER) {
-                  _mesa_append_uniforms_to_file(sh,
-                                                &shProg->VertexProgram->Base);
-               }
-               else if (sh->Type == GL_FRAGMENT_SHADER) {
-                  _mesa_append_uniforms_to_file(sh,
-                                                &shProg->FragmentProgram->Base);
-               }
-            }
-            shProg->_Used = GL_TRUE;
-         }
+      struct gl_shader_program *shProg[MESA_SHADER_TYPES];
+      gl_shader_type i;
+
+      shProg[MESA_SHADER_VERTEX] = ctx->Shader.CurrentVertexProgram;
+      shProg[MESA_SHADER_GEOMETRY] = ctx->Shader.CurrentGeometryProgram;
+      shProg[MESA_SHADER_FRAGMENT] = ctx->Shader.CurrentFragmentProgram;
+
+      for (i = 0; i < MESA_SHADER_TYPES; i++) {
+        struct gl_shader *sh;
+
+        if (shProg[i] == NULL || shProg[i]->_Used
+            || shProg[i]->_LinkedShaders[i] == NULL)
+           continue;
+
+        /* This is the first time this shader is being used.
+         * Append shader's constants/uniforms to log file.
+         *
+         * The logic is a little odd here.  We only want to log data for each
+         * shader target that will actually be used, and we only want to log
+         * it once.  It's possible to have a program bound to the vertex
+         * shader target that also supplied a fragment shader.  If that
+         * program isn't also bound to the fragment shader target we don't
+         * want to log its fragment data.
+         */
+        sh = shProg[i]->_LinkedShaders[i];
+        switch (sh->Type) {
+        case GL_VERTEX_SHADER:
+           _mesa_append_uniforms_to_file(sh, &shProg[i]->VertexProgram->Base);
+           break;
+
+        case GL_GEOMETRY_SHADER_ARB:
+           _mesa_append_uniforms_to_file(sh,
+                                         &shProg[i]->GeometryProgram->Base);
+           break;
+
+        case GL_FRAGMENT_SHADER:
+           _mesa_append_uniforms_to_file(sh,
+                                         &shProg[i]->FragmentProgram->Base);
+           break;
+        }
+      }
+
+      for (i = 0; i < MESA_SHADER_TYPES; i++) {
+        if (shProg[i] != NULL)
+           shProg[i]->_Used = GL_TRUE;
       }
    }
 #endif