From 51a59b7f7f9b134791d3b09673063e4c45ea9eee Mon Sep 17 00:00:00 2001
From: marha <marha@users.sourceforge.net>
Date: Wed, 9 Feb 2011 07:47:31 +0000
Subject: libX11 mesa git update 9 Feb 2011

---
 mesalib/configs/autoconf.in                        |    9 +
 mesalib/configs/default                            |    7 +
 mesalib/configure.ac                               |   21 +
 mesalib/include/GL/internal/dri_interface.h        |    8 +
 mesalib/src/glsl/ast_to_hir.cpp                    |    7 +
 mesalib/src/glsl/glsl_parser_extras.cpp            |    2 +-
 mesalib/src/mesa/drivers/dri/common/dri_util.c     | 2042 ++++-----
 mesalib/src/mesa/drivers/dri/common/dri_util.h     | 1120 ++---
 mesalib/src/mesa/drivers/dri/swrast/swrast.c       |    2 +-
 mesalib/src/mesa/drivers/windows/gdi/wmesa.c       | 3323 +++++++--------
 .../src/mesa/drivers/windows/gldirect/dglcontext.c | 4424 ++++++++++----------
 mesalib/src/mesa/main/blend.c                      | 1636 ++++----
 mesalib/src/mesa/main/bufferobj.c                  | 4303 +++++++++----------
 mesalib/src/mesa/main/context.c                    |   61 +-
 mesalib/src/mesa/main/context.h                    |  639 ++-
 mesalib/src/mesa/main/depth.c                      |  342 +-
 mesalib/src/mesa/main/hint.c                       |  293 +-
 mesalib/src/mesa/main/lines.c                      |  228 +-
 mesalib/src/mesa/main/mtypes.h                     |   17 +-
 mesalib/src/mesa/main/queryobj.c                   | 1208 +++---
 mesalib/src/mesa/main/shaderapi.c                  |   11 +
 mesalib/src/mesa/main/stencil.c                    | 1204 +++---
 mesalib/src/mesa/program/ir_to_mesa.cpp            |   47 +-
 mesalib/src/mesa/state_tracker/st_context.c        |  584 +--
 mesalib/src/mesa/state_tracker/st_draw_feedback.c  |  557 +--
 mesalib/src/mesa/state_tracker/st_program.c        | 2319 +++++-----
 26 files changed, 12290 insertions(+), 12124 deletions(-)

(limited to 'mesalib')

diff --git a/mesalib/configs/autoconf.in b/mesalib/configs/autoconf.in
index b7137a0ee..2ab18505c 100644
--- a/mesalib/configs/autoconf.in
+++ b/mesalib/configs/autoconf.in
@@ -64,6 +64,7 @@ GLESv1_CM_LIB = GLESv1_CM
 GLESv2_LIB = GLESv2
 VG_LIB = OpenVG
 GLAPI_LIB = glapi
+WAYLAND_EGL_LIB = wayland-egl
 
 # Library names (actual file names)
 GL_LIB_NAME = @GL_LIB_NAME@
@@ -76,6 +77,7 @@ GLESv1_CM_LIB_NAME = @GLESv1_CM_LIB_NAME@
 GLESv2_LIB_NAME = @GLESv2_LIB_NAME@
 VG_LIB_NAME = @VG_LIB_NAME@
 GLAPI_LIB_NAME = @GLAPI_LIB_NAME@
+WAYLAND_EGL_LIB_NAME = @WAYLAND_EGL_LIB_NAME@
 
 # Globs used to install the lib and all symlinks
 GL_LIB_GLOB = @GL_LIB_GLOB@
@@ -88,6 +90,7 @@ GLESv1_CM_LIB_GLOB = @GLESv1_CM_LIB_GLOB@
 GLESv2_LIB_GLOB = @GLESv2_LIB_GLOB@
 VG_LIB_GLOB = @VG_LIB_GLOB@
 GLAPI_LIB_GLOB = @GLAPI_LIB_GLOB@
+WAYLAND_EGL_LIB_GLOB = @WAYLAND_EGL_LIB_GLOB@
 
 # Directories to build
 LIB_DIR = @LIB_DIR@
@@ -131,6 +134,7 @@ GLESv1_CM_LIB_DEPS = $(EXTRA_LIB_PATH) @GLESv1_CM_LIB_DEPS@
 GLESv2_LIB_DEPS = $(EXTRA_LIB_PATH) @GLESv2_LIB_DEPS@
 VG_LIB_DEPS = $(EXTRA_LIB_PATH) @VG_LIB_DEPS@
 GLAPI_LIB_DEPS = $(EXTRA_LIB_PATH) @GLAPI_LIB_DEPS@
+WAYLAND_EGL_LIB_DEPS = $(EXTRA_LIBPATH) @WAYLAND_EGL_LIB_DEPS@
 
 # DRI dependencies
 DRI_LIB_DEPS = $(EXTRA_LIB_PATH) @DRI_LIB_DEPS@
@@ -184,11 +188,16 @@ GLESv2_PC_LIB_PRIV = @GLESv2_PC_LIB_PRIV@
 EGL_PC_REQ_PRIV = @GL_PC_REQ_PRIV@
 EGL_PC_LIB_PRIV = @GL_PC_LIB_PRIV@
 EGL_PC_CFLAGS = @GL_PC_CFLAGS@
+WAYLAND_EGL_PC_REQ_PRIV = @WAYLAND_EGL_PC_REQ_PRIV@
+WAYLAND_EGL_PC_LIB_PRIV = @WAYLAND_EGL_PC_LIB_PRIV@
+WAYLAND_EGL_PC_CFLAGS = @WAYLAND_EGL_PC_CFLAGS@
 
 XCB_DRI2_CFLAGS = @XCB_DRI2_CFLAGS@
 XCB_DRI2_LIBS = @XCB_DRI2_LIBS@
 LIBUDEV_CFLAGS = @LIBUDEV_CFLAGS@
 LIBUDEV_LIBS = @LIBUDEV_LIBS@
+WAYLAND_CFLAGS = @WAYLAND_CFLAGS@
+WAYLAND_LIBS = @WAYLAND_LIBS@
 
 MESA_LLVM = @MESA_LLVM@
 
diff --git a/mesalib/configs/default b/mesalib/configs/default
index b05e9fffc..442eb848e 100644
--- a/mesalib/configs/default
+++ b/mesalib/configs/default
@@ -60,6 +60,7 @@ GLESv1_CM_LIB = GLESv1_CM
 GLESv2_LIB = GLESv2
 VG_LIB = OpenVG
 GLAPI_LIB = glapi
+WAYLAND_EGL_LIB = wayland-egl
 
 
 # Library names (actual file names)
@@ -73,6 +74,7 @@ GLESv1_CM_LIB_NAME = lib$(GLESv1_CM_LIB).so
 GLESv2_LIB_NAME = lib$(GLESv2_LIB).so
 VG_LIB_NAME = lib$(VG_LIB).so
 GLAPI_LIB_NAME = lib$(GLAPI_LIB).so
+WAYLAND_EGL_LIB_NAME = lib$(WAYLAND_EGL_LIB).so
 
 # globs used to install the lib and all symlinks
 GL_LIB_GLOB = $(GL_LIB_NAME)*
@@ -85,6 +87,7 @@ GLESv1_CM_LIB_GLOB = $(GLESv1_CM_LIB_NAME)*
 GLESv2_LIB_GLOB = $(GLESv2_LIB_NAME)*
 VG_LIB_GLOB = $(VG_LIB_NAME)*
 GLAPI_LIB_GLOB = $(GLAPI_LIB_NAME)*
+WAYLAND_EGL_LIB_GLOB = $(WAYLAND_EGL_LIB_NAME)*
 
 # Optional assembly language optimization files for libGL
 MESA_ASM_SOURCES = 
@@ -131,6 +134,7 @@ GLESv1_CM_LIB_DEPS = $(EXTRA_LIB_PATH) -lpthread
 GLESv2_LIB_DEPS = $(EXTRA_LIB_PATH) -lpthread
 VG_LIB_DEPS    = $(EXTRA_LIB_PATH) -lpthread
 GLAPI_LIB_DEPS = $(EXTRA_LIB_PATH) -lpthread
+WAYLAND_EGL_LIB_DEPS = $(EXTRA_LIB_PATH) -lwayland-client -ldrm
 
 # Program dependencies - specific GL/glut libraries added in Makefiles
 APP_LIB_DEPS = -lm
@@ -179,3 +183,6 @@ GLESv2_PC_CFLAGS =
 VG_PC_REQ_PRIV =
 VG_PC_LIB_PRIV =
 VG_PC_CFLAGS =
+WAYLAND_EGL_PC_REQ_PRIV =
+WAYLAND_EGL_PC_LIB_PRIV =
+WAYLAND_EGL_PC_CFLAGS =
diff --git a/mesalib/configure.ac b/mesalib/configure.ac
index 9c6ce3f21..aa3895b9c 100644
--- a/mesalib/configure.ac
+++ b/mesalib/configure.ac
@@ -318,6 +318,7 @@ GLESv1_CM_LIB_NAME='lib$(GLESv1_CM_LIB).'${LIB_EXTENSION}
 GLESv2_LIB_NAME='lib$(GLESv2_LIB).'${LIB_EXTENSION}
 VG_LIB_NAME='lib$(VG_LIB).'${LIB_EXTENSION}
 GLAPI_LIB_NAME='lib$(GLAPI_LIB).'${LIB_EXTENSION}
+WAYLAND_EGL_LIB_NAME='lib$(WAYLAND_EGL_LIB).'${LIB_EXTENSION}
 
 GL_LIB_GLOB=${LIB_PREFIX_GLOB}'$(GL_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*'
 GLU_LIB_GLOB=${LIB_PREFIX_GLOB}'$(GLU_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*'
@@ -330,6 +331,7 @@ GLESv1_CM_LIB_GLOB=${LIB_PREFIX_GLOB}'$(GLESv1_CM_LIB)'${LIB_VERSION_SEPARATOR}'
 GLESv2_LIB_GLOB=${LIB_PREFIX_GLOB}'$(GLESv2_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*'
 VG_LIB_GLOB=${LIB_PREFIX_GLOB}'$(VG_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*'
 GLAPI_LIB_GLOB=${LIB_PREFIX_GLOB}'$(GLAPI_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*'
+WAYLAND_EGL_LIB_GLOB=${LIB_PREFIX_GLOB}'$(WAYLAND_EGL_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*'
 
 AC_SUBST([GL_LIB_NAME])
 AC_SUBST([GLU_LIB_NAME])
@@ -341,6 +343,7 @@ AC_SUBST([GLESv1_CM_LIB_NAME])
 AC_SUBST([GLESv2_LIB_NAME])
 AC_SUBST([VG_LIB_NAME])
 AC_SUBST([GLAPI_LIB_NAME])
+AC_SUBST([WAYLAND_EGL_LIB_NAME])
 
 AC_SUBST([GL_LIB_GLOB])
 AC_SUBST([GLU_LIB_GLOB])
@@ -352,6 +355,7 @@ AC_SUBST([GLESv1_CM_LIB_GLOB])
 AC_SUBST([GLESv2_LIB_GLOB])
 AC_SUBST([VG_LIB_GLOB])
 AC_SUBST([GLAPI_LIB_GLOB])
+AC_SUBST([WAYLAND_EGL_LIB_GLOB])
 
 dnl
 dnl Arch/platform-specific settings
@@ -1515,6 +1519,8 @@ AC_ARG_WITH([egl-displays],
     [with_egl_platforms="$withval"])
 
 EGL_PLATFORMS=""
+WAYLAND_EGL_LIB_DEPS=""
+
 case "$with_egl_platforms" in
 yes)
     if test "x$enable_egl" = xyes && test "x$mesa_driver" != xosmesa; then
@@ -1536,12 +1542,27 @@ yes)
         if test "$plat" = "fbdev"; then
                 GALLIUM_WINSYS_DIRS="$GALLIUM_WINSYS_DIRS sw/fbdev"
         fi
+	if test "$plat" = "wayland"; then
+		PKG_CHECK_MODULES([WAYLAND], [wayland-client],, \
+				  [AC_MSG_ERROR([cannot find libwayland-client])])
+		WAYLAND_EGL_LIB_DEPS="$WAYLAND_LIBS $LIBDRM_LIBS"
+	fi
     done
     EGL_PLATFORMS="$egl_platforms"
     ;;
 esac
 AC_SUBST([EGL_PLATFORMS])
 
+AC_SUBST([WAYLAND_EGL_LIB_DEPS])
+WAYLAND_EGL_PC_REQ_PRIV="wayland-client libdrm"
+WAYLAND_EGL_PC_LIB_PRIV=
+WAYLAND_EGL_PC_CFLAGS=
+
+AC_SUBST([WAYLAND_EGL_PC_REQ_PRIV])
+AC_SUBST([WAYLAND_EGL_PC_LIB_PRIV])
+AC_SUBST([WAYLAND_EGL_PC_CFLAGS])
+
+
 AC_ARG_WITH([egl-driver-dir],
     [AS_HELP_STRING([--with-egl-driver-dir=DIR],
                     [directory for EGL drivers [[default=${libdir}/egl]]])],
diff --git a/mesalib/include/GL/internal/dri_interface.h b/mesalib/include/GL/internal/dri_interface.h
index 035152677..2fb729afc 100644
--- a/mesalib/include/GL/internal/dri_interface.h
+++ b/mesalib/include/GL/internal/dri_interface.h
@@ -786,6 +786,14 @@ struct __DRIdri2ExtensionRec {
 					   const __DRIconfig *config,
 					   __DRIcontext *shared,
 					   void *data);
+
+   __DRIbuffer *(*allocateBuffer)(__DRIscreen *screen,
+				  unsigned int attachment,
+				  unsigned int format,
+				  int width,
+				  int height);
+   void (*releaseBuffer)(__DRIscreen *screen,
+			 __DRIbuffer *buffer);
 };
 
 
diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp
index 75f28cd2c..bef099cca 100644
--- a/mesalib/src/glsl/ast_to_hir.cpp
+++ b/mesalib/src/glsl/ast_to_hir.cpp
@@ -435,6 +435,13 @@ modulus_result_type(const struct glsl_type *type_a,
 		    const struct glsl_type *type_b,
 		    struct _mesa_glsl_parse_state *state, YYLTYPE *loc)
 {
+   if (state->language_version < 130) {
+      _mesa_glsl_error(loc, state,
+                       "operator '%%' is reserved in %s",
+                       state->version_string);
+      return glsl_type::error_type;
+   }
+
    /* From GLSL 1.50 spec, page 56:
     *    "The operator modulus (%) operates on signed or unsigned integers or
     *    integer vectors. The operand types must both be signed or both be
diff --git a/mesalib/src/glsl/glsl_parser_extras.cpp b/mesalib/src/glsl/glsl_parser_extras.cpp
index c2bb59b9c..d7a37aef4 100644
--- a/mesalib/src/glsl/glsl_parser_extras.cpp
+++ b/mesalib/src/glsl/glsl_parser_extras.cpp
@@ -764,7 +764,7 @@ do_common_optimization(exec_list *ir, bool linked, unsigned max_unroll_iteration
    progress = do_if_simplification(ir) || progress;
    progress = do_discard_simplification(ir) || progress;
    progress = do_copy_propagation(ir) || progress;
-   progress = do_copy_propagation_elements(ir) || progress;
+   /*progress = do_copy_propagation_elements(ir) || progress;*/
    if (linked)
       progress = do_dead_code(ir) || progress;
    else
diff --git a/mesalib/src/mesa/drivers/dri/common/dri_util.c b/mesalib/src/mesa/drivers/dri/common/dri_util.c
index 8b3b55e5e..82638fa72 100644
--- a/mesalib/src/mesa/drivers/dri/common/dri_util.c
+++ b/mesalib/src/mesa/drivers/dri/common/dri_util.c
@@ -1,1012 +1,1030 @@
-/**
- * \file dri_util.c
- * DRI utility functions.
- *
- * This module acts as glue between GLX and the actual hardware driver.  A DRI
- * driver doesn't really \e have to use any of this - it's optional.  But, some
- * useful stuff is done here that otherwise would have to be duplicated in most
- * drivers.
- * 
- * Basically, these utility functions take care of some of the dirty details of
- * screen initialization, context creation, context binding, DRM setup, etc.
- *
- * These functions are compiled into each DRI driver so libGL.so knows nothing
- * about them.
- */
-
-
-#include <assert.h>
-#include <stdarg.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include <stdio.h>
-
-#ifndef MAP_FAILED
-#define MAP_FAILED ((void *)-1)
-#endif
-
-#include "main/imports.h"
-#define None 0
-
-#include "dri_util.h"
-#include "drm_sarea.h"
-#include "utils.h"
-#include "xmlpool.h"
-#include "../glsl/glsl_parser_extras.h"
-
-PUBLIC const char __dri2ConfigOptions[] =
-   DRI_CONF_BEGIN
-      DRI_CONF_SECTION_PERFORMANCE
-         DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_1)
-      DRI_CONF_SECTION_END
-   DRI_CONF_END;
-
-static const uint __dri2NConfigOptions = 1;
-
-#ifndef GLX_OML_sync_control
-typedef GLboolean ( * PFNGLXGETMSCRATEOMLPROC) (__DRIdrawable *drawable, int32_t *numerator, int32_t *denominator);
-#endif
-
-static void dri_get_drawable(__DRIdrawable *pdp);
-static void dri_put_drawable(__DRIdrawable *pdp);
-
-/**
- * This is just a token extension used to signal that the driver
- * supports setting a read drawable.
- */
-const __DRIextension driReadDrawableExtension = {
-    __DRI_READ_DRAWABLE, __DRI_READ_DRAWABLE_VERSION
-};
-
-GLint
-driIntersectArea( drm_clip_rect_t rect1, drm_clip_rect_t rect2 )
-{
-   if (rect2.x1 > rect1.x1) rect1.x1 = rect2.x1;
-   if (rect2.x2 < rect1.x2) rect1.x2 = rect2.x2;
-   if (rect2.y1 > rect1.y1) rect1.y1 = rect2.y1;
-   if (rect2.y2 < rect1.y2) rect1.y2 = rect2.y2;
-
-   if (rect1.x1 > rect1.x2 || rect1.y1 > rect1.y2) return 0;
-
-   return (rect1.x2 - rect1.x1) * (rect1.y2 - rect1.y1);
-}
-
-/*****************************************************************/
-/** \name Context (un)binding functions                          */
-/*****************************************************************/
-/*@{*/
-
-/**
- * Unbind context.
- * 
- * \param scrn the screen.
- * \param gc context.
- *
- * \return \c GL_TRUE on success, or \c GL_FALSE on failure.
- * 
- * \internal
- * This function calls __DriverAPIRec::UnbindContext, and then decrements
- * __DRIdrawableRec::refcount which must be non-zero for a successful
- * return.
- * 
- * While casting the opaque private pointers associated with the parameters
- * into their respective real types it also assures they are not \c NULL. 
- */
-static int driUnbindContext(__DRIcontext *pcp)
-{
-    __DRIscreen *psp;
-    __DRIdrawable *pdp;
-    __DRIdrawable *prp;
-
-    /*
-    ** Assume error checking is done properly in glXMakeCurrent before
-    ** calling driUnbindContext.
-    */
-
-    if (pcp == NULL)
-        return GL_FALSE;
-
-    psp = pcp->driScreenPriv;
-    pdp = pcp->driDrawablePriv;
-    prp = pcp->driReadablePriv;
-
-    /* already unbound */
-    if (!pdp && !prp)
-      return GL_TRUE;
-    /* Let driver unbind drawable from context */
-    (*psp->DriverAPI.UnbindContext)(pcp);
-
-    assert(pdp);
-    if (pdp->refcount == 0) {
-	/* ERROR!!! */
-	return GL_FALSE;
-    }
-
-    dri_put_drawable(pdp);
-
-    if (prp != pdp) {
-        if (prp->refcount == 0) {
-	    /* ERROR!!! */
-	    return GL_FALSE;
-	}
-
-    	dri_put_drawable(prp);
-    }
-
-
-    /* XXX this is disabled so that if we call SwapBuffers on an unbound
-     * window we can determine the last context bound to the window and
-     * use that context's lock. (BrianP, 2-Dec-2000)
-     */
-    pcp->driDrawablePriv = pcp->driReadablePriv = NULL;
-
-    return GL_TRUE;
-}
-
-/**
- * This function takes both a read buffer and a draw buffer.  This is needed
- * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
- * function.
- */
-static int driBindContext(__DRIcontext *pcp,
-			  __DRIdrawable *pdp,
-			  __DRIdrawable *prp)
-{
-    __DRIscreen *psp = NULL;
-
-    /*
-    ** Assume error checking is done properly in glXMakeCurrent before
-    ** calling driUnbindContext.
-    */
-
-    if (!pcp)
-	return GL_FALSE;
-
-    /* Bind the drawable to the context */
-    psp = pcp->driScreenPriv;
-    pcp->driDrawablePriv = pdp;
-    pcp->driReadablePriv = prp;
-    if (pdp) {
-	pdp->driContextPriv = pcp;
-	dri_get_drawable(pdp);
-    }
-    if (prp && pdp != prp) {
-	dri_get_drawable(prp);
-    }
-
-    /*
-    ** Now that we have a context associated with this drawable, we can
-    ** initialize the drawable information if has not been done before.
-    */
-
-    if (!psp->dri2.enabled) {
-	if (pdp && !pdp->pStamp) {
-	    DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
-	    __driUtilUpdateDrawableInfo(pdp);
-	    DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
-	}
-	if (prp && pdp != prp && !prp->pStamp) {
-	    DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
-	    __driUtilUpdateDrawableInfo(prp);
-	    DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
-        }
-    }
-
-    /* Call device-specific MakeCurrent */
-    return (*psp->DriverAPI.MakeCurrent)(pcp, pdp, prp);
-}
-
-/*@}*/
-
-
-/*****************************************************************/
-/** \name Drawable handling functions                            */
-/*****************************************************************/
-/*@{*/
-
-/**
- * Update private drawable information.
- *
- * \param pdp pointer to the private drawable information to update.
- * 
- * This function basically updates the __DRIdrawable struct's
- * cliprect information by calling \c __DRIinterfaceMethods::getDrawableInfo.
- * This is usually called by the DRI_VALIDATE_DRAWABLE_INFO macro which
- * compares the __DRIdrwablePrivate pStamp and lastStamp values.  If
- * the values are different that means we have to update the clipping
- * info.
- */
-void
-__driUtilUpdateDrawableInfo(__DRIdrawable *pdp)
-{
-    __DRIscreen *psp = pdp->driScreenPriv;
-    __DRIcontext *pcp = pdp->driContextPriv;
-    
-    if (!pcp 
-	|| ((pdp != pcp->driDrawablePriv) && (pdp != pcp->driReadablePriv))) {
-	/* ERROR!!! 
-	 * ...but we must ignore it. There can be many contexts bound to a
-	 * drawable.
-	 */
-    }
-
-    if (pdp->pClipRects) {
-	free(pdp->pClipRects); 
-	pdp->pClipRects = NULL;
-    }
-
-    if (pdp->pBackClipRects) {
-	free(pdp->pBackClipRects); 
-	pdp->pBackClipRects = NULL;
-    }
-
-    DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
-
-    if (! (*psp->getDrawableInfo->getDrawableInfo)(pdp,
-			  &pdp->index, &pdp->lastStamp,
-			  &pdp->x, &pdp->y, &pdp->w, &pdp->h,
-			  &pdp->numClipRects, &pdp->pClipRects,
-			  &pdp->backX,
-			  &pdp->backY,
-			  &pdp->numBackClipRects,
-			  &pdp->pBackClipRects,
-			  pdp->loaderPrivate)) {
-	/* Error -- eg the window may have been destroyed.  Keep going
-	 * with no cliprects.
-	 */
-        pdp->pStamp = &pdp->lastStamp; /* prevent endless loop */
-	pdp->numClipRects = 0;
-	pdp->pClipRects = NULL;
-	pdp->numBackClipRects = 0;
-	pdp->pBackClipRects = NULL;
-    }
-    else
-       pdp->pStamp = &(psp->pSAREA->drawableTable[pdp->index].stamp);
-
-    DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
-}
-
-/*@}*/
-
-/*****************************************************************/
-/** \name GLX callbacks                                          */
-/*****************************************************************/
-/*@{*/
-
-static void driReportDamage(__DRIdrawable *pdp,
-			    struct drm_clip_rect *pClipRects, int numClipRects)
-{
-    __DRIscreen *psp = pdp->driScreenPriv;
-
-    /* Check that we actually have the new damage report method */
-    if (psp->damage) {
-	/* Report the damage.  Currently, all our drivers draw
-	 * directly to the front buffer, so we report the damage there
-	 * rather than to the backing storein (if any).
-	 */
-	(*psp->damage->reportDamage)(pdp,
-				     pdp->x, pdp->y,
-				     pClipRects, numClipRects,
-				     GL_TRUE, pdp->loaderPrivate);
-    }
-}
-
-
-/**
- * Swap buffers.
- *
- * \param drawablePrivate opaque pointer to the per-drawable private info.
- * 
- * \internal
- * This function calls __DRIdrawable::swapBuffers.
- * 
- * Is called directly from glXSwapBuffers().
- */
-static void driSwapBuffers(__DRIdrawable *dPriv)
-{
-    __DRIscreen *psp = dPriv->driScreenPriv;
-    drm_clip_rect_t *rects;
-    int i;
-
-    psp->DriverAPI.SwapBuffers(dPriv);
-
-    if (!dPriv->numClipRects)
-        return;
-
-    rects = malloc(sizeof(*rects) * dPriv->numClipRects);
-
-    if (!rects)
-        return;
-
-    for (i = 0; i < dPriv->numClipRects; i++) {
-        rects[i].x1 = dPriv->pClipRects[i].x1 - dPriv->x;
-        rects[i].y1 = dPriv->pClipRects[i].y1 - dPriv->y;
-        rects[i].x2 = dPriv->pClipRects[i].x2 - dPriv->x;
-        rects[i].y2 = dPriv->pClipRects[i].y2 - dPriv->y;
-    }
-
-    driReportDamage(dPriv, rects, dPriv->numClipRects);
-    free(rects);
-}
-
-static int driDrawableGetMSC( __DRIscreen *sPriv, __DRIdrawable *dPriv,
-			      int64_t *msc )
-{
-    return sPriv->DriverAPI.GetDrawableMSC(sPriv, dPriv, msc);
-}
-
-
-static int driWaitForMSC(__DRIdrawable *dPriv, int64_t target_msc,
-			 int64_t divisor, int64_t remainder,
-			 int64_t * msc, int64_t * sbc)
-{
-    __DRIswapInfo  sInfo;
-    int  status;
-
-    status = dPriv->driScreenPriv->DriverAPI.WaitForMSC( dPriv, target_msc,
-                                                         divisor, remainder,
-                                                         msc );
-
-    /* GetSwapInfo() may not be provided by the driver if GLX_SGI_video_sync
-     * is supported but GLX_OML_sync_control is not.  Therefore, don't return
-     * an error value if GetSwapInfo() is not implemented.
-    */
-    if ( status == 0
-         && dPriv->driScreenPriv->DriverAPI.GetSwapInfo ) {
-        status = dPriv->driScreenPriv->DriverAPI.GetSwapInfo( dPriv, & sInfo );
-        *sbc = sInfo.swap_count;
-    }
-
-    return status;
-}
-
-
-const __DRImediaStreamCounterExtension driMediaStreamCounterExtension = {
-    { __DRI_MEDIA_STREAM_COUNTER, __DRI_MEDIA_STREAM_COUNTER_VERSION },
-    driWaitForMSC,
-    driDrawableGetMSC,
-};
-
-
-static void driCopySubBuffer(__DRIdrawable *dPriv,
-			      int x, int y, int w, int h)
-{
-    drm_clip_rect_t rect;
-
-    rect.x1 = x;
-    rect.y1 = dPriv->h - y - h;
-    rect.x2 = x + w;
-    rect.y2 = rect.y1 + h;
-    driReportDamage(dPriv, &rect, 1);
-
-    dPriv->driScreenPriv->DriverAPI.CopySubBuffer(dPriv, x, y, w, h);
-}
-
-const __DRIcopySubBufferExtension driCopySubBufferExtension = {
-    { __DRI_COPY_SUB_BUFFER, __DRI_COPY_SUB_BUFFER_VERSION },
-    driCopySubBuffer
-};
-
-static void driSetSwapInterval(__DRIdrawable *dPriv, unsigned int interval)
-{
-    dPriv->swap_interval = interval;
-}
-
-static unsigned int driGetSwapInterval(__DRIdrawable *dPriv)
-{
-    return dPriv->swap_interval;
-}
-
-const __DRIswapControlExtension driSwapControlExtension = {
-    { __DRI_SWAP_CONTROL, __DRI_SWAP_CONTROL_VERSION },
-    driSetSwapInterval,
-    driGetSwapInterval
-};
-
-
-/**
- * This is called via __DRIscreenRec's createNewDrawable pointer.
- */
-static __DRIdrawable *
-driCreateNewDrawable(__DRIscreen *psp, const __DRIconfig *config,
-		     drm_drawable_t hwDrawable, int renderType,
-		     const int *attrs, void *data)
-{
-    __DRIdrawable *pdp;
-
-    /* Since pbuffers are not yet supported, no drawable attributes are
-     * supported either.
-     */
-    (void) attrs;
-
-    pdp = malloc(sizeof *pdp);
-    if (!pdp) {
-	return NULL;
-    }
-
-    pdp->driContextPriv = NULL;
-    pdp->loaderPrivate = data;
-    pdp->hHWDrawable = hwDrawable;
-    pdp->refcount = 1;
-    pdp->pStamp = NULL;
-    pdp->lastStamp = 0;
-    pdp->index = 0;
-    pdp->x = 0;
-    pdp->y = 0;
-    pdp->w = 0;
-    pdp->h = 0;
-    pdp->numClipRects = 0;
-    pdp->numBackClipRects = 0;
-    pdp->pClipRects = NULL;
-    pdp->pBackClipRects = NULL;
-    pdp->vblSeq = 0;
-    pdp->vblFlags = 0;
-
-    pdp->driScreenPriv = psp;
-
-    if (!(*psp->DriverAPI.CreateBuffer)(psp, pdp, &config->modes, 0)) {
-       free(pdp);
-       return NULL;
-    }
-
-    pdp->msc_base = 0;
-
-    /* This special default value is replaced with the configured
-     * default value when the drawable is first bound to a direct
-     * rendering context. 
-     */
-    pdp->swap_interval = (unsigned)-1;
-
-    return pdp;
-}
-
-
-static __DRIdrawable *
-dri2CreateNewDrawable(__DRIscreen *screen,
-		      const __DRIconfig *config,
-		      void *loaderPrivate)
-{
-    __DRIdrawable *pdraw;
-
-    pdraw = driCreateNewDrawable(screen, config, 0, 0, NULL, loaderPrivate);
-    if (!pdraw)
-    	return NULL;
-
-    pdraw->pClipRects = &pdraw->dri2.clipRect;
-    pdraw->pBackClipRects = &pdraw->dri2.clipRect;
-
-    pdraw->pStamp = &pdraw->dri2.stamp;
-    *pdraw->pStamp = pdraw->lastStamp + 1;
-
-    return pdraw;
-}
-
-static int
-dri2ConfigQueryb(__DRIscreen *screen, const char *var, GLboolean *val)
-{
-   if (!driCheckOption(&screen->optionCache, var, DRI_BOOL))
-      return -1;
-
-   *val = driQueryOptionb(&screen->optionCache, var);
-
-   return 0;
-}
-
-static int
-dri2ConfigQueryi(__DRIscreen *screen, const char *var, GLint *val)
-{
-   if (!driCheckOption(&screen->optionCache, var, DRI_INT) &&
-       !driCheckOption(&screen->optionCache, var, DRI_ENUM))
-      return -1;
-
-    *val = driQueryOptioni(&screen->optionCache, var);
-
-    return 0;
-}
-
-static int
-dri2ConfigQueryf(__DRIscreen *screen, const char *var, GLfloat *val)
-{
-   if (!driCheckOption(&screen->optionCache, var, DRI_FLOAT))
-      return -1;
-
-    *val = driQueryOptionf(&screen->optionCache, var);
-
-    return 0;
-}
-
-
-static void dri_get_drawable(__DRIdrawable *pdp)
-{
-    pdp->refcount++;
-}
-	
-static void dri_put_drawable(__DRIdrawable *pdp)
-{
-    __DRIscreen *psp;
-
-    if (pdp) {
-	pdp->refcount--;
-	if (pdp->refcount)
-	    return;
-
-	psp = pdp->driScreenPriv;
-        (*psp->DriverAPI.DestroyBuffer)(pdp);
-	if (pdp->pClipRects && pdp->pClipRects != &pdp->dri2.clipRect) {
-	    free(pdp->pClipRects);
-	    pdp->pClipRects = NULL;
-	}
-	if (pdp->pBackClipRects && pdp->pClipRects != &pdp->dri2.clipRect) {
-	    free(pdp->pBackClipRects);
-	    pdp->pBackClipRects = NULL;
-	}
-	free(pdp);
-    }
-}
-
-static void
-driDestroyDrawable(__DRIdrawable *pdp)
-{
-    dri_put_drawable(pdp);
-}
-
-/*@}*/
-
-
-/*****************************************************************/
-/** \name Context handling functions                             */
-/*****************************************************************/
-/*@{*/
-
-/**
- * Destroy the per-context private information.
- * 
- * \internal
- * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls
- * drmDestroyContext(), and finally frees \p contextPrivate.
- */
-static void
-driDestroyContext(__DRIcontext *pcp)
-{
-    if (pcp) {
-	(*pcp->driScreenPriv->DriverAPI.DestroyContext)(pcp);
-	free(pcp);
-    }
-}
-
-
-/**
- * Create the per-drawable private driver information.
- * 
- * \param render_type   Type of rendering target.  \c GLX_RGBA is the only
- *                      type likely to ever be supported for direct-rendering.
- * \param shared        Context with which to share textures, etc. or NULL
- *
- * \returns An opaque pointer to the per-context private information on
- *          success, or \c NULL on failure.
- * 
- * \internal
- * This function allocates and fills a __DRIcontextRec structure.  It
- * performs some device independent initialization and passes all the
- * relevent information to __DriverAPIRec::CreateContext to create the
- * context.
- *
- */
-static __DRIcontext *
-driCreateNewContext(__DRIscreen *psp, const __DRIconfig *config,
-		    int render_type, __DRIcontext *shared, 
-		    drm_context_t hwContext, void *data)
-{
-    __DRIcontext *pcp;
-    void * const shareCtx = (shared != NULL) ? shared->driverPrivate : NULL;
-
-    pcp = malloc(sizeof *pcp);
-    if (!pcp)
-	return NULL;
-
-    pcp->driScreenPriv = psp;
-    pcp->driDrawablePriv = NULL;
-    pcp->loaderPrivate = data;
-    
-    pcp->dri2.draw_stamp = 0;
-    pcp->dri2.read_stamp = 0;
-
-    pcp->hHWContext = hwContext;
-
-    if ( !(*psp->DriverAPI.CreateContext)(API_OPENGL,
-					  &config->modes, pcp, shareCtx) ) {
-        free(pcp);
-        return NULL;
-    }
-
-    return pcp;
-}
-
-static unsigned int
-dri2GetAPIMask(__DRIscreen *screen)
-{
-    return screen->api_mask;
-}
-
-static __DRIcontext *
-dri2CreateNewContextForAPI(__DRIscreen *screen, int api,
-			   const __DRIconfig *config,
-			   __DRIcontext *shared, void *data)
-{
-    __DRIcontext *context;
-    const struct gl_config *modes = (config != NULL) ? &config->modes : NULL;
-    void *shareCtx = (shared != NULL) ? shared->driverPrivate : NULL;
-    gl_api mesa_api;
-
-    if (!(screen->api_mask & (1 << api)))
-	return NULL;
-
-    switch (api) {
-    case __DRI_API_OPENGL:
-	    mesa_api = API_OPENGL;
-	    break;
-    case __DRI_API_GLES:
-	    mesa_api = API_OPENGLES;
-	    break;
-    case __DRI_API_GLES2:
-	    mesa_api = API_OPENGLES2;
-	    break;
-    default:
-	    return NULL;
-    }
-
-    context = malloc(sizeof *context);
-    if (!context)
-	return NULL;
-
-    context->driScreenPriv = screen;
-    context->driDrawablePriv = NULL;
-    context->loaderPrivate = data;
-    
-    if (!(*screen->DriverAPI.CreateContext)(mesa_api, modes,
-					    context, shareCtx) ) {
-        free(context);
-        return NULL;
-    }
-
-    return context;
-}
-
-
-static __DRIcontext *
-dri2CreateNewContext(__DRIscreen *screen, const __DRIconfig *config,
-		      __DRIcontext *shared, void *data)
-{
-   return dri2CreateNewContextForAPI(screen, __DRI_API_OPENGL,
-				     config, shared, data);
-}
-
-static int
-driCopyContext(__DRIcontext *dest, __DRIcontext *src, unsigned long mask)
-{
-    return GL_FALSE;
-}
-
-/*@}*/
-
-
-/*****************************************************************/
-/** \name Screen handling functions                              */
-/*****************************************************************/
-/*@{*/
-
-/**
- * Destroy the per-screen private information.
- * 
- * \internal
- * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls
- * drmClose(), and finally frees \p screenPrivate.
- */
-static void driDestroyScreen(__DRIscreen *psp)
-{
-    if (psp) {
-	/* No interaction with the X-server is possible at this point.  This
-	 * routine is called after XCloseDisplay, so there is no protocol
-	 * stream open to the X-server anymore.
-	 */
-
-       _mesa_destroy_shader_compiler();
-
-	if (psp->DriverAPI.DestroyScreen)
-	    (*psp->DriverAPI.DestroyScreen)(psp);
-
-	if (!psp->dri2.enabled) {
-	   (void)drmUnmap((drmAddress)psp->pSAREA, SAREA_MAX);
-	   (void)drmUnmap((drmAddress)psp->pFB, psp->fbSize);
-	   (void)drmCloseOnce(psp->fd);
-	} else {
-	   driDestroyOptionCache(&psp->optionCache);
-	   driDestroyOptionInfo(&psp->optionInfo);
-	}
-
-	free(psp);
-    }
-}
-
-static void
-setupLoaderExtensions(__DRIscreen *psp,
-		      const __DRIextension **extensions)
-{
-    int i;
-
-    for (i = 0; extensions[i]; i++) {
-	if (strcmp(extensions[i]->name, __DRI_GET_DRAWABLE_INFO) == 0)
-	    psp->getDrawableInfo = (__DRIgetDrawableInfoExtension *) extensions[i];
-	if (strcmp(extensions[i]->name, __DRI_DAMAGE) == 0)
-	    psp->damage = (__DRIdamageExtension *) extensions[i];
-	if (strcmp(extensions[i]->name, __DRI_SYSTEM_TIME) == 0)
-	    psp->systemTime = (__DRIsystemTimeExtension *) extensions[i];
-	if (strcmp(extensions[i]->name, __DRI_DRI2_LOADER) == 0)
-	    psp->dri2.loader = (__DRIdri2LoaderExtension *) extensions[i];
-	if (strcmp(extensions[i]->name, __DRI_IMAGE_LOOKUP) == 0)
-	    psp->dri2.image = (__DRIimageLookupExtension *) extensions[i];
-	if (strcmp(extensions[i]->name, __DRI_USE_INVALIDATE) == 0)
-	    psp->dri2.useInvalidate = (__DRIuseInvalidateExtension *) extensions[i];
-    }
-}
-
-/**
- * This is the bootstrap function for the driver.  libGL supplies all of the
- * requisite information about the system, and the driver initializes itself.
- * This routine also fills in the linked list pointed to by \c driver_modes
- * with the \c struct gl_config that the driver can support for windows or
- * pbuffers.
- *
- * For legacy DRI.
- * 
- * \param scrn  Index of the screen
- * \param ddx_version Version of the 2D DDX.  This may not be meaningful for
- *                    all drivers.
- * \param dri_version Version of the "server-side" DRI.
- * \param drm_version Version of the kernel DRM.
- * \param frame_buffer Data describing the location and layout of the
- *                     framebuffer.
- * \param pSAREA       Pointer to the SAREA.
- * \param fd           Device handle for the DRM.
- * \param extensions   ??
- * \param driver_modes  Returns modes suppoted by the driver
- * \param loaderPrivate  ??
- * 
- * \note There is no need to check the minimum API version in this
- * function.  Since the name of this function is versioned, it is
- * impossible for a loader that is too old to even load this driver.
- */
-static __DRIscreen *
-driCreateNewScreen(int scrn,
-		   const __DRIversion *ddx_version,
-		   const __DRIversion *dri_version,
-		   const __DRIversion *drm_version,
-		   const __DRIframebuffer *frame_buffer,
-		   drmAddress pSAREA, int fd, 
-		   const __DRIextension **extensions,
-		   const __DRIconfig ***driver_modes,
-		   void *loaderPrivate)
-{
-    static const __DRIextension *emptyExtensionList[] = { NULL };
-    __DRIscreen *psp;
-
-    if (driDriverAPI.InitScreen == NULL)
-	return NULL;
-
-    psp = calloc(1, sizeof *psp);
-    if (!psp)
-	return NULL;
-
-    setupLoaderExtensions(psp, extensions);
-
-    /*
-    ** NOT_DONE: This is used by the X server to detect when the client
-    ** has died while holding the drawable lock.  The client sets the
-    ** drawable lock to this value.
-    */
-    psp->drawLockID = 1;
-
-    psp->drm_version = *drm_version;
-    psp->ddx_version = *ddx_version;
-    psp->dri_version = *dri_version;
-
-    psp->pSAREA = pSAREA;
-    psp->lock = (drmLock *) &psp->pSAREA->lock;
-
-    psp->pFB = frame_buffer->base;
-    psp->fbSize = frame_buffer->size;
-    psp->fbStride = frame_buffer->stride;
-    psp->fbWidth = frame_buffer->width;
-    psp->fbHeight = frame_buffer->height;
-    psp->devPrivSize = frame_buffer->dev_priv_size;
-    psp->pDevPriv = frame_buffer->dev_priv;
-    psp->fbBPP = psp->fbStride * 8 / frame_buffer->width;
-
-    psp->extensions = emptyExtensionList;
-    psp->fd = fd;
-    psp->myNum = scrn;
-    psp->dri2.enabled = GL_FALSE;
-
-    psp->DriverAPI = driDriverAPI;
-    psp->api_mask = (1 << __DRI_API_OPENGL);
-
-    *driver_modes = driDriverAPI.InitScreen(psp);
-    if (*driver_modes == NULL) {
-	free(psp);
-	return NULL;
-    }
-
-    return psp;
-}
-
-/**
- * DRI2
- */
-static __DRIscreen *
-dri2CreateNewScreen(int scrn, int fd,
-		    const __DRIextension **extensions,
-		    const __DRIconfig ***driver_configs, void *data)
-{
-    static const __DRIextension *emptyExtensionList[] = { NULL };
-    __DRIscreen *psp;
-    drmVersionPtr version;
-
-    if (driDriverAPI.InitScreen2 == NULL)
-        return NULL;
-
-    psp = calloc(1, sizeof(*psp));
-    if (!psp)
-	return NULL;
-
-    setupLoaderExtensions(psp, extensions);
-
-    version = drmGetVersion(fd);
-    if (version) {
-	psp->drm_version.major = version->version_major;
-	psp->drm_version.minor = version->version_minor;
-	psp->drm_version.patch = version->version_patchlevel;
-	drmFreeVersion(version);
-    }
-
-    psp->extensions = emptyExtensionList;
-    psp->fd = fd;
-    psp->myNum = scrn;
-    psp->dri2.enabled = GL_TRUE;
-
-    psp->DriverAPI = driDriverAPI;
-    psp->api_mask = (1 << __DRI_API_OPENGL);
-    *driver_configs = driDriverAPI.InitScreen2(psp);
-    if (*driver_configs == NULL) {
-	free(psp);
-	return NULL;
-    }
-
-    psp->DriverAPI = driDriverAPI;
-    psp->loaderPrivate = data;
-
-    driParseOptionInfo(&psp->optionInfo, __dri2ConfigOptions,
-		       __dri2NConfigOptions);
-    driParseConfigFiles(&psp->optionCache, &psp->optionInfo, psp->myNum,
-			"dri2");
-
-    return psp;
-}
-
-static const __DRIextension **driGetExtensions(__DRIscreen *psp)
-{
-    return psp->extensions;
-}
-
-/** Core interface */
-const __DRIcoreExtension driCoreExtension = {
-    { __DRI_CORE, __DRI_CORE_VERSION },
-    NULL,
-    driDestroyScreen,
-    driGetExtensions,
-    driGetConfigAttrib,
-    driIndexConfigAttrib,
-    NULL,
-    driDestroyDrawable,
-    driSwapBuffers,
-    NULL,
-    driCopyContext,
-    driDestroyContext,
-    driBindContext,
-    driUnbindContext
-};
-
-/** Legacy DRI interface */
-const __DRIlegacyExtension driLegacyExtension = {
-    { __DRI_LEGACY, __DRI_LEGACY_VERSION },
-    driCreateNewScreen,
-    driCreateNewDrawable,
-    driCreateNewContext,
-};
-
-/** DRI2 interface */
-const __DRIdri2Extension driDRI2Extension = {
-    { __DRI_DRI2, __DRI_DRI2_VERSION },
-    dri2CreateNewScreen,
-    dri2CreateNewDrawable,
-    dri2CreateNewContext,
-    dri2GetAPIMask,
-    dri2CreateNewContextForAPI
-};
-
-const __DRI2configQueryExtension dri2ConfigQueryExtension = {
-   { __DRI2_CONFIG_QUERY, __DRI2_CONFIG_QUERY_VERSION },
-   dri2ConfigQueryb,
-   dri2ConfigQueryi,
-   dri2ConfigQueryf,
-};
-
-/**
- * Calculate amount of swap interval used between GLX buffer swaps.
- * 
- * The usage value, on the range [0,max], is the fraction of total swap
- * interval time used between GLX buffer swaps is calculated.
- *
- *            \f$p = t_d / (i * t_r)\f$
- * 
- * Where \f$t_d\f$ is the time since the last GLX buffer swap, \f$i\f$ is the
- * swap interval (as set by \c glXSwapIntervalSGI), and \f$t_r\f$ time
- * required for a single vertical refresh period (as returned by \c
- * glXGetMscRateOML).
- * 
- * See the documentation for the GLX_MESA_swap_frame_usage extension for more
- * details.
- *
- * \param   dPriv  Pointer to the private drawable structure.
- * \return  If less than a single swap interval time period was required
- *          between GLX buffer swaps, a number greater than 0 and less than
- *          1.0 is returned.  If exactly one swap interval time period is
- *          required, 1.0 is returned, and if more than one is required then
- *          a number greater than 1.0 will be returned.
- *
- * \sa glXSwapIntervalSGI glXGetMscRateOML
- * 
- * \todo Instead of caching the \c glXGetMscRateOML function pointer, would it
- *       be possible to cache the sync rate?
- */
-float
-driCalculateSwapUsage( __DRIdrawable *dPriv, int64_t last_swap_ust,
-		       int64_t current_ust )
-{
-   int32_t   n;
-   int32_t   d;
-   int       interval;
-   float     usage = 1.0;
-   __DRIscreen *psp = dPriv->driScreenPriv;
-
-   if ( (*psp->systemTime->getMSCRate)(dPriv, &n, &d, dPriv->loaderPrivate) ) {
-      interval = (dPriv->swap_interval != 0) ? dPriv->swap_interval : 1;
-
-
-      /* We want to calculate
-       * (current_UST - last_swap_UST) / (interval * us_per_refresh).  We get
-       * current_UST by calling __glXGetUST.  last_swap_UST is stored in
-       * dPriv->swap_ust.  interval has already been calculated.
-       *
-       * The only tricky part is us_per_refresh.  us_per_refresh is
-       * 1000000 / MSC_rate.  We know the MSC_rate is n / d.  We can flip it
-       * around and say us_per_refresh = 1000000 * d / n.  Since this goes in
-       * the denominator of the final calculation, we calculate
-       * (interval * 1000000 * d) and move n into the numerator.
-       */
-
-      usage = (current_ust - last_swap_ust);
-      usage *= n;
-      usage /= (interval * d);
-      usage /= 1000000.0;
-   }
-   
-   return usage;
-}
-
-void
-dri2InvalidateDrawable(__DRIdrawable *drawable)
-{
-    drawable->dri2.stamp++;
-}
-
-/*@}*/
+/**
+ * \file dri_util.c
+ * DRI utility functions.
+ *
+ * This module acts as glue between GLX and the actual hardware driver.  A DRI
+ * driver doesn't really \e have to use any of this - it's optional.  But, some
+ * useful stuff is done here that otherwise would have to be duplicated in most
+ * drivers.
+ * 
+ * Basically, these utility functions take care of some of the dirty details of
+ * screen initialization, context creation, context binding, DRM setup, etc.
+ *
+ * These functions are compiled into each DRI driver so libGL.so knows nothing
+ * about them.
+ */
+
+
+#include <assert.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <stdio.h>
+
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void *)-1)
+#endif
+
+#include "main/imports.h"
+#define None 0
+
+#include "dri_util.h"
+#include "drm_sarea.h"
+#include "utils.h"
+#include "xmlpool.h"
+#include "../glsl/glsl_parser_extras.h"
+
+PUBLIC const char __dri2ConfigOptions[] =
+   DRI_CONF_BEGIN
+      DRI_CONF_SECTION_PERFORMANCE
+         DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_1)
+      DRI_CONF_SECTION_END
+   DRI_CONF_END;
+
+static const uint __dri2NConfigOptions = 1;
+
+#ifndef GLX_OML_sync_control
+typedef GLboolean ( * PFNGLXGETMSCRATEOMLPROC) (__DRIdrawable *drawable, int32_t *numerator, int32_t *denominator);
+#endif
+
+static void dri_get_drawable(__DRIdrawable *pdp);
+static void dri_put_drawable(__DRIdrawable *pdp);
+
+/**
+ * This is just a token extension used to signal that the driver
+ * supports setting a read drawable.
+ */
+const __DRIextension driReadDrawableExtension = {
+    __DRI_READ_DRAWABLE, __DRI_READ_DRAWABLE_VERSION
+};
+
+GLint
+driIntersectArea( drm_clip_rect_t rect1, drm_clip_rect_t rect2 )
+{
+   if (rect2.x1 > rect1.x1) rect1.x1 = rect2.x1;
+   if (rect2.x2 < rect1.x2) rect1.x2 = rect2.x2;
+   if (rect2.y1 > rect1.y1) rect1.y1 = rect2.y1;
+   if (rect2.y2 < rect1.y2) rect1.y2 = rect2.y2;
+
+   if (rect1.x1 > rect1.x2 || rect1.y1 > rect1.y2) return 0;
+
+   return (rect1.x2 - rect1.x1) * (rect1.y2 - rect1.y1);
+}
+
+/*****************************************************************/
+/** \name Context (un)binding functions                          */
+/*****************************************************************/
+/*@{*/
+
+/**
+ * Unbind context.
+ * 
+ * \param scrn the screen.
+ * \param gc context.
+ *
+ * \return \c GL_TRUE on success, or \c GL_FALSE on failure.
+ * 
+ * \internal
+ * This function calls __DriverAPIRec::UnbindContext, and then decrements
+ * __DRIdrawableRec::refcount which must be non-zero for a successful
+ * return.
+ * 
+ * While casting the opaque private pointers associated with the parameters
+ * into their respective real types it also assures they are not \c NULL. 
+ */
+static int driUnbindContext(__DRIcontext *pcp)
+{
+    __DRIscreen *psp;
+    __DRIdrawable *pdp;
+    __DRIdrawable *prp;
+
+    /*
+    ** Assume error checking is done properly in glXMakeCurrent before
+    ** calling driUnbindContext.
+    */
+
+    if (pcp == NULL)
+        return GL_FALSE;
+
+    psp = pcp->driScreenPriv;
+    pdp = pcp->driDrawablePriv;
+    prp = pcp->driReadablePriv;
+
+    /* already unbound */
+    if (!pdp && !prp)
+      return GL_TRUE;
+    /* Let driver unbind drawable from context */
+    (*psp->DriverAPI.UnbindContext)(pcp);
+
+    assert(pdp);
+    if (pdp->refcount == 0) {
+	/* ERROR!!! */
+	return GL_FALSE;
+    }
+
+    dri_put_drawable(pdp);
+
+    if (prp != pdp) {
+        if (prp->refcount == 0) {
+	    /* ERROR!!! */
+	    return GL_FALSE;
+	}
+
+    	dri_put_drawable(prp);
+    }
+
+
+    /* XXX this is disabled so that if we call SwapBuffers on an unbound
+     * window we can determine the last context bound to the window and
+     * use that context's lock. (BrianP, 2-Dec-2000)
+     */
+    pcp->driDrawablePriv = pcp->driReadablePriv = NULL;
+
+    return GL_TRUE;
+}
+
+/**
+ * This function takes both a read buffer and a draw buffer.  This is needed
+ * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
+ * function.
+ */
+static int driBindContext(__DRIcontext *pcp,
+			  __DRIdrawable *pdp,
+			  __DRIdrawable *prp)
+{
+    __DRIscreen *psp = NULL;
+
+    /*
+    ** Assume error checking is done properly in glXMakeCurrent before
+    ** calling driUnbindContext.
+    */
+
+    if (!pcp)
+	return GL_FALSE;
+
+    /* Bind the drawable to the context */
+    psp = pcp->driScreenPriv;
+    pcp->driDrawablePriv = pdp;
+    pcp->driReadablePriv = prp;
+    if (pdp) {
+	pdp->driContextPriv = pcp;
+	dri_get_drawable(pdp);
+    }
+    if (prp && pdp != prp) {
+	dri_get_drawable(prp);
+    }
+
+    /*
+    ** Now that we have a context associated with this drawable, we can
+    ** initialize the drawable information if has not been done before.
+    */
+
+    if (!psp->dri2.enabled) {
+	if (pdp && !pdp->pStamp) {
+	    DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
+	    __driUtilUpdateDrawableInfo(pdp);
+	    DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
+	}
+	if (prp && pdp != prp && !prp->pStamp) {
+	    DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
+	    __driUtilUpdateDrawableInfo(prp);
+	    DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
+        }
+    }
+
+    /* Call device-specific MakeCurrent */
+    return (*psp->DriverAPI.MakeCurrent)(pcp, pdp, prp);
+}
+
+/*@}*/
+
+
+/*****************************************************************/
+/** \name Drawable handling functions                            */
+/*****************************************************************/
+/*@{*/
+
+/**
+ * Update private drawable information.
+ *
+ * \param pdp pointer to the private drawable information to update.
+ * 
+ * This function basically updates the __DRIdrawable struct's
+ * cliprect information by calling \c __DRIinterfaceMethods::getDrawableInfo.
+ * This is usually called by the DRI_VALIDATE_DRAWABLE_INFO macro which
+ * compares the __DRIdrwablePrivate pStamp and lastStamp values.  If
+ * the values are different that means we have to update the clipping
+ * info.
+ */
+void
+__driUtilUpdateDrawableInfo(__DRIdrawable *pdp)
+{
+    __DRIscreen *psp = pdp->driScreenPriv;
+    __DRIcontext *pcp = pdp->driContextPriv;
+    
+    if (!pcp 
+	|| ((pdp != pcp->driDrawablePriv) && (pdp != pcp->driReadablePriv))) {
+	/* ERROR!!! 
+	 * ...but we must ignore it. There can be many contexts bound to a
+	 * drawable.
+	 */
+    }
+
+    if (pdp->pClipRects) {
+	free(pdp->pClipRects); 
+	pdp->pClipRects = NULL;
+    }
+
+    if (pdp->pBackClipRects) {
+	free(pdp->pBackClipRects); 
+	pdp->pBackClipRects = NULL;
+    }
+
+    DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
+
+    if (! (*psp->getDrawableInfo->getDrawableInfo)(pdp,
+			  &pdp->index, &pdp->lastStamp,
+			  &pdp->x, &pdp->y, &pdp->w, &pdp->h,
+			  &pdp->numClipRects, &pdp->pClipRects,
+			  &pdp->backX,
+			  &pdp->backY,
+			  &pdp->numBackClipRects,
+			  &pdp->pBackClipRects,
+			  pdp->loaderPrivate)) {
+	/* Error -- eg the window may have been destroyed.  Keep going
+	 * with no cliprects.
+	 */
+        pdp->pStamp = &pdp->lastStamp; /* prevent endless loop */
+	pdp->numClipRects = 0;
+	pdp->pClipRects = NULL;
+	pdp->numBackClipRects = 0;
+	pdp->pBackClipRects = NULL;
+    }
+    else
+       pdp->pStamp = &(psp->pSAREA->drawableTable[pdp->index].stamp);
+
+    DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
+}
+
+/*@}*/
+
+/*****************************************************************/
+/** \name GLX callbacks                                          */
+/*****************************************************************/
+/*@{*/
+
+static void driReportDamage(__DRIdrawable *pdp,
+			    struct drm_clip_rect *pClipRects, int numClipRects)
+{
+    __DRIscreen *psp = pdp->driScreenPriv;
+
+    /* Check that we actually have the new damage report method */
+    if (psp->damage) {
+	/* Report the damage.  Currently, all our drivers draw
+	 * directly to the front buffer, so we report the damage there
+	 * rather than to the backing storein (if any).
+	 */
+	(*psp->damage->reportDamage)(pdp,
+				     pdp->x, pdp->y,
+				     pClipRects, numClipRects,
+				     GL_TRUE, pdp->loaderPrivate);
+    }
+}
+
+
+/**
+ * Swap buffers.
+ *
+ * \param drawablePrivate opaque pointer to the per-drawable private info.
+ * 
+ * \internal
+ * This function calls __DRIdrawable::swapBuffers.
+ * 
+ * Is called directly from glXSwapBuffers().
+ */
+static void driSwapBuffers(__DRIdrawable *dPriv)
+{
+    __DRIscreen *psp = dPriv->driScreenPriv;
+    drm_clip_rect_t *rects;
+    int i;
+
+    psp->DriverAPI.SwapBuffers(dPriv);
+
+    if (!dPriv->numClipRects)
+        return;
+
+    rects = malloc(sizeof(*rects) * dPriv->numClipRects);
+
+    if (!rects)
+        return;
+
+    for (i = 0; i < dPriv->numClipRects; i++) {
+        rects[i].x1 = dPriv->pClipRects[i].x1 - dPriv->x;
+        rects[i].y1 = dPriv->pClipRects[i].y1 - dPriv->y;
+        rects[i].x2 = dPriv->pClipRects[i].x2 - dPriv->x;
+        rects[i].y2 = dPriv->pClipRects[i].y2 - dPriv->y;
+    }
+
+    driReportDamage(dPriv, rects, dPriv->numClipRects);
+    free(rects);
+}
+
+static int driDrawableGetMSC( __DRIscreen *sPriv, __DRIdrawable *dPriv,
+			      int64_t *msc )
+{
+    return sPriv->DriverAPI.GetDrawableMSC(sPriv, dPriv, msc);
+}
+
+
+static int driWaitForMSC(__DRIdrawable *dPriv, int64_t target_msc,
+			 int64_t divisor, int64_t remainder,
+			 int64_t * msc, int64_t * sbc)
+{
+    __DRIswapInfo  sInfo;
+    int  status;
+
+    status = dPriv->driScreenPriv->DriverAPI.WaitForMSC( dPriv, target_msc,
+                                                         divisor, remainder,
+                                                         msc );
+
+    /* GetSwapInfo() may not be provided by the driver if GLX_SGI_video_sync
+     * is supported but GLX_OML_sync_control is not.  Therefore, don't return
+     * an error value if GetSwapInfo() is not implemented.
+    */
+    if ( status == 0
+         && dPriv->driScreenPriv->DriverAPI.GetSwapInfo ) {
+        status = dPriv->driScreenPriv->DriverAPI.GetSwapInfo( dPriv, & sInfo );
+        *sbc = sInfo.swap_count;
+    }
+
+    return status;
+}
+
+
+const __DRImediaStreamCounterExtension driMediaStreamCounterExtension = {
+    { __DRI_MEDIA_STREAM_COUNTER, __DRI_MEDIA_STREAM_COUNTER_VERSION },
+    driWaitForMSC,
+    driDrawableGetMSC,
+};
+
+
+static void driCopySubBuffer(__DRIdrawable *dPriv,
+			      int x, int y, int w, int h)
+{
+    drm_clip_rect_t rect;
+
+    rect.x1 = x;
+    rect.y1 = dPriv->h - y - h;
+    rect.x2 = x + w;
+    rect.y2 = rect.y1 + h;
+    driReportDamage(dPriv, &rect, 1);
+
+    dPriv->driScreenPriv->DriverAPI.CopySubBuffer(dPriv, x, y, w, h);
+}
+
+const __DRIcopySubBufferExtension driCopySubBufferExtension = {
+    { __DRI_COPY_SUB_BUFFER, __DRI_COPY_SUB_BUFFER_VERSION },
+    driCopySubBuffer
+};
+
+static void driSetSwapInterval(__DRIdrawable *dPriv, unsigned int interval)
+{
+    dPriv->swap_interval = interval;
+}
+
+static unsigned int driGetSwapInterval(__DRIdrawable *dPriv)
+{
+    return dPriv->swap_interval;
+}
+
+const __DRIswapControlExtension driSwapControlExtension = {
+    { __DRI_SWAP_CONTROL, __DRI_SWAP_CONTROL_VERSION },
+    driSetSwapInterval,
+    driGetSwapInterval
+};
+
+
+/**
+ * This is called via __DRIscreenRec's createNewDrawable pointer.
+ */
+static __DRIdrawable *
+driCreateNewDrawable(__DRIscreen *psp, const __DRIconfig *config,
+		     drm_drawable_t hwDrawable, int renderType,
+		     const int *attrs, void *data)
+{
+    __DRIdrawable *pdp;
+
+    /* Since pbuffers are not yet supported, no drawable attributes are
+     * supported either.
+     */
+    (void) attrs;
+
+    pdp = malloc(sizeof *pdp);
+    if (!pdp) {
+	return NULL;
+    }
+
+    pdp->driContextPriv = NULL;
+    pdp->loaderPrivate = data;
+    pdp->hHWDrawable = hwDrawable;
+    pdp->refcount = 1;
+    pdp->pStamp = NULL;
+    pdp->lastStamp = 0;
+    pdp->index = 0;
+    pdp->x = 0;
+    pdp->y = 0;
+    pdp->w = 0;
+    pdp->h = 0;
+    pdp->numClipRects = 0;
+    pdp->numBackClipRects = 0;
+    pdp->pClipRects = NULL;
+    pdp->pBackClipRects = NULL;
+    pdp->vblSeq = 0;
+    pdp->vblFlags = 0;
+
+    pdp->driScreenPriv = psp;
+
+    if (!(*psp->DriverAPI.CreateBuffer)(psp, pdp, &config->modes, 0)) {
+       free(pdp);
+       return NULL;
+    }
+
+    pdp->msc_base = 0;
+
+    /* This special default value is replaced with the configured
+     * default value when the drawable is first bound to a direct
+     * rendering context. 
+     */
+    pdp->swap_interval = (unsigned)-1;
+
+    return pdp;
+}
+
+
+static __DRIdrawable *
+dri2CreateNewDrawable(__DRIscreen *screen,
+		      const __DRIconfig *config,
+		      void *loaderPrivate)
+{
+    __DRIdrawable *pdraw;
+
+    pdraw = driCreateNewDrawable(screen, config, 0, 0, NULL, loaderPrivate);
+    if (!pdraw)
+    	return NULL;
+
+    pdraw->pClipRects = &pdraw->dri2.clipRect;
+    pdraw->pBackClipRects = &pdraw->dri2.clipRect;
+
+    pdraw->pStamp = &pdraw->dri2.stamp;
+    *pdraw->pStamp = pdraw->lastStamp + 1;
+
+    return pdraw;
+}
+
+static __DRIbuffer *
+dri2AllocateBuffer(__DRIscreen *screen,
+		   unsigned int attachment, unsigned int format,
+		   int width, int height)
+{
+    return (*screen->DriverAPI.AllocateBuffer)(screen, attachment, format,
+					       width, height);
+}
+
+static void
+dri2ReleaseBuffer(__DRIscreen *screen, __DRIbuffer *buffer)
+{
+   (*screen->DriverAPI.ReleaseBuffer)(screen, buffer);
+}
+
+
+static int
+dri2ConfigQueryb(__DRIscreen *screen, const char *var, GLboolean *val)
+{
+   if (!driCheckOption(&screen->optionCache, var, DRI_BOOL))
+      return -1;
+
+   *val = driQueryOptionb(&screen->optionCache, var);
+
+   return 0;
+}
+
+static int
+dri2ConfigQueryi(__DRIscreen *screen, const char *var, GLint *val)
+{
+   if (!driCheckOption(&screen->optionCache, var, DRI_INT) &&
+       !driCheckOption(&screen->optionCache, var, DRI_ENUM))
+      return -1;
+
+    *val = driQueryOptioni(&screen->optionCache, var);
+
+    return 0;
+}
+
+static int
+dri2ConfigQueryf(__DRIscreen *screen, const char *var, GLfloat *val)
+{
+   if (!driCheckOption(&screen->optionCache, var, DRI_FLOAT))
+      return -1;
+
+    *val = driQueryOptionf(&screen->optionCache, var);
+
+    return 0;
+}
+
+
+static void dri_get_drawable(__DRIdrawable *pdp)
+{
+    pdp->refcount++;
+}
+	
+static void dri_put_drawable(__DRIdrawable *pdp)
+{
+    __DRIscreen *psp;
+
+    if (pdp) {
+	pdp->refcount--;
+	if (pdp->refcount)
+	    return;
+
+	psp = pdp->driScreenPriv;
+        (*psp->DriverAPI.DestroyBuffer)(pdp);
+	if (pdp->pClipRects && pdp->pClipRects != &pdp->dri2.clipRect) {
+	    free(pdp->pClipRects);
+	    pdp->pClipRects = NULL;
+	}
+	if (pdp->pBackClipRects && pdp->pClipRects != &pdp->dri2.clipRect) {
+	    free(pdp->pBackClipRects);
+	    pdp->pBackClipRects = NULL;
+	}
+	free(pdp);
+    }
+}
+
+static void
+driDestroyDrawable(__DRIdrawable *pdp)
+{
+    dri_put_drawable(pdp);
+}
+
+/*@}*/
+
+
+/*****************************************************************/
+/** \name Context handling functions                             */
+/*****************************************************************/
+/*@{*/
+
+/**
+ * Destroy the per-context private information.
+ * 
+ * \internal
+ * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls
+ * drmDestroyContext(), and finally frees \p contextPrivate.
+ */
+static void
+driDestroyContext(__DRIcontext *pcp)
+{
+    if (pcp) {
+	(*pcp->driScreenPriv->DriverAPI.DestroyContext)(pcp);
+	free(pcp);
+    }
+}
+
+
+/**
+ * Create the per-drawable private driver information.
+ * 
+ * \param render_type   Type of rendering target.  \c GLX_RGBA is the only
+ *                      type likely to ever be supported for direct-rendering.
+ * \param shared        Context with which to share textures, etc. or NULL
+ *
+ * \returns An opaque pointer to the per-context private information on
+ *          success, or \c NULL on failure.
+ * 
+ * \internal
+ * This function allocates and fills a __DRIcontextRec structure.  It
+ * performs some device independent initialization and passes all the
+ * relevent information to __DriverAPIRec::CreateContext to create the
+ * context.
+ *
+ */
+static __DRIcontext *
+driCreateNewContext(__DRIscreen *psp, const __DRIconfig *config,
+		    int render_type, __DRIcontext *shared, 
+		    drm_context_t hwContext, void *data)
+{
+    __DRIcontext *pcp;
+    void * const shareCtx = (shared != NULL) ? shared->driverPrivate : NULL;
+
+    pcp = malloc(sizeof *pcp);
+    if (!pcp)
+	return NULL;
+
+    pcp->driScreenPriv = psp;
+    pcp->driDrawablePriv = NULL;
+    pcp->loaderPrivate = data;
+    
+    pcp->dri2.draw_stamp = 0;
+    pcp->dri2.read_stamp = 0;
+
+    pcp->hHWContext = hwContext;
+
+    if ( !(*psp->DriverAPI.CreateContext)(API_OPENGL,
+					  &config->modes, pcp, shareCtx) ) {
+        free(pcp);
+        return NULL;
+    }
+
+    return pcp;
+}
+
+static unsigned int
+dri2GetAPIMask(__DRIscreen *screen)
+{
+    return screen->api_mask;
+}
+
+static __DRIcontext *
+dri2CreateNewContextForAPI(__DRIscreen *screen, int api,
+			   const __DRIconfig *config,
+			   __DRIcontext *shared, void *data)
+{
+    __DRIcontext *context;
+    const struct gl_config *modes = (config != NULL) ? &config->modes : NULL;
+    void *shareCtx = (shared != NULL) ? shared->driverPrivate : NULL;
+    gl_api mesa_api;
+
+    if (!(screen->api_mask & (1 << api)))
+	return NULL;
+
+    switch (api) {
+    case __DRI_API_OPENGL:
+	    mesa_api = API_OPENGL;
+	    break;
+    case __DRI_API_GLES:
+	    mesa_api = API_OPENGLES;
+	    break;
+    case __DRI_API_GLES2:
+	    mesa_api = API_OPENGLES2;
+	    break;
+    default:
+	    return NULL;
+    }
+
+    context = malloc(sizeof *context);
+    if (!context)
+	return NULL;
+
+    context->driScreenPriv = screen;
+    context->driDrawablePriv = NULL;
+    context->loaderPrivate = data;
+    
+    if (!(*screen->DriverAPI.CreateContext)(mesa_api, modes,
+					    context, shareCtx) ) {
+        free(context);
+        return NULL;
+    }
+
+    return context;
+}
+
+
+static __DRIcontext *
+dri2CreateNewContext(__DRIscreen *screen, const __DRIconfig *config,
+		      __DRIcontext *shared, void *data)
+{
+   return dri2CreateNewContextForAPI(screen, __DRI_API_OPENGL,
+				     config, shared, data);
+}
+
+static int
+driCopyContext(__DRIcontext *dest, __DRIcontext *src, unsigned long mask)
+{
+    return GL_FALSE;
+}
+
+/*@}*/
+
+
+/*****************************************************************/
+/** \name Screen handling functions                              */
+/*****************************************************************/
+/*@{*/
+
+/**
+ * Destroy the per-screen private information.
+ * 
+ * \internal
+ * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls
+ * drmClose(), and finally frees \p screenPrivate.
+ */
+static void driDestroyScreen(__DRIscreen *psp)
+{
+    if (psp) {
+	/* No interaction with the X-server is possible at this point.  This
+	 * routine is called after XCloseDisplay, so there is no protocol
+	 * stream open to the X-server anymore.
+	 */
+
+       _mesa_destroy_shader_compiler();
+
+	if (psp->DriverAPI.DestroyScreen)
+	    (*psp->DriverAPI.DestroyScreen)(psp);
+
+	if (!psp->dri2.enabled) {
+	   (void)drmUnmap((drmAddress)psp->pSAREA, SAREA_MAX);
+	   (void)drmUnmap((drmAddress)psp->pFB, psp->fbSize);
+	   (void)drmCloseOnce(psp->fd);
+	} else {
+	   driDestroyOptionCache(&psp->optionCache);
+	   driDestroyOptionInfo(&psp->optionInfo);
+	}
+
+	free(psp);
+    }
+}
+
+static void
+setupLoaderExtensions(__DRIscreen *psp,
+		      const __DRIextension **extensions)
+{
+    int i;
+
+    for (i = 0; extensions[i]; i++) {
+	if (strcmp(extensions[i]->name, __DRI_GET_DRAWABLE_INFO) == 0)
+	    psp->getDrawableInfo = (__DRIgetDrawableInfoExtension *) extensions[i];
+	if (strcmp(extensions[i]->name, __DRI_DAMAGE) == 0)
+	    psp->damage = (__DRIdamageExtension *) extensions[i];
+	if (strcmp(extensions[i]->name, __DRI_SYSTEM_TIME) == 0)
+	    psp->systemTime = (__DRIsystemTimeExtension *) extensions[i];
+	if (strcmp(extensions[i]->name, __DRI_DRI2_LOADER) == 0)
+	    psp->dri2.loader = (__DRIdri2LoaderExtension *) extensions[i];
+	if (strcmp(extensions[i]->name, __DRI_IMAGE_LOOKUP) == 0)
+	    psp->dri2.image = (__DRIimageLookupExtension *) extensions[i];
+	if (strcmp(extensions[i]->name, __DRI_USE_INVALIDATE) == 0)
+	    psp->dri2.useInvalidate = (__DRIuseInvalidateExtension *) extensions[i];
+    }
+}
+
+/**
+ * This is the bootstrap function for the driver.  libGL supplies all of the
+ * requisite information about the system, and the driver initializes itself.
+ * This routine also fills in the linked list pointed to by \c driver_modes
+ * with the \c struct gl_config that the driver can support for windows or
+ * pbuffers.
+ *
+ * For legacy DRI.
+ * 
+ * \param scrn  Index of the screen
+ * \param ddx_version Version of the 2D DDX.  This may not be meaningful for
+ *                    all drivers.
+ * \param dri_version Version of the "server-side" DRI.
+ * \param drm_version Version of the kernel DRM.
+ * \param frame_buffer Data describing the location and layout of the
+ *                     framebuffer.
+ * \param pSAREA       Pointer to the SAREA.
+ * \param fd           Device handle for the DRM.
+ * \param extensions   ??
+ * \param driver_modes  Returns modes suppoted by the driver
+ * \param loaderPrivate  ??
+ * 
+ * \note There is no need to check the minimum API version in this
+ * function.  Since the name of this function is versioned, it is
+ * impossible for a loader that is too old to even load this driver.
+ */
+static __DRIscreen *
+driCreateNewScreen(int scrn,
+		   const __DRIversion *ddx_version,
+		   const __DRIversion *dri_version,
+		   const __DRIversion *drm_version,
+		   const __DRIframebuffer *frame_buffer,
+		   drmAddress pSAREA, int fd, 
+		   const __DRIextension **extensions,
+		   const __DRIconfig ***driver_modes,
+		   void *loaderPrivate)
+{
+    static const __DRIextension *emptyExtensionList[] = { NULL };
+    __DRIscreen *psp;
+
+    if (driDriverAPI.InitScreen == NULL)
+	return NULL;
+
+    psp = calloc(1, sizeof *psp);
+    if (!psp)
+	return NULL;
+
+    setupLoaderExtensions(psp, extensions);
+
+    /*
+    ** NOT_DONE: This is used by the X server to detect when the client
+    ** has died while holding the drawable lock.  The client sets the
+    ** drawable lock to this value.
+    */
+    psp->drawLockID = 1;
+
+    psp->drm_version = *drm_version;
+    psp->ddx_version = *ddx_version;
+    psp->dri_version = *dri_version;
+
+    psp->pSAREA = pSAREA;
+    psp->lock = (drmLock *) &psp->pSAREA->lock;
+
+    psp->pFB = frame_buffer->base;
+    psp->fbSize = frame_buffer->size;
+    psp->fbStride = frame_buffer->stride;
+    psp->fbWidth = frame_buffer->width;
+    psp->fbHeight = frame_buffer->height;
+    psp->devPrivSize = frame_buffer->dev_priv_size;
+    psp->pDevPriv = frame_buffer->dev_priv;
+    psp->fbBPP = psp->fbStride * 8 / frame_buffer->width;
+
+    psp->extensions = emptyExtensionList;
+    psp->fd = fd;
+    psp->myNum = scrn;
+    psp->dri2.enabled = GL_FALSE;
+
+    psp->DriverAPI = driDriverAPI;
+    psp->api_mask = (1 << __DRI_API_OPENGL);
+
+    *driver_modes = driDriverAPI.InitScreen(psp);
+    if (*driver_modes == NULL) {
+	free(psp);
+	return NULL;
+    }
+
+    return psp;
+}
+
+/**
+ * DRI2
+ */
+static __DRIscreen *
+dri2CreateNewScreen(int scrn, int fd,
+		    const __DRIextension **extensions,
+		    const __DRIconfig ***driver_configs, void *data)
+{
+    static const __DRIextension *emptyExtensionList[] = { NULL };
+    __DRIscreen *psp;
+    drmVersionPtr version;
+
+    if (driDriverAPI.InitScreen2 == NULL)
+        return NULL;
+
+    psp = calloc(1, sizeof(*psp));
+    if (!psp)
+	return NULL;
+
+    setupLoaderExtensions(psp, extensions);
+
+    version = drmGetVersion(fd);
+    if (version) {
+	psp->drm_version.major = version->version_major;
+	psp->drm_version.minor = version->version_minor;
+	psp->drm_version.patch = version->version_patchlevel;
+	drmFreeVersion(version);
+    }
+
+    psp->extensions = emptyExtensionList;
+    psp->fd = fd;
+    psp->myNum = scrn;
+    psp->dri2.enabled = GL_TRUE;
+
+    psp->DriverAPI = driDriverAPI;
+    psp->api_mask = (1 << __DRI_API_OPENGL);
+    *driver_configs = driDriverAPI.InitScreen2(psp);
+    if (*driver_configs == NULL) {
+	free(psp);
+	return NULL;
+    }
+
+    psp->DriverAPI = driDriverAPI;
+    psp->loaderPrivate = data;
+
+    driParseOptionInfo(&psp->optionInfo, __dri2ConfigOptions,
+		       __dri2NConfigOptions);
+    driParseConfigFiles(&psp->optionCache, &psp->optionInfo, psp->myNum,
+			"dri2");
+
+    return psp;
+}
+
+static const __DRIextension **driGetExtensions(__DRIscreen *psp)
+{
+    return psp->extensions;
+}
+
+/** Core interface */
+const __DRIcoreExtension driCoreExtension = {
+    { __DRI_CORE, __DRI_CORE_VERSION },
+    NULL,
+    driDestroyScreen,
+    driGetExtensions,
+    driGetConfigAttrib,
+    driIndexConfigAttrib,
+    NULL,
+    driDestroyDrawable,
+    driSwapBuffers,
+    NULL,
+    driCopyContext,
+    driDestroyContext,
+    driBindContext,
+    driUnbindContext
+};
+
+/** Legacy DRI interface */
+const __DRIlegacyExtension driLegacyExtension = {
+    { __DRI_LEGACY, __DRI_LEGACY_VERSION },
+    driCreateNewScreen,
+    driCreateNewDrawable,
+    driCreateNewContext,
+};
+
+/** DRI2 interface */
+const __DRIdri2Extension driDRI2Extension = {
+    { __DRI_DRI2, __DRI_DRI2_VERSION },
+    dri2CreateNewScreen,
+    dri2CreateNewDrawable,
+    dri2CreateNewContext,
+    dri2GetAPIMask,
+    dri2CreateNewContextForAPI,
+    dri2AllocateBuffer,
+    dri2ReleaseBuffer
+};
+
+const __DRI2configQueryExtension dri2ConfigQueryExtension = {
+   { __DRI2_CONFIG_QUERY, __DRI2_CONFIG_QUERY_VERSION },
+   dri2ConfigQueryb,
+   dri2ConfigQueryi,
+   dri2ConfigQueryf,
+};
+
+/**
+ * Calculate amount of swap interval used between GLX buffer swaps.
+ * 
+ * The usage value, on the range [0,max], is the fraction of total swap
+ * interval time used between GLX buffer swaps is calculated.
+ *
+ *            \f$p = t_d / (i * t_r)\f$
+ * 
+ * Where \f$t_d\f$ is the time since the last GLX buffer swap, \f$i\f$ is the
+ * swap interval (as set by \c glXSwapIntervalSGI), and \f$t_r\f$ time
+ * required for a single vertical refresh period (as returned by \c
+ * glXGetMscRateOML).
+ * 
+ * See the documentation for the GLX_MESA_swap_frame_usage extension for more
+ * details.
+ *
+ * \param   dPriv  Pointer to the private drawable structure.
+ * \return  If less than a single swap interval time period was required
+ *          between GLX buffer swaps, a number greater than 0 and less than
+ *          1.0 is returned.  If exactly one swap interval time period is
+ *          required, 1.0 is returned, and if more than one is required then
+ *          a number greater than 1.0 will be returned.
+ *
+ * \sa glXSwapIntervalSGI glXGetMscRateOML
+ * 
+ * \todo Instead of caching the \c glXGetMscRateOML function pointer, would it
+ *       be possible to cache the sync rate?
+ */
+float
+driCalculateSwapUsage( __DRIdrawable *dPriv, int64_t last_swap_ust,
+		       int64_t current_ust )
+{
+   int32_t   n;
+   int32_t   d;
+   int       interval;
+   float     usage = 1.0;
+   __DRIscreen *psp = dPriv->driScreenPriv;
+
+   if ( (*psp->systemTime->getMSCRate)(dPriv, &n, &d, dPriv->loaderPrivate) ) {
+      interval = (dPriv->swap_interval != 0) ? dPriv->swap_interval : 1;
+
+
+      /* We want to calculate
+       * (current_UST - last_swap_UST) / (interval * us_per_refresh).  We get
+       * current_UST by calling __glXGetUST.  last_swap_UST is stored in
+       * dPriv->swap_ust.  interval has already been calculated.
+       *
+       * The only tricky part is us_per_refresh.  us_per_refresh is
+       * 1000000 / MSC_rate.  We know the MSC_rate is n / d.  We can flip it
+       * around and say us_per_refresh = 1000000 * d / n.  Since this goes in
+       * the denominator of the final calculation, we calculate
+       * (interval * 1000000 * d) and move n into the numerator.
+       */
+
+      usage = (current_ust - last_swap_ust);
+      usage *= n;
+      usage /= (interval * d);
+      usage /= 1000000.0;
+   }
+   
+   return usage;
+}
+
+void
+dri2InvalidateDrawable(__DRIdrawable *drawable)
+{
+    drawable->dri2.stamp++;
+}
+
+/*@}*/
diff --git a/mesalib/src/mesa/drivers/dri/common/dri_util.h b/mesalib/src/mesa/drivers/dri/common/dri_util.h
index b6f04993e..3d3d5c9cd 100644
--- a/mesalib/src/mesa/drivers/dri/common/dri_util.h
+++ b/mesalib/src/mesa/drivers/dri/common/dri_util.h
@@ -1,557 +1,563 @@
-/*
- * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
- * 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"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file dri_util.h
- * DRI utility functions definitions.
- *
- * This module acts as glue between GLX and the actual hardware driver.  A DRI
- * driver doesn't really \e have to use any of this - it's optional.  But, some
- * useful stuff is done here that otherwise would have to be duplicated in most
- * drivers.
- * 
- * Basically, these utility functions take care of some of the dirty details of
- * screen initialization, context creation, context binding, DRM setup, etc.
- *
- * These functions are compiled into each DRI driver so libGL.so knows nothing
- * about them.
- *
- * \sa dri_util.c.
- * 
- * \author Kevin E. Martin <kevin@precisioninsight.com>
- * \author Brian Paul <brian@precisioninsight.com>
- */
-
-#ifndef _DRI_UTIL_H_
-#define _DRI_UTIL_H_
-
-#include <GL/gl.h>
-#include <drm.h>
-#include <drm_sarea.h>
-#include <xf86drm.h>
-#include "xmlconfig.h"
-#include "main/glheader.h"
-#include "main/mtypes.h"
-#include "GL/internal/dri_interface.h"
-
-#define GLX_BAD_CONTEXT                    5
-
-typedef struct __DRIswapInfoRec        __DRIswapInfo;
-
-/**
- * Extensions.
- */
-extern const __DRIlegacyExtension driLegacyExtension;
-extern const __DRIcoreExtension driCoreExtension;
-extern const __DRIdri2Extension driDRI2Extension;
-extern const __DRIextension driReadDrawableExtension;
-extern const __DRIcopySubBufferExtension driCopySubBufferExtension;
-extern const __DRIswapControlExtension driSwapControlExtension;
-extern const __DRImediaStreamCounterExtension driMediaStreamCounterExtension;
-extern const __DRI2configQueryExtension dri2ConfigQueryExtension;
-
-/**
- * Used by DRI_VALIDATE_DRAWABLE_INFO
- */
-#define DRI_VALIDATE_DRAWABLE_INFO_ONCE(pDrawPriv)              \
-    do {                                                        \
-	if (*(pDrawPriv->pStamp) != pDrawPriv->lastStamp) {     \
-	    __driUtilUpdateDrawableInfo(pDrawPriv);             \
-	}                                                       \
-    } while (0)
-
-
-/**
- * Utility macro to validate the drawable information.
- *
- * See __DRIdrawable::pStamp and __DRIdrawable::lastStamp.
- */
-#define DRI_VALIDATE_DRAWABLE_INFO(psp, pdp)                            \
-do {                                                                    \
-    while (*(pdp->pStamp) != pdp->lastStamp) {                          \
-        register unsigned int hwContext = psp->pSAREA->lock.lock &      \
-		     ~(DRM_LOCK_HELD | DRM_LOCK_CONT);                  \
-	DRM_UNLOCK(psp->fd, &psp->pSAREA->lock, hwContext);             \
-                                                                        \
-	DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);     \
-	DRI_VALIDATE_DRAWABLE_INFO_ONCE(pdp);                           \
-	DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);   \
-                                                                        \
-	DRM_LIGHT_LOCK(psp->fd, &psp->pSAREA->lock, hwContext);         \
-    }                                                                   \
-} while (0)
-
-/**
- * Same as above, but for two drawables simultaneously.
- *
- */
-
-#define DRI_VALIDATE_TWO_DRAWABLES_INFO(psp, pdp, prp)			\
-do {								\
-    while (*((pdp)->pStamp) != (pdp)->lastStamp ||			\
-	   *((prp)->pStamp) != (prp)->lastStamp) {			\
-        register unsigned int hwContext = (psp)->pSAREA->lock.lock &	\
-	    ~(DRM_LOCK_HELD | DRM_LOCK_CONT);				\
-	DRM_UNLOCK((psp)->fd, &(psp)->pSAREA->lock, hwContext);		\
-									\
-	DRM_SPINLOCK(&(psp)->pSAREA->drawable_lock, (psp)->drawLockID);	\
-	DRI_VALIDATE_DRAWABLE_INFO_ONCE(pdp);                           \
-	DRI_VALIDATE_DRAWABLE_INFO_ONCE(prp);				\
-	DRM_SPINUNLOCK(&(psp)->pSAREA->drawable_lock, (psp)->drawLockID); \
-									\
-	DRM_LIGHT_LOCK((psp)->fd, &(psp)->pSAREA->lock, hwContext);	\
-    }                                                                   \
-} while (0)
-
-
-/**
- * Driver callback functions.
- *
- * Each DRI driver must have one of these structures with all the pointers set
- * to appropriate functions within the driver.
- * 
- * When glXCreateContext() is called, for example, it'll call a helper function
- * dri_util.c which in turn will jump through the \a CreateContext pointer in
- * this structure.
- */
-struct __DriverAPIRec {
-    const __DRIconfig **(*InitScreen) (__DRIscreen * priv);
-
-    /**
-     * Screen destruction callback
-     */
-    void (*DestroyScreen)(__DRIscreen *driScrnPriv);
-
-    /**
-     * Context creation callback
-     */	    	    
-    GLboolean (*CreateContext)(gl_api api,
-			       const struct gl_config *glVis,
-			       __DRIcontext *driContextPriv,
-                               void *sharedContextPrivate);
-
-    /**
-     * Context destruction callback
-     */
-    void (*DestroyContext)(__DRIcontext *driContextPriv);
-
-    /**
-     * Buffer (drawable) creation callback
-     */
-    GLboolean (*CreateBuffer)(__DRIscreen *driScrnPriv,
-                              __DRIdrawable *driDrawPriv,
-                              const struct gl_config *glVis,
-                              GLboolean pixmapBuffer);
-    
-    /**
-     * Buffer (drawable) destruction callback
-     */
-    void (*DestroyBuffer)(__DRIdrawable *driDrawPriv);
-
-    /**
-     * Buffer swapping callback 
-     */
-    void (*SwapBuffers)(__DRIdrawable *driDrawPriv);
-
-    /**
-     * Context activation callback
-     */
-    GLboolean (*MakeCurrent)(__DRIcontext *driContextPriv,
-                             __DRIdrawable *driDrawPriv,
-                             __DRIdrawable *driReadPriv);
-
-    /**
-     * Context unbinding callback
-     */
-    GLboolean (*UnbindContext)(__DRIcontext *driContextPriv);
-  
-    /**
-     * Retrieves statistics about buffer swap operations.  Required if
-     * GLX_OML_sync_control or GLX_MESA_swap_frame_usage is supported.
-     */
-    int (*GetSwapInfo)( __DRIdrawable *dPriv, __DRIswapInfo * sInfo );
-
-
-    /**
-     * These are required if GLX_OML_sync_control is supported.
-     */
-    /*@{*/
-    int (*WaitForMSC)( __DRIdrawable *priv, int64_t target_msc, 
-		       int64_t divisor, int64_t remainder,
-		       int64_t * msc );
-    int (*WaitForSBC)( __DRIdrawable *priv, int64_t target_sbc,
-		       int64_t * msc, int64_t * sbc );
-
-    int64_t (*SwapBuffersMSC)( __DRIdrawable *priv, int64_t target_msc,
-			       int64_t divisor, int64_t remainder );
-    /*@}*/
-    void (*CopySubBuffer)(__DRIdrawable *driDrawPriv,
-			  int x, int y, int w, int h);
-
-    /**
-     * New version of GetMSC so we can pass drawable data to the low
-     * level DRM driver (e.g. pipe info).  Required if
-     * GLX_SGI_video_sync or GLX_OML_sync_control is supported.
-     */
-    int (*GetDrawableMSC) ( __DRIscreen * priv,
-			    __DRIdrawable *drawablePrivate,
-			    int64_t *count);
-
-
-
-    /* DRI2 Entry point */
-    const __DRIconfig **(*InitScreen2) (__DRIscreen * priv);
-};
-
-extern const struct __DriverAPIRec driDriverAPI;
-
-
-struct __DRIswapInfoRec {
-    /** 
-     * Number of swapBuffers operations that have been *completed*. 
-     */
-    uint64_t swap_count;
-
-    /**
-     * Unadjusted system time of the last buffer swap.  This is the time
-     * when the swap completed, not the time when swapBuffers was called.
-     */
-    int64_t   swap_ust;
-
-    /**
-     * Number of swap operations that occurred after the swap deadline.  That
-     * is if a swap happens more than swap_interval frames after the previous
-     * swap, it has missed its deadline.  If swap_interval is 0, then the
-     * swap deadline is 1 frame after the previous swap.
-     */
-    uint64_t swap_missed_count;
-
-    /**
-     * Amount of time used by the last swap that missed its deadline.  This
-     * is calculated as (__glXGetUST() - swap_ust) / (swap_interval * 
-     * time_for_single_vrefresh)).  If the actual value of swap_interval is
-     * 0, then 1 is used instead.  If swap_missed_count is non-zero, this
-     * should be greater-than 1.0.
-     */
-    float     swap_missed_usage;
-};
-
-
-/**
- * Per-drawable private DRI driver information.
- */
-struct __DRIdrawableRec {
-    /**
-     * Kernel drawable handle
-     */
-    drm_drawable_t hHWDrawable;
-
-    /**
-     * Driver's private drawable information.  
-     *
-     * This structure is opaque.
-     */
-    void *driverPrivate;
-
-    /**
-     * Private data from the loader.  We just hold on to it and pass
-     * it back when calling into loader provided functions.
-     */
-    void *loaderPrivate;
-
-    /**
-     * Reference count for number of context's currently bound to this
-     * drawable.  
-     *
-     * Once it reaches zero, the drawable can be destroyed.
-     *
-     * \note This behavior will change with GLX 1.3.
-     */
-    int refcount;
-
-    /**
-     * Index of this drawable information in the SAREA.
-     */
-    unsigned int index;
-
-    /**
-     * Pointer to the "drawable has changed ID" stamp in the SAREA (or
-     * to dri2.stamp if DRI2 is being used).
-     */
-    unsigned int *pStamp;
-
-    /**
-     * Last value of the stamp.
-     *
-     * If this differs from the value stored at __DRIdrawable::pStamp,
-     * then the drawable information has been modified by the X server, and the
-     * drawable information (below) should be retrieved from the X server.
-     */
-    unsigned int lastStamp;
-
-    /**
-     * \name Drawable 
-     *
-     * Drawable information used in software fallbacks.
-     */
-    /*@{*/
-    int x;
-    int y;
-    int w;
-    int h;
-    int numClipRects;
-    drm_clip_rect_t *pClipRects;
-    /*@}*/
-
-    /**
-     * \name Back and depthbuffer
-     *
-     * Information about the back and depthbuffer where different from above.
-     */
-    /*@{*/
-    int backX;
-    int backY;
-    int backClipRectType;
-    int numBackClipRects;
-    drm_clip_rect_t *pBackClipRects;
-    /*@}*/
-
-    /**
-     * \name Vertical blank tracking information
-     * Used for waiting on vertical blank events.
-     */
-    /*@{*/
-    unsigned int vblSeq;
-    unsigned int vblFlags;
-    /*@}*/
-
-    /**
-     * \name Monotonic MSC tracking
-     *
-     * Low level driver is responsible for updating msc_base and
-     * vblSeq values so that higher level code can calculate
-     * a new msc value or msc target for a WaitMSC call.  The new value
-     * will be:
-     *   msc = msc_base + get_vblank_count() - vblank_base;
-     *
-     * And for waiting on a value, core code will use:
-     *   actual_target = target_msc - msc_base + vblank_base;
-     */
-    /*@{*/
-    int64_t vblank_base;
-    int64_t msc_base;
-    /*@}*/
-
-    /**
-     * Pointer to context to which this drawable is currently bound.
-     */
-    __DRIcontext *driContextPriv;
-
-    /**
-     * Pointer to screen on which this drawable was created.
-     */
-    __DRIscreen *driScreenPriv;
-
-    /**
-     * Controls swap interval as used by GLX_SGI_swap_control and
-     * GLX_MESA_swap_control.
-     */
-    unsigned int swap_interval;
-
-    struct {
-	unsigned int stamp;
-	drm_clip_rect_t clipRect;
-    } dri2;
-};
-
-/**
- * Per-context private driver information.
- */
-struct __DRIcontextRec {
-    /**
-     * Kernel context handle used to access the device lock.
-     */
-    drm_context_t hHWContext;
-
-    /**
-     * Device driver's private context data.  This structure is opaque.
-     */
-    void *driverPrivate;
-
-    /**
-     * Pointer to drawable currently bound to this context for drawing.
-     */
-    __DRIdrawable *driDrawablePriv;
-
-    /**
-     * Pointer to drawable currently bound to this context for reading.
-     */
-    __DRIdrawable *driReadablePriv;
-
-    /**
-     * Pointer to screen on which this context was created.
-     */
-    __DRIscreen *driScreenPriv;
-
-    /**
-     * The loaders's private context data.  This structure is opaque.
-     */
-    void *loaderPrivate;
-
-    struct {
-	int draw_stamp;
-	int read_stamp;
-    } dri2;
-};
-
-/**
- * Per-screen private driver information.
- */
-struct __DRIscreenRec {
-    /**
-     * Current screen's number
-     */
-    int myNum;
-
-    /**
-     * Callback functions into the hardware-specific DRI driver code.
-     */
-    struct __DriverAPIRec DriverAPI;
-
-    const __DRIextension **extensions;
-    /**
-     * DDX / 2D driver version information.
-     */
-    __DRIversion ddx_version;
-
-    /**
-     * DRI X extension version information.
-     */
-    __DRIversion dri_version;
-
-    /**
-     * DRM (kernel module) version information.
-     */
-    __DRIversion drm_version;
-
-    /**
-     * ID used when the client sets the drawable lock.
-     *
-     * The X server uses this value to detect if the client has died while
-     * holding the drawable lock.
-     */
-    int drawLockID;
-
-    /**
-     * File descriptor returned when the kernel device driver is opened.
-     * 
-     * Used to:
-     *   - authenticate client to kernel
-     *   - map the frame buffer, SAREA, etc.
-     *   - close the kernel device driver
-     */
-    int fd;
-
-    /**
-     * SAREA pointer 
-     *
-     * Used to access:
-     *   - the device lock
-     *   - the device-independent per-drawable and per-context(?) information
-     */
-    drm_sarea_t *pSAREA;
-
-    /**
-     * \name Direct frame buffer access information 
-     * Used for software fallbacks.
-     */
-    /*@{*/
-    unsigned char *pFB;
-    int fbSize;
-    int fbOrigin;
-    int fbStride;
-    int fbWidth;
-    int fbHeight;
-    int fbBPP;
-    /*@}*/
-
-    /**
-     * \name Device-dependent private information (stored in the SAREA).
-     *
-     * This data is accessed by the client driver only.
-     */
-    /*@{*/
-    void *pDevPriv;
-    int devPrivSize;
-    /*@}*/
-
-    /**
-     * Device-dependent private information (not stored in the SAREA).
-     * 
-     * This pointer is never touched by the DRI layer.
-     */
-#ifdef __cplusplus
-    void *priv;
-#else
-    void *private;
-#endif
-
-    /* Extensions provided by the loader. */
-    const __DRIgetDrawableInfoExtension *getDrawableInfo;
-    const __DRIsystemTimeExtension *systemTime;
-    const __DRIdamageExtension *damage;
-
-    struct {
-	/* Flag to indicate that this is a DRI2 screen.  Many of the above
-	 * fields will not be valid or initializaed in that case. */
-	int enabled;
-	__DRIdri2LoaderExtension *loader;
-	__DRIimageLookupExtension *image;
-	__DRIuseInvalidateExtension *useInvalidate;
-    } dri2;
-
-    /* The lock actually in use, old sarea or DRI2 */
-    drmLock *lock;
-
-    driOptionCache optionInfo;
-    driOptionCache optionCache;
-   unsigned int api_mask;
-   void *loaderPrivate;
-};
-
-extern void
-__driUtilUpdateDrawableInfo(__DRIdrawable *pdp);
-
-extern float
-driCalculateSwapUsage( __DRIdrawable *dPriv,
-		       int64_t last_swap_ust, int64_t current_ust );
-
-extern GLint
-driIntersectArea( drm_clip_rect_t rect1, drm_clip_rect_t rect2 );
-
-extern void
-dri2InvalidateDrawable(__DRIdrawable *drawable);
-
-#endif /* _DRI_UTIL_H_ */
+/*
+ * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+ * 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"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file dri_util.h
+ * DRI utility functions definitions.
+ *
+ * This module acts as glue between GLX and the actual hardware driver.  A DRI
+ * driver doesn't really \e have to use any of this - it's optional.  But, some
+ * useful stuff is done here that otherwise would have to be duplicated in most
+ * drivers.
+ * 
+ * Basically, these utility functions take care of some of the dirty details of
+ * screen initialization, context creation, context binding, DRM setup, etc.
+ *
+ * These functions are compiled into each DRI driver so libGL.so knows nothing
+ * about them.
+ *
+ * \sa dri_util.c.
+ * 
+ * \author Kevin E. Martin <kevin@precisioninsight.com>
+ * \author Brian Paul <brian@precisioninsight.com>
+ */
+
+#ifndef _DRI_UTIL_H_
+#define _DRI_UTIL_H_
+
+#include <GL/gl.h>
+#include <drm.h>
+#include <drm_sarea.h>
+#include <xf86drm.h>
+#include "xmlconfig.h"
+#include "main/glheader.h"
+#include "main/mtypes.h"
+#include "GL/internal/dri_interface.h"
+
+#define GLX_BAD_CONTEXT                    5
+
+typedef struct __DRIswapInfoRec        __DRIswapInfo;
+
+/**
+ * Extensions.
+ */
+extern const __DRIlegacyExtension driLegacyExtension;
+extern const __DRIcoreExtension driCoreExtension;
+extern const __DRIdri2Extension driDRI2Extension;
+extern const __DRIextension driReadDrawableExtension;
+extern const __DRIcopySubBufferExtension driCopySubBufferExtension;
+extern const __DRIswapControlExtension driSwapControlExtension;
+extern const __DRImediaStreamCounterExtension driMediaStreamCounterExtension;
+extern const __DRI2configQueryExtension dri2ConfigQueryExtension;
+
+/**
+ * Used by DRI_VALIDATE_DRAWABLE_INFO
+ */
+#define DRI_VALIDATE_DRAWABLE_INFO_ONCE(pDrawPriv)              \
+    do {                                                        \
+	if (*(pDrawPriv->pStamp) != pDrawPriv->lastStamp) {     \
+	    __driUtilUpdateDrawableInfo(pDrawPriv);             \
+	}                                                       \
+    } while (0)
+
+
+/**
+ * Utility macro to validate the drawable information.
+ *
+ * See __DRIdrawable::pStamp and __DRIdrawable::lastStamp.
+ */
+#define DRI_VALIDATE_DRAWABLE_INFO(psp, pdp)                            \
+do {                                                                    \
+    while (*(pdp->pStamp) != pdp->lastStamp) {                          \
+        register unsigned int hwContext = psp->pSAREA->lock.lock &      \
+		     ~(DRM_LOCK_HELD | DRM_LOCK_CONT);                  \
+	DRM_UNLOCK(psp->fd, &psp->pSAREA->lock, hwContext);             \
+                                                                        \
+	DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);     \
+	DRI_VALIDATE_DRAWABLE_INFO_ONCE(pdp);                           \
+	DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);   \
+                                                                        \
+	DRM_LIGHT_LOCK(psp->fd, &psp->pSAREA->lock, hwContext);         \
+    }                                                                   \
+} while (0)
+
+/**
+ * Same as above, but for two drawables simultaneously.
+ *
+ */
+
+#define DRI_VALIDATE_TWO_DRAWABLES_INFO(psp, pdp, prp)			\
+do {								\
+    while (*((pdp)->pStamp) != (pdp)->lastStamp ||			\
+	   *((prp)->pStamp) != (prp)->lastStamp) {			\
+        register unsigned int hwContext = (psp)->pSAREA->lock.lock &	\
+	    ~(DRM_LOCK_HELD | DRM_LOCK_CONT);				\
+	DRM_UNLOCK((psp)->fd, &(psp)->pSAREA->lock, hwContext);		\
+									\
+	DRM_SPINLOCK(&(psp)->pSAREA->drawable_lock, (psp)->drawLockID);	\
+	DRI_VALIDATE_DRAWABLE_INFO_ONCE(pdp);                           \
+	DRI_VALIDATE_DRAWABLE_INFO_ONCE(prp);				\
+	DRM_SPINUNLOCK(&(psp)->pSAREA->drawable_lock, (psp)->drawLockID); \
+									\
+	DRM_LIGHT_LOCK((psp)->fd, &(psp)->pSAREA->lock, hwContext);	\
+    }                                                                   \
+} while (0)
+
+
+/**
+ * Driver callback functions.
+ *
+ * Each DRI driver must have one of these structures with all the pointers set
+ * to appropriate functions within the driver.
+ * 
+ * When glXCreateContext() is called, for example, it'll call a helper function
+ * dri_util.c which in turn will jump through the \a CreateContext pointer in
+ * this structure.
+ */
+struct __DriverAPIRec {
+    const __DRIconfig **(*InitScreen) (__DRIscreen * priv);
+
+    /**
+     * Screen destruction callback
+     */
+    void (*DestroyScreen)(__DRIscreen *driScrnPriv);
+
+    /**
+     * Context creation callback
+     */	    	    
+    GLboolean (*CreateContext)(gl_api api,
+			       const struct gl_config *glVis,
+			       __DRIcontext *driContextPriv,
+                               void *sharedContextPrivate);
+
+    /**
+     * Context destruction callback
+     */
+    void (*DestroyContext)(__DRIcontext *driContextPriv);
+
+    /**
+     * Buffer (drawable) creation callback
+     */
+    GLboolean (*CreateBuffer)(__DRIscreen *driScrnPriv,
+                              __DRIdrawable *driDrawPriv,
+                              const struct gl_config *glVis,
+                              GLboolean pixmapBuffer);
+    
+    /**
+     * Buffer (drawable) destruction callback
+     */
+    void (*DestroyBuffer)(__DRIdrawable *driDrawPriv);
+
+    /**
+     * Buffer swapping callback 
+     */
+    void (*SwapBuffers)(__DRIdrawable *driDrawPriv);
+
+    /**
+     * Context activation callback
+     */
+    GLboolean (*MakeCurrent)(__DRIcontext *driContextPriv,
+                             __DRIdrawable *driDrawPriv,
+                             __DRIdrawable *driReadPriv);
+
+    /**
+     * Context unbinding callback
+     */
+    GLboolean (*UnbindContext)(__DRIcontext *driContextPriv);
+  
+    /**
+     * Retrieves statistics about buffer swap operations.  Required if
+     * GLX_OML_sync_control or GLX_MESA_swap_frame_usage is supported.
+     */
+    int (*GetSwapInfo)( __DRIdrawable *dPriv, __DRIswapInfo * sInfo );
+
+
+    /**
+     * These are required if GLX_OML_sync_control is supported.
+     */
+    /*@{*/
+    int (*WaitForMSC)( __DRIdrawable *priv, int64_t target_msc, 
+		       int64_t divisor, int64_t remainder,
+		       int64_t * msc );
+    int (*WaitForSBC)( __DRIdrawable *priv, int64_t target_sbc,
+		       int64_t * msc, int64_t * sbc );
+
+    int64_t (*SwapBuffersMSC)( __DRIdrawable *priv, int64_t target_msc,
+			       int64_t divisor, int64_t remainder );
+    /*@}*/
+    void (*CopySubBuffer)(__DRIdrawable *driDrawPriv,
+			  int x, int y, int w, int h);
+
+    /**
+     * New version of GetMSC so we can pass drawable data to the low
+     * level DRM driver (e.g. pipe info).  Required if
+     * GLX_SGI_video_sync or GLX_OML_sync_control is supported.
+     */
+    int (*GetDrawableMSC) ( __DRIscreen * priv,
+			    __DRIdrawable *drawablePrivate,
+			    int64_t *count);
+
+
+
+    /* DRI2 Entry point */
+    const __DRIconfig **(*InitScreen2) (__DRIscreen * priv);
+
+    __DRIbuffer *(*AllocateBuffer) (__DRIscreen *screenPrivate,
+				    unsigned int attachment,
+				    unsigned int format,
+				    int width, int height);
+    void (*ReleaseBuffer) (__DRIscreen *screenPrivate, __DRIbuffer *buffer);
+};
+
+extern const struct __DriverAPIRec driDriverAPI;
+
+
+struct __DRIswapInfoRec {
+    /** 
+     * Number of swapBuffers operations that have been *completed*. 
+     */
+    uint64_t swap_count;
+
+    /**
+     * Unadjusted system time of the last buffer swap.  This is the time
+     * when the swap completed, not the time when swapBuffers was called.
+     */
+    int64_t   swap_ust;
+
+    /**
+     * Number of swap operations that occurred after the swap deadline.  That
+     * is if a swap happens more than swap_interval frames after the previous
+     * swap, it has missed its deadline.  If swap_interval is 0, then the
+     * swap deadline is 1 frame after the previous swap.
+     */
+    uint64_t swap_missed_count;
+
+    /**
+     * Amount of time used by the last swap that missed its deadline.  This
+     * is calculated as (__glXGetUST() - swap_ust) / (swap_interval * 
+     * time_for_single_vrefresh)).  If the actual value of swap_interval is
+     * 0, then 1 is used instead.  If swap_missed_count is non-zero, this
+     * should be greater-than 1.0.
+     */
+    float     swap_missed_usage;
+};
+
+
+/**
+ * Per-drawable private DRI driver information.
+ */
+struct __DRIdrawableRec {
+    /**
+     * Kernel drawable handle
+     */
+    drm_drawable_t hHWDrawable;
+
+    /**
+     * Driver's private drawable information.  
+     *
+     * This structure is opaque.
+     */
+    void *driverPrivate;
+
+    /**
+     * Private data from the loader.  We just hold on to it and pass
+     * it back when calling into loader provided functions.
+     */
+    void *loaderPrivate;
+
+    /**
+     * Reference count for number of context's currently bound to this
+     * drawable.  
+     *
+     * Once it reaches zero, the drawable can be destroyed.
+     *
+     * \note This behavior will change with GLX 1.3.
+     */
+    int refcount;
+
+    /**
+     * Index of this drawable information in the SAREA.
+     */
+    unsigned int index;
+
+    /**
+     * Pointer to the "drawable has changed ID" stamp in the SAREA (or
+     * to dri2.stamp if DRI2 is being used).
+     */
+    unsigned int *pStamp;
+
+    /**
+     * Last value of the stamp.
+     *
+     * If this differs from the value stored at __DRIdrawable::pStamp,
+     * then the drawable information has been modified by the X server, and the
+     * drawable information (below) should be retrieved from the X server.
+     */
+    unsigned int lastStamp;
+
+    /**
+     * \name Drawable 
+     *
+     * Drawable information used in software fallbacks.
+     */
+    /*@{*/
+    int x;
+    int y;
+    int w;
+    int h;
+    int numClipRects;
+    drm_clip_rect_t *pClipRects;
+    /*@}*/
+
+    /**
+     * \name Back and depthbuffer
+     *
+     * Information about the back and depthbuffer where different from above.
+     */
+    /*@{*/
+    int backX;
+    int backY;
+    int backClipRectType;
+    int numBackClipRects;
+    drm_clip_rect_t *pBackClipRects;
+    /*@}*/
+
+    /**
+     * \name Vertical blank tracking information
+     * Used for waiting on vertical blank events.
+     */
+    /*@{*/
+    unsigned int vblSeq;
+    unsigned int vblFlags;
+    /*@}*/
+
+    /**
+     * \name Monotonic MSC tracking
+     *
+     * Low level driver is responsible for updating msc_base and
+     * vblSeq values so that higher level code can calculate
+     * a new msc value or msc target for a WaitMSC call.  The new value
+     * will be:
+     *   msc = msc_base + get_vblank_count() - vblank_base;
+     *
+     * And for waiting on a value, core code will use:
+     *   actual_target = target_msc - msc_base + vblank_base;
+     */
+    /*@{*/
+    int64_t vblank_base;
+    int64_t msc_base;
+    /*@}*/
+
+    /**
+     * Pointer to context to which this drawable is currently bound.
+     */
+    __DRIcontext *driContextPriv;
+
+    /**
+     * Pointer to screen on which this drawable was created.
+     */
+    __DRIscreen *driScreenPriv;
+
+    /**
+     * Controls swap interval as used by GLX_SGI_swap_control and
+     * GLX_MESA_swap_control.
+     */
+    unsigned int swap_interval;
+
+    struct {
+	unsigned int stamp;
+	drm_clip_rect_t clipRect;
+    } dri2;
+};
+
+/**
+ * Per-context private driver information.
+ */
+struct __DRIcontextRec {
+    /**
+     * Kernel context handle used to access the device lock.
+     */
+    drm_context_t hHWContext;
+
+    /**
+     * Device driver's private context data.  This structure is opaque.
+     */
+    void *driverPrivate;
+
+    /**
+     * Pointer to drawable currently bound to this context for drawing.
+     */
+    __DRIdrawable *driDrawablePriv;
+
+    /**
+     * Pointer to drawable currently bound to this context for reading.
+     */
+    __DRIdrawable *driReadablePriv;
+
+    /**
+     * Pointer to screen on which this context was created.
+     */
+    __DRIscreen *driScreenPriv;
+
+    /**
+     * The loaders's private context data.  This structure is opaque.
+     */
+    void *loaderPrivate;
+
+    struct {
+	int draw_stamp;
+	int read_stamp;
+    } dri2;
+};
+
+/**
+ * Per-screen private driver information.
+ */
+struct __DRIscreenRec {
+    /**
+     * Current screen's number
+     */
+    int myNum;
+
+    /**
+     * Callback functions into the hardware-specific DRI driver code.
+     */
+    struct __DriverAPIRec DriverAPI;
+
+    const __DRIextension **extensions;
+    /**
+     * DDX / 2D driver version information.
+     */
+    __DRIversion ddx_version;
+
+    /**
+     * DRI X extension version information.
+     */
+    __DRIversion dri_version;
+
+    /**
+     * DRM (kernel module) version information.
+     */
+    __DRIversion drm_version;
+
+    /**
+     * ID used when the client sets the drawable lock.
+     *
+     * The X server uses this value to detect if the client has died while
+     * holding the drawable lock.
+     */
+    int drawLockID;
+
+    /**
+     * File descriptor returned when the kernel device driver is opened.
+     * 
+     * Used to:
+     *   - authenticate client to kernel
+     *   - map the frame buffer, SAREA, etc.
+     *   - close the kernel device driver
+     */
+    int fd;
+
+    /**
+     * SAREA pointer 
+     *
+     * Used to access:
+     *   - the device lock
+     *   - the device-independent per-drawable and per-context(?) information
+     */
+    drm_sarea_t *pSAREA;
+
+    /**
+     * \name Direct frame buffer access information 
+     * Used for software fallbacks.
+     */
+    /*@{*/
+    unsigned char *pFB;
+    int fbSize;
+    int fbOrigin;
+    int fbStride;
+    int fbWidth;
+    int fbHeight;
+    int fbBPP;
+    /*@}*/
+
+    /**
+     * \name Device-dependent private information (stored in the SAREA).
+     *
+     * This data is accessed by the client driver only.
+     */
+    /*@{*/
+    void *pDevPriv;
+    int devPrivSize;
+    /*@}*/
+
+    /**
+     * Device-dependent private information (not stored in the SAREA).
+     * 
+     * This pointer is never touched by the DRI layer.
+     */
+#ifdef __cplusplus
+    void *priv;
+#else
+    void *private;
+#endif
+
+    /* Extensions provided by the loader. */
+    const __DRIgetDrawableInfoExtension *getDrawableInfo;
+    const __DRIsystemTimeExtension *systemTime;
+    const __DRIdamageExtension *damage;
+
+    struct {
+	/* Flag to indicate that this is a DRI2 screen.  Many of the above
+	 * fields will not be valid or initializaed in that case. */
+	int enabled;
+	__DRIdri2LoaderExtension *loader;
+	__DRIimageLookupExtension *image;
+	__DRIuseInvalidateExtension *useInvalidate;
+    } dri2;
+
+    /* The lock actually in use, old sarea or DRI2 */
+    drmLock *lock;
+
+    driOptionCache optionInfo;
+    driOptionCache optionCache;
+   unsigned int api_mask;
+   void *loaderPrivate;
+};
+
+extern void
+__driUtilUpdateDrawableInfo(__DRIdrawable *pdp);
+
+extern float
+driCalculateSwapUsage( __DRIdrawable *dPriv,
+		       int64_t last_swap_ust, int64_t current_ust );
+
+extern GLint
+driIntersectArea( drm_clip_rect_t rect1, drm_clip_rect_t rect2 );
+
+extern void
+dri2InvalidateDrawable(__DRIdrawable *drawable);
+
+#endif /* _DRI_UTIL_H_ */
diff --git a/mesalib/src/mesa/drivers/dri/swrast/swrast.c b/mesalib/src/mesa/drivers/dri/swrast/swrast.c
index 144b187c1..719b406ec 100644
--- a/mesalib/src/mesa/drivers/dri/swrast/swrast.c
+++ b/mesalib/src/mesa/drivers/dri/swrast/swrast.c
@@ -651,7 +651,7 @@ dri_create_context(gl_api api,
     mesaCtx = &ctx->Base;
 
     /* basic context setup */
-    if (!_mesa_initialize_context_for_api(mesaCtx, api, visual, sharedCtx, &functions, (void *) cPriv)) {
+    if (!_mesa_initialize_context(mesaCtx, api, visual, sharedCtx, &functions, (void *) cPriv)) {
 	goto context_fail;
     }
 
diff --git a/mesalib/src/mesa/drivers/windows/gdi/wmesa.c b/mesalib/src/mesa/drivers/windows/gdi/wmesa.c
index a30326c0c..4a8b1b283 100644
--- a/mesalib/src/mesa/drivers/windows/gdi/wmesa.c
+++ b/mesalib/src/mesa/drivers/windows/gdi/wmesa.c
@@ -1,1661 +1,1662 @@
-/*
- * Windows (Win32/Win64) device driver for Mesa
- *
- */
-
-#include "wmesadef.h"
-#include "colors.h"
-#include <GL/wmesa.h>
-#include <winuser.h>
-#include "context.h"
-#include "extensions.h"
-#include "framebuffer.h"
-#include "renderbuffer.h"
-#include "drivers/common/driverfuncs.h"
-#include "drivers/common/meta.h"
-#include "vbo/vbo.h"
-#include "swrast/swrast.h"
-#include "swrast_setup/swrast_setup.h"
-#include "tnl/tnl.h"
-#include "tnl/t_context.h"
-#include "tnl/t_pipeline.h"
-
-
-/* linked list of our Framebuffers (windows) */
-static WMesaFramebuffer FirstFramebuffer = NULL;
-
-
-/**
- * Create a new WMesaFramebuffer object which will correspond to the
- * given HDC (Window handle).
- */
-WMesaFramebuffer
-wmesa_new_framebuffer(HDC hdc, struct gl_config *visual)
-{
-    WMesaFramebuffer pwfb
-        = (WMesaFramebuffer) malloc(sizeof(struct wmesa_framebuffer));
-    if (pwfb) {
-        _mesa_initialize_window_framebuffer(&pwfb->Base, visual);
-        pwfb->hDC = hdc;
-        /* insert at head of list */
-        pwfb->next = FirstFramebuffer;
-        FirstFramebuffer = pwfb;
-    }
-    return pwfb;
-}
-
-/**
- * Given an hdc, free the corresponding WMesaFramebuffer
- */
-void
-wmesa_free_framebuffer(HDC hdc)
-{
-    WMesaFramebuffer pwfb, prev;
-    for (pwfb = FirstFramebuffer; pwfb; pwfb = pwfb->next) {
-        if (pwfb->hDC == hdc)
-            break;
-	prev = pwfb;
-    }
-    if (pwfb) {
-        struct gl_framebuffer *fb;
-	if (pwfb == FirstFramebuffer)
-	    FirstFramebuffer = pwfb->next;
-	else
-	    prev->next = pwfb->next;
-        fb = &pwfb->Base;
-        _mesa_reference_framebuffer(&fb, NULL); 
-    }
-}
-
-/**
- * Given an hdc, return the corresponding WMesaFramebuffer
- */
-WMesaFramebuffer
-wmesa_lookup_framebuffer(HDC hdc)
-{
-    WMesaFramebuffer pwfb;
-    for (pwfb = FirstFramebuffer; pwfb; pwfb = pwfb->next) {
-        if (pwfb->hDC == hdc)
-            return pwfb;
-    }
-    return NULL;
-}
-
-
-/**
- * Given a struct gl_framebuffer, return the corresponding WMesaFramebuffer.
- */
-static WMesaFramebuffer wmesa_framebuffer(struct gl_framebuffer *fb)
-{
-    return (WMesaFramebuffer) fb;
-}
-
-
-/**
- * Given a struct gl_context, return the corresponding WMesaContext.
- */
-static WMesaContext wmesa_context(const struct gl_context *ctx)
-{
-    return (WMesaContext) ctx;
-}
-
-
-/*
- * Every driver should implement a GetString function in order to
- * return a meaningful GL_RENDERER string.
- */
-static const GLubyte *wmesa_get_string(struct gl_context *ctx, GLenum name)
-{
-    return (name == GL_RENDERER) ? 
-	(GLubyte *) "Mesa Windows GDI Driver" : NULL;
-}
-
-
-/*
- * Determine the pixel format based on the pixel size.
- */
-static void wmSetPixelFormat(WMesaFramebuffer pwfb, HDC hDC)
-{
-    pwfb->cColorBits = GetDeviceCaps(hDC, BITSPIXEL);
-
-    /* Only 16 and 32 bit targets are supported now */
-    assert(pwfb->cColorBits == 0 ||
-	   pwfb->cColorBits == 16 || 
-	   pwfb->cColorBits == 24 || 
-	   pwfb->cColorBits == 32);
-
-    switch(pwfb->cColorBits){
-    case 8:
-	pwfb->pixelformat = PF_INDEX8;
-	break;
-    case 16:
-	pwfb->pixelformat = PF_5R6G5B;
-	break;
-    case 24:
-    case 32:
-	pwfb->pixelformat = PF_8R8G8B;
-	break;
-    default:
-	pwfb->pixelformat = PF_BADFORMAT;
-    }
-}
-
-
-/**
- * Create DIB for back buffer.
- * We write into this memory with the span routines and then blit it
- * to the window on a buffer swap.
- */
-BOOL wmCreateBackingStore(WMesaFramebuffer pwfb, long lxSize, long lySize)
-{
-    HDC          hdc = pwfb->hDC;
-    LPBITMAPINFO pbmi = &(pwfb->bmi);
-    HDC          hic;
-
-    pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
-    pbmi->bmiHeader.biWidth = lxSize;
-    pbmi->bmiHeader.biHeight= -lySize;
-    pbmi->bmiHeader.biPlanes = 1;
-    pbmi->bmiHeader.biBitCount = GetDeviceCaps(pwfb->hDC, BITSPIXEL);
-    pbmi->bmiHeader.biCompression = BI_RGB;
-    pbmi->bmiHeader.biSizeImage = 0;
-    pbmi->bmiHeader.biXPelsPerMeter = 0;
-    pbmi->bmiHeader.biYPelsPerMeter = 0;
-    pbmi->bmiHeader.biClrUsed = 0;
-    pbmi->bmiHeader.biClrImportant = 0;
-    
-    pwfb->cColorBits = pbmi->bmiHeader.biBitCount;
-    pwfb->ScanWidth = (lxSize * (pwfb->cColorBits / 8) + 3) & ~3;
-    
-    hic = CreateIC("display", NULL, NULL, NULL);
-    pwfb->dib_hDC = CreateCompatibleDC(hic);
-    
-    pwfb->hbmDIB = CreateDIBSection(hic,
-				   &pwfb->bmi,
-				   DIB_RGB_COLORS,
-				   (void **)&(pwfb->pbPixels),
-				   0,
-				   0);
-    pwfb->hOldBitmap = SelectObject(pwfb->dib_hDC, pwfb->hbmDIB);
-    
-    DeleteDC(hic);
-
-    wmSetPixelFormat(pwfb, pwfb->hDC);
-    return TRUE;
-}
-
-
-static wmDeleteBackingStore(WMesaFramebuffer pwfb)
-{
-    if (pwfb->hbmDIB) {
-	SelectObject(pwfb->dib_hDC, pwfb->hOldBitmap);
-	DeleteDC(pwfb->dib_hDC);
-	DeleteObject(pwfb->hbmDIB);
-    }
-}
-
-
-/**
- * Find the width and height of the window named by hdc.
- */
-static void
-get_window_size(HDC hdc, GLuint *width, GLuint *height)
-{
-    if (WindowFromDC(hdc)) {
-        RECT rect;
-        GetClientRect(WindowFromDC(hdc), &rect);
-        *width = rect.right - rect.left;
-        *height = rect.bottom - rect.top;
-    }
-    else { /* Memory context */
-        /* From contributed code - use the size of the desktop
-         * for the size of a memory context (?) */
-        *width = GetDeviceCaps(hdc, HORZRES);
-        *height = GetDeviceCaps(hdc, VERTRES);
-    }
-}
-
-
-static void
-wmesa_get_buffer_size(struct gl_framebuffer *buffer, GLuint *width, GLuint *height)
-{
-    WMesaFramebuffer pwfb = wmesa_framebuffer(buffer);
-    get_window_size(pwfb->hDC, width, height);
-}
-
-
-static void wmesa_flush(struct gl_context *ctx)
-{
-    WMesaContext pwc = wmesa_context(ctx);
-    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->WinSysDrawBuffer);
-
-    if (ctx->Visual.doubleBufferMode == 1) {
-	BitBlt(pwfb->hDC, 0, 0, pwfb->Base.Width, pwfb->Base.Height,
-	       pwfb->dib_hDC, 0, 0, SRCCOPY);
-    }
-    else {
-	/* Do nothing for single buffer */
-    }
-}
-
-
-/**********************************************************************/
-/*****                   CLEAR Functions                          *****/
-/**********************************************************************/
-
-/* If we do not implement these, Mesa clears the buffers via the pixel
- * span writing interface, which is very slow for a clear operation.
- */
-
-/*
- * Set the color used to clear the color buffer.
- */
-static void clear_color(struct gl_context *ctx, const GLfloat color[4])
-{
-    WMesaContext pwc = wmesa_context(ctx);
-    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
-    GLubyte col[3];
-    UINT    bytesPerPixel = pwfb->cColorBits / 8; 
-
-    CLAMPED_FLOAT_TO_UBYTE(col[0], color[0]);
-    CLAMPED_FLOAT_TO_UBYTE(col[1], color[1]);
-    CLAMPED_FLOAT_TO_UBYTE(col[2], color[2]);
-    pwc->clearColorRef = RGB(col[0], col[1], col[2]);
-    DeleteObject(pwc->clearPen);
-    DeleteObject(pwc->clearBrush);
-    pwc->clearPen = CreatePen(PS_SOLID, 1, pwc->clearColorRef); 
-    pwc->clearBrush = CreateSolidBrush(pwc->clearColorRef); 
-}
-
-
-/* 
- * Clear the specified region of the color buffer using the clear color 
- * or index as specified by one of the two functions above. 
- * 
- * This procedure clears either the front and/or the back COLOR buffers. 
- * Only the "left" buffer is cleared since we are not stereo. 
- * Clearing of the other non-color buffers is left to the swrast. 
- */ 
-
-static void clear(struct gl_context *ctx, GLbitfield mask)
-{
-#define FLIP(Y)  (ctx->DrawBuffer->Height - (Y) - 1)
-    const GLint x = ctx->DrawBuffer->_Xmin;
-    const GLint y = ctx->DrawBuffer->_Ymin;
-    const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
-    const GLint width  = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
-
-    WMesaContext pwc = wmesa_context(ctx);
-    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
-    int done = 0;
-
-    /* Let swrast do all the work if the masks are not set to
-     * clear all channels. */
-    if (!ctx->Color.ColorMask[0][0] ||
-	!ctx->Color.ColorMask[0][1] ||
-	!ctx->Color.ColorMask[0][2] ||
-	!ctx->Color.ColorMask[0][3]) {
-	_swrast_Clear(ctx, mask);
-	return;
-    }
-
-    /* Back buffer */
-    if (mask & BUFFER_BIT_BACK_LEFT) { 
-	
-	int     i, rowSize; 
-	UINT    bytesPerPixel = pwfb->cColorBits / 8; 
-	LPBYTE  lpb, clearRow;
-	LPWORD  lpw;
-	BYTE    bColor; 
-	WORD    wColor; 
-	BYTE    r, g, b; 
-	DWORD   dwColor; 
-	LPDWORD lpdw; 
-	
-	/* Try for a fast clear - clearing entire buffer with a single
-	 * byte value. */
-	if (width == ctx->DrawBuffer->Width &&
-            height == ctx->DrawBuffer->Height) { /* entire buffer */
-	    /* Now check for an easy clear value */
-	    switch (bytesPerPixel) {
-	    case 1:
-		bColor = BGR8(GetRValue(pwc->clearColorRef), 
-			      GetGValue(pwc->clearColorRef), 
-			      GetBValue(pwc->clearColorRef));
-		memset(pwfb->pbPixels, bColor, 
-		       pwfb->ScanWidth * height);
-		done = 1;
-		break;
-	    case 2:
-		wColor = BGR16(GetRValue(pwc->clearColorRef), 
-			       GetGValue(pwc->clearColorRef), 
-			       GetBValue(pwc->clearColorRef)); 
-		if (((wColor >> 8) & 0xff) == (wColor & 0xff)) {
-		    memset(pwfb->pbPixels, wColor & 0xff, 
-			   pwfb->ScanWidth * height);
-		    done = 1;
-		}
-		break;
-	    case 3:
-		/* fall through */
-	    case 4:
-		if (GetRValue(pwc->clearColorRef) == 
-		    GetGValue(pwc->clearColorRef) &&
-		    GetRValue(pwc->clearColorRef) == 
-		    GetBValue(pwc->clearColorRef)) {
-		    memset(pwfb->pbPixels, 
-			   GetRValue(pwc->clearColorRef), 
-			   pwfb->ScanWidth * height);
-		    done = 1;
-		}
-		break;
-	    default:
-		break;
-	    }
-	} /* all */
-
-	if (!done) {
-	    /* Need to clear a row at a time.  Begin by setting the first
-	     * row in the area to be cleared to the clear color. */
-	    
-	    clearRow = pwfb->pbPixels + 
-		pwfb->ScanWidth * FLIP(y) +
-		bytesPerPixel * x; 
-	    switch (bytesPerPixel) {
-	    case 1:
-		lpb = clearRow;
-		bColor = BGR8(GetRValue(pwc->clearColorRef), 
-			      GetGValue(pwc->clearColorRef), 
-			      GetBValue(pwc->clearColorRef));
-		memset(lpb, bColor, width);
-		break;
-	    case 2:
-		lpw = (LPWORD)clearRow;
-		wColor = BGR16(GetRValue(pwc->clearColorRef), 
-			       GetGValue(pwc->clearColorRef), 
-			       GetBValue(pwc->clearColorRef)); 
-		for (i=0; i<width; i++)
-		    *lpw++ = wColor;
-		break;
-	    case 3: 
-		lpb = clearRow;
-		r = GetRValue(pwc->clearColorRef); 
-		g = GetGValue(pwc->clearColorRef); 
-		b = GetBValue(pwc->clearColorRef); 
-		for (i=0; i<width; i++) {
-		    *lpb++ = b; 
-		    *lpb++ = g; 
-		    *lpb++ = r; 
-		} 
-		break;
-	    case 4: 
-		lpdw = (LPDWORD)clearRow; 
-		dwColor = BGR32(GetRValue(pwc->clearColorRef), 
-				GetGValue(pwc->clearColorRef), 
-				GetBValue(pwc->clearColorRef)); 
-		for (i=0; i<width; i++)
-		    *lpdw++ = dwColor;
-		break;
-	    default:
-		break;
-	    } /* switch */
-	    
-	    /* copy cleared row to other rows in buffer */
-	    lpb = clearRow - pwfb->ScanWidth;
-	    rowSize = width * bytesPerPixel;
-	    for (i=1; i<height; i++) { 
-		memcpy(lpb, clearRow, rowSize); 
-		lpb -= pwfb->ScanWidth; 
-	    } 
-	} /* not done */
-	mask &= ~BUFFER_BIT_BACK_LEFT;
-    } /* back buffer */ 
-
-    /* front buffer */
-    if (mask & BUFFER_BIT_FRONT_LEFT) { 
-	HDC DC = pwc->hDC; 
-	HPEN Old_Pen = SelectObject(DC, pwc->clearPen); 
-	HBRUSH Old_Brush = SelectObject(DC, pwc->clearBrush);
-	Rectangle(DC,
-		  x,
-		  FLIP(y) + 1,
-		  x + width + 1,
-		  FLIP(y) - height + 1);
-	SelectObject(DC, Old_Pen); 
-	SelectObject(DC, Old_Brush); 
-	mask &= ~BUFFER_BIT_FRONT_LEFT;
-    } /* front buffer */ 
-    
-    /* Call swrast if there is anything left to clear (like DEPTH) */ 
-    if (mask) 
-	_swrast_Clear(ctx, mask);
-  
-#undef FLIP
-} 
-
-
-/**********************************************************************/
-/*****                   PIXEL Functions                          *****/
-/**********************************************************************/
-
-#define FLIP(Y)  (rb->Height - (Y) - 1)
-
-
-/**
- ** Front Buffer reading/writing
- ** These are slow, but work with all non-indexed visual types.
- **/
-
-/* Write a horizontal span of RGBA color pixels with a boolean mask. */
-static void write_rgba_span_front(const struct gl_context *ctx, 
-				   struct gl_renderbuffer *rb, 
-				   GLuint n, GLint x, GLint y,
-				   const GLubyte rgba[][4], 
-				   const GLubyte mask[] )
-{
-   WMesaContext pwc = wmesa_context(ctx);
-   WMesaFramebuffer pwfb = wmesa_lookup_framebuffer(pwc->hDC);
-   CONST BITMAPINFO bmi=
-   {
-      {
-         sizeof(BITMAPINFOHEADER),
-         n, 1, 1, 32, BI_RGB, 0, 1, 1, 0, 0
-      }
-   };
-   HBITMAP bmp=0;
-   HDC mdc=0;
-   typedef union
-   {
-      unsigned i;
-      struct {
-         unsigned b:8, g:8, r:8, a:8;
-      };
-   } BGRA;
-   BGRA *bgra, c;
-   GLuint i;
-
-   if (n < 16) {   // the value 16 is just guessed
-      y=FLIP(y);
-      if (mask) {
-         for (i=0; i<n; i++)
-            if (mask[i])
-               SetPixel(pwc->hDC, x+i, y,
-                        RGB(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]));
-      }
-      else {
-         for (i=0; i<n; i++)
-            SetPixel(pwc->hDC, x+i, y,
-                     RGB(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]));
-      }
-   }
-   else {
-      if (!pwfb) {
-         _mesa_problem(NULL, "wmesa: write_rgba_span_front on unknown hdc");
-         return;
-      }
-      bgra=malloc(n*sizeof(BGRA));
-      if (!bgra) {
-         _mesa_problem(NULL, "wmesa: write_rgba_span_front: out of memory");
-         return;
-      }
-      c.a=0;
-      if (mask) {
-         for (i=0; i<n; i++) {
-            if (mask[i]) {
-               c.r=rgba[i][RCOMP];
-               c.g=rgba[i][GCOMP];
-               c.b=rgba[i][BCOMP];
-               c.a=rgba[i][ACOMP];
-               bgra[i]=c;
-            }
-            else
-               bgra[i].i=0;
-         }
-      }
-      else {
-         for (i=0; i<n; i++) {
-            c.r=rgba[i][RCOMP];
-            c.g=rgba[i][GCOMP];
-            c.b=rgba[i][BCOMP];
-            c.a=rgba[i][ACOMP];
-            bgra[i]=c;
-         }
-      }
-      bmp=CreateBitmap(n, 1,  1, 32, bgra);
-      mdc=CreateCompatibleDC(pwfb->hDC);
-      SelectObject(mdc, bmp);
-      y=FLIP(y);
-      BitBlt(pwfb->hDC, x, y, n, 1, mdc, 0, 0, SRCCOPY);
-      SelectObject(mdc, 0);
-      DeleteObject(bmp);
-      DeleteDC(mdc);
-      free(bgra);
-   }
-}
-
-/* Write a horizontal span of RGB color pixels with a boolean mask. */
-static void write_rgb_span_front(const struct gl_context *ctx, 
-				  struct gl_renderbuffer *rb, 
-				  GLuint n, GLint x, GLint y,
-				  const GLubyte rgb[][3], 
-				  const GLubyte mask[] )
-{
-    WMesaContext pwc = wmesa_context(ctx);
-    GLuint i;
-    
-    (void) ctx;
-    y=FLIP(y);
-    if (mask) {
-	for (i=0; i<n; i++)
-	    if (mask[i])
-		SetPixel(pwc->hDC, x+i, y, RGB(rgb[i][RCOMP], rgb[i][GCOMP], 
-					       rgb[i][BCOMP]));
-    }
-    else {
-	for (i=0; i<n; i++)
-	    SetPixel(pwc->hDC, x+i, y, RGB(rgb[i][RCOMP], rgb[i][GCOMP], 
-					   rgb[i][BCOMP]));
-    }
-    
-}
-
-/*
- * Write a horizontal span of pixels with a boolean mask.  The current color
- * is used for all pixels.
- */
-static void write_mono_rgba_span_front(const struct gl_context *ctx, 
-					struct gl_renderbuffer *rb,
-					GLuint n, GLint x, GLint y,
-					const GLchan color[4], 
-					const GLubyte mask[])
-{
-    GLuint i;
-    WMesaContext pwc = wmesa_context(ctx);
-    COLORREF colorref;
-
-    (void) ctx;
-    colorref = RGB(color[RCOMP], color[GCOMP], color[BCOMP]);
-    y=FLIP(y);
-    if (mask) {
-	for (i=0; i<n; i++)
-	    if (mask[i])
-		SetPixel(pwc->hDC, x+i, y, colorref);
-    }
-    else
-	for (i=0; i<n; i++)
-	    SetPixel(pwc->hDC, x+i, y, colorref);
-
-}
-
-/* Write an array of RGBA pixels with a boolean mask. */
-static void write_rgba_pixels_front(const struct gl_context *ctx, 
-				     struct gl_renderbuffer *rb,
-				     GLuint n, 
-				     const GLint x[], const GLint y[],
-				     const GLubyte rgba[][4], 
-				     const GLubyte mask[] )
-{
-    GLuint i;
-    WMesaContext pwc = wmesa_context(ctx);
-    (void) ctx;
-    for (i=0; i<n; i++)
-	if (mask[i])
-	    SetPixel(pwc->hDC, x[i], FLIP(y[i]), 
-		     RGB(rgba[i][RCOMP], rgba[i][GCOMP], 
-			 rgba[i][BCOMP]));
-}
-
-
-
-/*
- * Write an array of pixels with a boolean mask.  The current color
- * is used for all pixels.
- */
-static void write_mono_rgba_pixels_front(const struct gl_context *ctx, 
-					  struct gl_renderbuffer *rb,
-					  GLuint n,
-					  const GLint x[], const GLint y[],
-					  const GLchan color[4],
-					  const GLubyte mask[] )
-{
-    GLuint i;
-    WMesaContext pwc = wmesa_context(ctx);
-    COLORREF colorref;
-    (void) ctx;
-    colorref = RGB(color[RCOMP], color[GCOMP], color[BCOMP]);
-    for (i=0; i<n; i++)
-	if (mask[i])
-	    SetPixel(pwc->hDC, x[i], FLIP(y[i]), colorref);
-}
-
-/* Read a horizontal span of color pixels. */
-static void read_rgba_span_front(const struct gl_context *ctx, 
-				  struct gl_renderbuffer *rb,
-				  GLuint n, GLint x, GLint y,
-				  GLubyte rgba[][4] )
-{
-    WMesaContext pwc = wmesa_context(ctx);
-    GLuint i;
-    COLORREF Color;
-    y = FLIP(y);
-    for (i=0; i<n; i++) {
-	Color = GetPixel(pwc->hDC, x+i, y);
-	rgba[i][RCOMP] = GetRValue(Color);
-	rgba[i][GCOMP] = GetGValue(Color);
-	rgba[i][BCOMP] = GetBValue(Color);
-	rgba[i][ACOMP] = 255;
-    }
-}
-
-
-/* Read an array of color pixels. */
-static void read_rgba_pixels_front(const struct gl_context *ctx, 
-				    struct gl_renderbuffer *rb,
-				    GLuint n, const GLint x[], const GLint y[],
-				    GLubyte rgba[][4])
-{
-    WMesaContext pwc = wmesa_context(ctx);
-    GLuint i;
-    COLORREF Color;
-    for (i=0; i<n; i++) {
-        GLint y2 = FLIP(y[i]);
-        Color = GetPixel(pwc->hDC, x[i], y2);
-        rgba[i][RCOMP] = GetRValue(Color);
-        rgba[i][GCOMP] = GetGValue(Color);
-        rgba[i][BCOMP] = GetBValue(Color);
-        rgba[i][ACOMP] = 255;
-    }
-}
-
-/*********************************************************************/
-
-/* DOUBLE BUFFER 32-bit */
-
-#define WMSETPIXEL32(pwc, y, x, r, g, b) { \
-LPDWORD lpdw = ((LPDWORD)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (x)); \
-*lpdw = BGR32((r),(g),(b)); }
-
-
-
-/* Write a horizontal span of RGBA color pixels with a boolean mask. */
-static void write_rgba_span_32(const struct gl_context *ctx, 
-			       struct gl_renderbuffer *rb, 
-			       GLuint n, GLint x, GLint y,
-			       const GLubyte rgba[][4], 
-			       const GLubyte mask[] )
-{
-    WMesaContext pwc = wmesa_context(ctx);
-    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
-    GLuint i;
-    LPDWORD lpdw;
-
-    (void) ctx;
-    
-    y=FLIP(y);
-    lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
-    if (mask) {
-	for (i=0; i<n; i++)
-	    if (mask[i])
-                lpdw[i] = BGR32(rgba[i][RCOMP], rgba[i][GCOMP], 
-				rgba[i][BCOMP]);
-    }
-    else {
-	for (i=0; i<n; i++)
-                *lpdw++ = BGR32(rgba[i][RCOMP], rgba[i][GCOMP], 
-				rgba[i][BCOMP]);
-    }
-}
-
-
-/* Write a horizontal span of RGB color pixels with a boolean mask. */
-static void write_rgb_span_32(const struct gl_context *ctx, 
-			      struct gl_renderbuffer *rb, 
-			      GLuint n, GLint x, GLint y,
-			      const GLubyte rgb[][3], 
-			      const GLubyte mask[] )
-{
-    WMesaContext pwc = wmesa_context(ctx);
-    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
-    GLuint i;
-    LPDWORD lpdw;
-
-    (void) ctx;
-    
-    y=FLIP(y);
-    lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
-    if (mask) {
-	for (i=0; i<n; i++)
-	    if (mask[i])
-                lpdw[i] = BGR32(rgb[i][RCOMP], rgb[i][GCOMP], 
-				rgb[i][BCOMP]);
-    }
-    else {
-	for (i=0; i<n; i++)
-                *lpdw++ = BGR32(rgb[i][RCOMP], rgb[i][GCOMP], 
-				rgb[i][BCOMP]);
-    }
-}
-
-/*
- * Write a horizontal span of pixels with a boolean mask.  The current color
- * is used for all pixels.
- */
-static void write_mono_rgba_span_32(const struct gl_context *ctx, 
-				    struct gl_renderbuffer *rb,
-				    GLuint n, GLint x, GLint y,
-				    const GLchan color[4], 
-				    const GLubyte mask[])
-{
-    LPDWORD lpdw;
-    DWORD pixel;
-    GLuint i;
-    WMesaContext pwc = wmesa_context(ctx);
-    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
-    lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
-    y=FLIP(y);
-    pixel = BGR32(color[RCOMP], color[GCOMP], color[BCOMP]);
-    if (mask) {
-	for (i=0; i<n; i++)
-	    if (mask[i])
-                lpdw[i] = pixel;
-    }
-    else
-	for (i=0; i<n; i++)
-                *lpdw++ = pixel;
-
-}
-
-/* Write an array of RGBA pixels with a boolean mask. */
-static void write_rgba_pixels_32(const struct gl_context *ctx, 
-				 struct gl_renderbuffer *rb,
-				 GLuint n, const GLint x[], const GLint y[],
-				 const GLubyte rgba[][4], 
-				 const GLubyte mask[])
-{
-    GLuint i;
-    WMesaContext pwc = wmesa_context(ctx);
-    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
-    for (i=0; i<n; i++)
-	if (mask[i])
-	    WMSETPIXEL32(pwfb, FLIP(y[i]), x[i],
-			 rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
-}
-
-/*
- * Write an array of pixels with a boolean mask.  The current color
- * is used for all pixels.
- */
-static void write_mono_rgba_pixels_32(const struct gl_context *ctx, 
-				      struct gl_renderbuffer *rb,
-				      GLuint n,
-				      const GLint x[], const GLint y[],
-				      const GLchan color[4],
-				      const GLubyte mask[])
-{
-    GLuint i;
-    WMesaContext pwc = wmesa_context(ctx);
-    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
-    for (i=0; i<n; i++)
-	if (mask[i])
-	    WMSETPIXEL32(pwfb, FLIP(y[i]),x[i],color[RCOMP],
-			 color[GCOMP], color[BCOMP]);
-}
-
-/* Read a horizontal span of color pixels. */
-static void read_rgba_span_32(const struct gl_context *ctx, 
-			      struct gl_renderbuffer *rb,
-			      GLuint n, GLint x, GLint y,
-			      GLubyte rgba[][4] )
-{
-    GLuint i;
-    DWORD pixel;
-    LPDWORD lpdw;
-    WMesaContext pwc = wmesa_context(ctx);
-    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
-    
-    y = FLIP(y);
-    lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
-    for (i=0; i<n; i++) {
-	pixel = lpdw[i];
-	rgba[i][RCOMP] = (GLubyte)((pixel & 0x00ff0000) >> 16);
-	rgba[i][GCOMP] = (GLubyte)((pixel & 0x0000ff00) >> 8);
-	rgba[i][BCOMP] = (GLubyte)(pixel & 0x000000ff);
-	rgba[i][ACOMP] = 255;
-    }
-}
-
-
-/* Read an array of color pixels. */
-static void read_rgba_pixels_32(const struct gl_context *ctx, 
-				struct gl_renderbuffer *rb,
-				GLuint n, const GLint x[], const GLint y[],
-				GLubyte rgba[][4])
-{
-    GLuint i;
-    DWORD pixel;
-    LPDWORD lpdw;
-    WMesaContext pwc = wmesa_context(ctx);
-    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
-
-    for (i=0; i<n; i++) {
-	GLint y2 = FLIP(y[i]);
-	lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y2)) + x[i];
-	pixel = *lpdw;
-	rgba[i][RCOMP] = (GLubyte)((pixel & 0x00ff0000) >> 16);
-	rgba[i][GCOMP] = (GLubyte)((pixel & 0x0000ff00) >> 8);
-	rgba[i][BCOMP] = (GLubyte)(pixel & 0x000000ff);
-	rgba[i][ACOMP] = 255;
-  }
-}
-
-
-/*********************************************************************/
-
-/* DOUBLE BUFFER 24-bit */
-
-#define WMSETPIXEL24(pwc, y, x, r, g, b) { \
-LPBYTE lpb = ((LPBYTE)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (3 * x)); \
-lpb[0] = (b); \
-lpb[1] = (g); \
-lpb[2] = (r); }
-
-/* Write a horizontal span of RGBA color pixels with a boolean mask. */
-static void write_rgba_span_24(const struct gl_context *ctx, 
-			       struct gl_renderbuffer *rb, 
-			       GLuint n, GLint x, GLint y,
-			       const GLubyte rgba[][4], 
-			       const GLubyte mask[] )
-{
-    WMesaContext pwc = wmesa_context(ctx);
-    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
-    GLuint i;
-    LPBYTE lpb;
-
-    (void) ctx;
-    
-    y=FLIP(y);
-    lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y)) + (3 * x);
-    if (mask) {
-	for (i=0; i<n; i++)
-	    if (mask[i]) {
-                lpb[3*i] = rgba[i][BCOMP];
-                lpb[3*i+1] = rgba[i][GCOMP];
-                lpb[3*i+2] = rgba[i][RCOMP];
-	    }
-    }
-    else {
-	    for (i=0; i<n; i++) {
-            *lpb++ = rgba[i][BCOMP];
-            *lpb++ = rgba[i][GCOMP];
-            *lpb++ = rgba[i][RCOMP];
-	    }
-    }
-}
-
-
-/* Write a horizontal span of RGB color pixels with a boolean mask. */
-static void write_rgb_span_24(const struct gl_context *ctx, 
-			      struct gl_renderbuffer *rb, 
-			      GLuint n, GLint x, GLint y,
-			      const GLubyte rgb[][3], 
-			      const GLubyte mask[] )
-{
-    WMesaContext pwc = wmesa_context(ctx);
-    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
-    GLuint i;
-    LPBYTE lpb;
-
-    (void) ctx;
-    
-    y=FLIP(y);
-    lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y)) + (3 * x);
-    if (mask) {
-	for (i=0; i<n; i++)
-	    if (mask[i]) {
-            lpb[3*i] = rgb[i][BCOMP];
-            lpb[3*i+1] = rgb[i][GCOMP];
-            lpb[3*i+2] = rgb[i][RCOMP];
-	    }
-    }
-    else {
-    	for (i=0; i<n; i++) {
-    		*lpb++ = rgb[i][BCOMP];
-    		*lpb++ = rgb[i][GCOMP];
-    		*lpb++ = rgb[i][RCOMP];
-    	}
-    }
-}
-
-/*
- * Write a horizontal span of pixels with a boolean mask.  The current color
- * is used for all pixels.
- */
-static void write_mono_rgba_span_24(const struct gl_context *ctx, 
-				    struct gl_renderbuffer *rb,
-				    GLuint n, GLint x, GLint y,
-				    const GLchan color[4], 
-				    const GLubyte mask[])
-{
-    LPBYTE lpb;
-    GLuint i;
-    WMesaContext pwc = wmesa_context(ctx);
-    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
-    lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y)) + (3 * x);
-    y=FLIP(y);
-    if (mask) {
-	for (i=0; i<n; i++)
-	    if (mask[i]) {
-	    	lpb[3*i] = color[BCOMP];
-	    	lpb[3*i+1] = color[GCOMP];
-	    	lpb[3*i+2] = color[RCOMP];
-	    }
-    }
-    else
-	for (i=0; i<n; i++) {
-		*lpb++ = color[BCOMP];
-		*lpb++ = color[GCOMP];
-		*lpb++ = color[RCOMP];		
-	}
-}
-
-/* Write an array of RGBA pixels with a boolean mask. */
-static void write_rgba_pixels_24(const struct gl_context *ctx, 
-				 struct gl_renderbuffer *rb,
-				 GLuint n, const GLint x[], const GLint y[],
-				 const GLubyte rgba[][4], 
-				 const GLubyte mask[])
-{
-    GLuint i;
-    WMesaContext pwc = wmesa_context(ctx);
-    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
-    for (i=0; i<n; i++)
-	if (mask[i])
-	    WMSETPIXEL24(pwfb, FLIP(y[i]), x[i],
-			 rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
-}
-
-/*
- * Write an array of pixels with a boolean mask.  The current color
- * is used for all pixels.
- */
-static void write_mono_rgba_pixels_24(const struct gl_context *ctx, 
-				      struct gl_renderbuffer *rb,
-				      GLuint n,
-				      const GLint x[], const GLint y[],
-				      const GLchan color[4],
-				      const GLubyte mask[])
-{
-    GLuint i;
-    WMesaContext pwc = wmesa_context(ctx);
-    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
-    for (i=0; i<n; i++)
-	if (mask[i])
-	    WMSETPIXEL24(pwfb, FLIP(y[i]),x[i],color[RCOMP],
-			 color[GCOMP], color[BCOMP]);
-}
-
-/* Read a horizontal span of color pixels. */
-static void read_rgba_span_24(const struct gl_context *ctx, 
-			      struct gl_renderbuffer *rb,
-			      GLuint n, GLint x, GLint y,
-			      GLubyte rgba[][4] )
-{
-    GLuint i;
-    LPBYTE lpb;
-    WMesaContext pwc = wmesa_context(ctx);
-    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
-    
-    y = FLIP(y);
-    lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y)) + (3 * x);
-    for (i=0; i<n; i++) {
-	rgba[i][RCOMP] = lpb[3*i+2];
-	rgba[i][GCOMP] = lpb[3*i+1];
-	rgba[i][BCOMP] = lpb[3*i];
-	rgba[i][ACOMP] = 255;
-    }
-}
-
-
-/* Read an array of color pixels. */
-static void read_rgba_pixels_24(const struct gl_context *ctx, 
-				struct gl_renderbuffer *rb,
-				GLuint n, const GLint x[], const GLint y[],
-				GLubyte rgba[][4])
-{
-    GLuint i;
-    LPBYTE lpb;
-    WMesaContext pwc = wmesa_context(ctx);
-    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
-
-    for (i=0; i<n; i++) {
-	GLint y2 = FLIP(y[i]);
-	lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y2)) + (3 * x[i]);
-	rgba[i][RCOMP] = lpb[3*i+2];
-	rgba[i][GCOMP] = lpb[3*i+1];
-	rgba[i][BCOMP] = lpb[3*i];
-	rgba[i][ACOMP] = 255;
-  }
-}
-
-
-/*********************************************************************/
-
-/* DOUBLE BUFFER 16-bit */
-
-#define WMSETPIXEL16(pwc, y, x, r, g, b) { \
-LPWORD lpw = ((LPWORD)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (x)); \
-*lpw = BGR16((r),(g),(b)); }
-
-
-
-/* Write a horizontal span of RGBA color pixels with a boolean mask. */
-static void write_rgba_span_16(const struct gl_context *ctx, 
-			       struct gl_renderbuffer *rb, 
-			       GLuint n, GLint x, GLint y,
-			       const GLubyte rgba[][4], 
-			       const GLubyte mask[] )
-{
-    WMesaContext pwc = wmesa_context(ctx);
-    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
-    GLuint i;
-    LPWORD lpw;
-
-    (void) ctx;
-    
-    y=FLIP(y);
-    lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
-    if (mask) {
-	for (i=0; i<n; i++)
-	    if (mask[i])
-                lpw[i] = BGR16(rgba[i][RCOMP], rgba[i][GCOMP], 
-			       rgba[i][BCOMP]);
-    }
-    else {
-	for (i=0; i<n; i++)
-                *lpw++ = BGR16(rgba[i][RCOMP], rgba[i][GCOMP], 
-			       rgba[i][BCOMP]);
-    }
-}
-
-
-/* Write a horizontal span of RGB color pixels with a boolean mask. */
-static void write_rgb_span_16(const struct gl_context *ctx, 
-			      struct gl_renderbuffer *rb, 
-			      GLuint n, GLint x, GLint y,
-			      const GLubyte rgb[][3], 
-			      const GLubyte mask[] )
-{
-    WMesaContext pwc = wmesa_context(ctx);
-    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
-    GLuint i;
-    LPWORD lpw;
-
-    (void) ctx;
-    
-    y=FLIP(y);
-    lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
-    if (mask) {
-	for (i=0; i<n; i++)
-	    if (mask[i])
-                lpw[i] = BGR16(rgb[i][RCOMP], rgb[i][GCOMP], 
-			       rgb[i][BCOMP]);
-    }
-    else {
-	for (i=0; i<n; i++)
-                *lpw++ = BGR16(rgb[i][RCOMP], rgb[i][GCOMP], 
-			       rgb[i][BCOMP]);
-    }
-}
-
-/*
- * Write a horizontal span of pixels with a boolean mask.  The current color
- * is used for all pixels.
- */
-static void write_mono_rgba_span_16(const struct gl_context *ctx, 
-				    struct gl_renderbuffer *rb,
-				    GLuint n, GLint x, GLint y,
-				    const GLchan color[4], 
-				    const GLubyte mask[])
-{
-    LPWORD lpw;
-    WORD pixel;
-    GLuint i;
-    WMesaContext pwc = wmesa_context(ctx);
-    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
-    (void) ctx;
-    lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
-    y=FLIP(y);
-    pixel = BGR16(color[RCOMP], color[GCOMP], color[BCOMP]);
-    if (mask) {
-	for (i=0; i<n; i++)
-	    if (mask[i])
-                lpw[i] = pixel;
-    }
-    else
-	for (i=0; i<n; i++)
-                *lpw++ = pixel;
-
-}
-
-/* Write an array of RGBA pixels with a boolean mask. */
-static void write_rgba_pixels_16(const struct gl_context *ctx, 
-				 struct gl_renderbuffer *rb,
-				 GLuint n, const GLint x[], const GLint y[],
-				 const GLubyte rgba[][4], 
-				 const GLubyte mask[])
-{
-    GLuint i;
-    WMesaContext pwc = wmesa_context(ctx);
-    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
-    (void) ctx;
-    for (i=0; i<n; i++)
-	if (mask[i])
-	    WMSETPIXEL16(pwfb, FLIP(y[i]), x[i],
-			 rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
-}
-
-/*
- * Write an array of pixels with a boolean mask.  The current color
- * is used for all pixels.
- */
-static void write_mono_rgba_pixels_16(const struct gl_context *ctx, 
-				      struct gl_renderbuffer *rb,
-				      GLuint n,
-				      const GLint x[], const GLint y[],
-				      const GLchan color[4],
-				      const GLubyte mask[])
-{
-    GLuint i;
-    WMesaContext pwc = wmesa_context(ctx);
-    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
-    (void) ctx;
-    for (i=0; i<n; i++)
-	if (mask[i])
-	    WMSETPIXEL16(pwfb, FLIP(y[i]),x[i],color[RCOMP],
-			 color[GCOMP], color[BCOMP]);
-}
-
-/* Read a horizontal span of color pixels. */
-static void read_rgba_span_16(const struct gl_context *ctx, 
-			      struct gl_renderbuffer *rb,
-			      GLuint n, GLint x, GLint y,
-			      GLubyte rgba[][4] )
-{
-    GLuint i, pixel;
-    LPWORD lpw;
-    WMesaContext pwc = wmesa_context(ctx);
-    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
-    
-    y = FLIP(y);
-    lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
-    for (i=0; i<n; i++) {
-	pixel = lpw[i];
-	/* Windows uses 5,5,5 for 16-bit */
-	rgba[i][RCOMP] = (pixel & 0x7c00) >> 7;
-	rgba[i][GCOMP] = (pixel & 0x03e0) >> 2;
-	rgba[i][BCOMP] = (pixel & 0x001f) << 3;
-	rgba[i][ACOMP] = 255;
-    }
-}
-
-
-/* Read an array of color pixels. */
-static void read_rgba_pixels_16(const struct gl_context *ctx, 
-				struct gl_renderbuffer *rb,
-				GLuint n, const GLint x[], const GLint y[],
-				GLubyte rgba[][4])
-{
-    GLuint i, pixel;
-    LPWORD lpw;
-    WMesaContext pwc = wmesa_context(ctx);
-    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
-
-    for (i=0; i<n; i++) {
-	GLint y2 = FLIP(y[i]);
-	lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y2)) + x[i];
-	pixel = *lpw;
-	/* Windows uses 5,5,5 for 16-bit */
-	rgba[i][RCOMP] = (pixel & 0x7c00) >> 7;
-	rgba[i][GCOMP] = (pixel & 0x03e0) >> 2;
-	rgba[i][BCOMP] = (pixel & 0x001f) << 3;
-	rgba[i][ACOMP] = 255;
-  }
-}
-
-
-
-
-/**********************************************************************/
-/*****                   BUFFER Functions                         *****/
-/**********************************************************************/
-
-
-
-
-static void
-wmesa_delete_renderbuffer(struct gl_renderbuffer *rb)
-{
-    free(rb);
-}
-
-
-/**
- * This is called by Mesa whenever it determines that the window size
- * has changed.  Do whatever's needed to cope with that.
- */
-static GLboolean
-wmesa_renderbuffer_storage(struct gl_context *ctx, 
-			   struct gl_renderbuffer *rb,
-			   GLenum internalFormat, 
-			   GLuint width, 
-			   GLuint height)
-{
-    rb->Width = width;
-    rb->Height = height;
-    return GL_TRUE;
-}
-
-
-/**
- * Plug in the Get/PutRow/Values functions for a renderbuffer depending
- * on if we're drawing to the front or back color buffer.
- */
-void wmesa_set_renderbuffer_funcs(struct gl_renderbuffer *rb, int pixelformat,
-                                  int cColorBits, int double_buffer)
-{
-    if (double_buffer) {
-        /* back buffer */
-	/* Picking the correct span functions is important because
-	 * the DIB was allocated with the indicated depth. */
-	switch(pixelformat) {
-	case PF_5R6G5B:
-	    rb->PutRow = write_rgba_span_16;
-	    rb->PutRowRGB = write_rgb_span_16;
-	    rb->PutMonoRow = write_mono_rgba_span_16;
-	    rb->PutValues = write_rgba_pixels_16;
-	    rb->PutMonoValues = write_mono_rgba_pixels_16;
-	    rb->GetRow = read_rgba_span_16;
-	    rb->GetValues = read_rgba_pixels_16;
-	    break;
-	case PF_8R8G8B:
-		if (cColorBits == 24)
-		{
-		    rb->PutRow = write_rgba_span_24;
-		    rb->PutRowRGB = write_rgb_span_24;
-		    rb->PutMonoRow = write_mono_rgba_span_24;
-		    rb->PutValues = write_rgba_pixels_24;
-		    rb->PutMonoValues = write_mono_rgba_pixels_24;
-		    rb->GetRow = read_rgba_span_24;
-		    rb->GetValues = read_rgba_pixels_24;
-		}
-		else
-		{
-	        rb->PutRow = write_rgba_span_32;
-	        rb->PutRowRGB = write_rgb_span_32;
-	        rb->PutMonoRow = write_mono_rgba_span_32;
-	        rb->PutValues = write_rgba_pixels_32;
-	        rb->PutMonoValues = write_mono_rgba_pixels_32;
-	        rb->GetRow = read_rgba_span_32;
-	        rb->GetValues = read_rgba_pixels_32;
-		}
-	    break;
-	default:
-	    break;
-	}
-    }
-    else {
-        /* front buffer (actual Windows window) */
-	rb->PutRow = write_rgba_span_front;
-	rb->PutRowRGB = write_rgb_span_front;
-	rb->PutMonoRow = write_mono_rgba_span_front;
-	rb->PutValues = write_rgba_pixels_front;
-	rb->PutMonoValues = write_mono_rgba_pixels_front;
-	rb->GetRow = read_rgba_span_front;
-	rb->GetValues = read_rgba_pixels_front;
-    }
-}
-
-/**
- * Called by ctx->Driver.ResizeBuffers()
- * Resize the front/back colorbuffers to match the latest window size.
- */
-static void
-wmesa_resize_buffers(struct gl_context *ctx, struct gl_framebuffer *buffer,
-                     GLuint width, GLuint height)
-{
-    WMesaContext pwc = wmesa_context(ctx);
-    WMesaFramebuffer pwfb = wmesa_framebuffer(buffer);
-
-    if (pwfb->Base.Width != width || pwfb->Base.Height != height) {
-	/* Realloc back buffer */
-	if (ctx->Visual.doubleBufferMode == 1) {
-	    wmDeleteBackingStore(pwfb);
-	    wmCreateBackingStore(pwfb, width, height);
-	}
-    }
-    _mesa_resize_framebuffer(ctx, buffer, width, height);
-}
-
-
-/**
- * Called by glViewport.
- * This is a good time for us to poll the current window size and adjust
- * our renderbuffers to match the current window size.
- * Remember, we have no opportunity to respond to conventional
- * resize events since the driver has no event loop.
- * Thus, we poll.
- * MakeCurrent also ends up making a call here, so that ensures
- * we get the viewport set correctly, even if the app does not call
- * glViewport and relies on the defaults.
- */
-static void wmesa_viewport(struct gl_context *ctx, 
-			   GLint x, GLint y, 
-			   GLsizei width, GLsizei height)
-{
-    WMesaContext pwc = wmesa_context(ctx);
-    GLuint new_width, new_height;
-
-    wmesa_get_buffer_size(ctx->WinSysDrawBuffer, &new_width, &new_height);
-
-    /**
-     * Resize buffers if the window size changed.
-     */
-    wmesa_resize_buffers(ctx, ctx->WinSysDrawBuffer, new_width, new_height);
-    ctx->NewState |= _NEW_BUFFERS;  /* to update scissor / window bounds */
-}
-
-
-
-
-/**
- * Called when the driver should update it's state, based on the new_state
- * flags.
- */
-static void wmesa_update_state(struct gl_context *ctx, GLuint new_state)
-{
-    _swrast_InvalidateState(ctx, new_state);
-    _swsetup_InvalidateState(ctx, new_state);
-    _vbo_InvalidateState(ctx, new_state);
-    _tnl_InvalidateState(ctx, new_state);
-
-    /* TODO - This code is not complete yet because I 
-     * don't know what to do for all state updates.
-     */
-
-    if (new_state & _NEW_BUFFERS) {
-    }
-}
-
-
-
-
-
-/**********************************************************************/
-/*****                   WMESA Functions                          *****/
-/**********************************************************************/
-
-WMesaContext WMesaCreateContext(HDC hDC, 
-				HPALETTE* Pal,
-				GLboolean rgb_flag,
-				GLboolean db_flag,
-				GLboolean alpha_flag)
-{
-    WMesaContext c;
-    struct dd_function_table functions;
-    GLint red_bits, green_bits, blue_bits, alpha_bits;
-    struct gl_context *ctx;
-    struct gl_config *visual;
-
-    (void) Pal;
-    
-    /* Indexed mode not supported */
-    if (!rgb_flag)
-	return NULL;
-
-    /* Allocate wmesa context */
-    c = CALLOC_STRUCT(wmesa_context);
-    if (!c)
-	return NULL;
-
-#if 0
-    /* I do not understand this contributed code */
-    /* Support memory and device contexts */
-    if(WindowFromDC(hDC) != NULL) {
-	c->hDC = GetDC(WindowFromDC(hDC)); /* huh ???? */
-    }
-    else {
-	c->hDC = hDC;
-    }
-#else
-    c->hDC = hDC;
-#endif
-
-    /* Get data for visual */
-    /* Dealing with this is actually a bit of overkill because Mesa will end
-     * up treating all color component size requests less than 8 by using 
-     * a single byte per channel.  In addition, the interface to the span
-     * routines passes colors as an entire byte per channel anyway, so there
-     * is nothing to be saved by telling the visual to be 16 bits if the device
-     * is 16 bits.  That is, Mesa is going to compute colors down to 8 bits per
-     * channel anyway.
-     * But we go through the motions here anyway.
-     */
-    switch (GetDeviceCaps(c->hDC, BITSPIXEL)) {
-    case 16:
-	red_bits = green_bits = blue_bits = 5;
-	alpha_bits = 0;
-	break;
-    default:
-	red_bits = green_bits = blue_bits = 8;
-	alpha_bits = 8;
-	break;
-    }
-    /* Create visual based on flags */
-    visual = _mesa_create_visual(db_flag,    /* db_flag */
-                                 GL_FALSE,   /* stereo */
-                                 red_bits, green_bits, blue_bits, /* color RGB */
-                                 alpha_flag ? alpha_bits : 0, /* color A */
-                                 DEFAULT_SOFTWARE_DEPTH_BITS, /* depth_bits */
-                                 8,          /* stencil_bits */
-                                 16,16,16,   /* accum RGB */
-                                 alpha_flag ? 16 : 0, /* accum A */
-                                 1);         /* num samples */
-    
-    if (!visual) {
-	free(c);
-	return NULL;
-    }
-
-    /* Set up driver functions */
-    _mesa_init_driver_functions(&functions);
-    functions.GetString = wmesa_get_string;
-    functions.UpdateState = wmesa_update_state;
-    functions.GetBufferSize = wmesa_get_buffer_size;
-    functions.Flush = wmesa_flush;
-    functions.Clear = clear;
-    functions.ClearColor = clear_color;
-    functions.ResizeBuffers = wmesa_resize_buffers;
-    functions.Viewport = wmesa_viewport;
-
-    /* initialize the Mesa context data */
-    ctx = &c->gl_ctx;
-    _mesa_initialize_context(ctx, visual, NULL, &functions, (void *)c);
-
-    /* visual no longer needed - it was copied by _mesa_initialize_context() */
-    _mesa_destroy_visual(visual);
-
-    _mesa_enable_sw_extensions(ctx);
-    _mesa_enable_1_3_extensions(ctx);
-    _mesa_enable_1_4_extensions(ctx);
-    _mesa_enable_1_5_extensions(ctx);
-    _mesa_enable_2_0_extensions(ctx);
-    _mesa_enable_2_1_extensions(ctx);
-  
-    _mesa_meta_init(ctx);
-
-    /* Initialize the software rasterizer and helper modules. */
-    if (!_swrast_CreateContext(ctx) ||
-        !_vbo_CreateContext(ctx) ||
-        !_tnl_CreateContext(ctx) ||
-	!_swsetup_CreateContext(ctx)) {
-	_mesa_free_context_data(ctx);
-	free(c);
-	return NULL;
-    }
-    _swsetup_Wakeup(ctx);
-    TNL_CONTEXT(ctx)->Driver.RunPipeline = _tnl_run_pipeline;
-
-    return c;
-}
-
-
-void WMesaDestroyContext( WMesaContext pwc )
-{
-    struct gl_context *ctx = &pwc->gl_ctx;
-    WMesaFramebuffer pwfb;
-    GET_CURRENT_CONTEXT(cur_ctx);
-
-    if (cur_ctx == ctx) {
-        /* unbind current if deleting current context */
-        WMesaMakeCurrent(NULL, NULL);
-    }
-
-    /* clean up frame buffer resources */
-    pwfb = wmesa_lookup_framebuffer(pwc->hDC);
-    if (pwfb) {
-	if (ctx->Visual.doubleBufferMode == 1)
-	    wmDeleteBackingStore(pwfb);
-	wmesa_free_framebuffer(pwc->hDC);
-    }
-
-    /* Release for device, not memory contexts */
-    if (WindowFromDC(pwc->hDC) != NULL)
-    {
-      ReleaseDC(WindowFromDC(pwc->hDC), pwc->hDC);
-    }
-    DeleteObject(pwc->clearPen); 
-    DeleteObject(pwc->clearBrush); 
-    
-    _mesa_meta_free(ctx);
-
-    _swsetup_DestroyContext(ctx);
-    _tnl_DestroyContext(ctx);
-    _vbo_DestroyContext(ctx);
-    _swrast_DestroyContext(ctx);
-    
-    _mesa_free_context_data(ctx);
-    free(pwc);
-}
-
-
-/**
- * Create a new color renderbuffer.
- */
-struct gl_renderbuffer *
-wmesa_new_renderbuffer(void)
-{
-    struct gl_renderbuffer *rb = CALLOC_STRUCT(gl_renderbuffer);
-    if (!rb)
-        return NULL;
-
-    _mesa_init_renderbuffer(rb, (GLuint)0);
-    
-    rb->_BaseFormat = GL_RGBA;
-    rb->InternalFormat = GL_RGBA;
-    rb->DataType = CHAN_TYPE;
-    rb->Delete = wmesa_delete_renderbuffer;
-    rb->AllocStorage = wmesa_renderbuffer_storage;
-    return rb;
-}
-
-
-void WMesaMakeCurrent(WMesaContext c, HDC hdc)
-{
-    WMesaFramebuffer pwfb;
-
-    {
-        /* return if already current */
-        GET_CURRENT_CONTEXT(ctx);
-        WMesaContext pwc = wmesa_context(ctx);
-        if (pwc && c == pwc && pwc->hDC == hdc)
-            return;
-    }
-
-    pwfb = wmesa_lookup_framebuffer(hdc);
-
-    /* Lazy creation of framebuffers */
-    if (c && !pwfb && hdc) {
-        struct gl_renderbuffer *rb;
-        struct gl_config *visual = &c->gl_ctx.Visual;
-        GLuint width, height;
-
-        get_window_size(hdc, &width, &height);
-
-	c->clearPen = CreatePen(PS_SOLID, 1, 0); 
-	c->clearBrush = CreateSolidBrush(0); 
-
-        pwfb = wmesa_new_framebuffer(hdc, visual);
-
-	/* Create back buffer if double buffered */
-	if (visual->doubleBufferMode == 1) {
-	    wmCreateBackingStore(pwfb, width, height);
-	}
-	
-        /* make render buffers */
-        if (visual->doubleBufferMode == 1) {
-            rb = wmesa_new_renderbuffer();
-            _mesa_add_renderbuffer(&pwfb->Base, BUFFER_BACK_LEFT, rb);
-            wmesa_set_renderbuffer_funcs(rb, pwfb->pixelformat, pwfb->cColorBits, 1);
-	}
-        rb = wmesa_new_renderbuffer();
-        _mesa_add_renderbuffer(&pwfb->Base, BUFFER_FRONT_LEFT, rb);
-        wmesa_set_renderbuffer_funcs(rb, pwfb->pixelformat, pwfb->cColorBits, 0);
-
-	/* Let Mesa own the Depth, Stencil, and Accum buffers */
-        _mesa_add_soft_renderbuffers(&pwfb->Base,
-                                     GL_FALSE, /* color */
-                                     visual->depthBits > 0,
-                                     visual->stencilBits > 0,
-                                     visual->accumRedBits > 0,
-                                     visual->alphaBits >0, 
-                                     GL_FALSE);
-    }
-
-    if (c && pwfb)
-	_mesa_make_current(&c->gl_ctx, &pwfb->Base, &pwfb->Base);
-    else
-        _mesa_make_current(NULL, NULL, NULL);
-}
-
-
-void WMesaSwapBuffers( HDC hdc )
-{
-    GET_CURRENT_CONTEXT(ctx);
-    WMesaContext pwc = wmesa_context(ctx);
-    WMesaFramebuffer pwfb = wmesa_lookup_framebuffer(hdc);
-
-    if (!pwfb) {
-        _mesa_problem(NULL, "wmesa: swapbuffers on unknown hdc");
-        return;
-    }
-
-    /* If we're swapping the buffer associated with the current context
-     * we have to flush any pending rendering commands first.
-     */
-    if (pwc->hDC == hdc) {
-	_mesa_notifySwapBuffers(ctx);
-
-	BitBlt(pwfb->hDC, 0, 0, pwfb->Base.Width, pwfb->Base.Height,
-	       pwfb->dib_hDC, 0, 0, SRCCOPY);
-    }
-    else {
-        /* XXX for now only allow swapping current window */
-        _mesa_problem(NULL, "wmesa: can't swap non-current window");
-    }
-}
-
-void WMesaShareLists(WMesaContext ctx_to_share, WMesaContext ctx)
-{
-	_mesa_share_state(&ctx->gl_ctx, &ctx_to_share->gl_ctx);	
-}
-
+/*
+ * Windows (Win32/Win64) device driver for Mesa
+ *
+ */
+
+#include "wmesadef.h"
+#include "colors.h"
+#include <GL/wmesa.h>
+#include <winuser.h>
+#include "context.h"
+#include "extensions.h"
+#include "framebuffer.h"
+#include "renderbuffer.h"
+#include "drivers/common/driverfuncs.h"
+#include "drivers/common/meta.h"
+#include "vbo/vbo.h"
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+
+/* linked list of our Framebuffers (windows) */
+static WMesaFramebuffer FirstFramebuffer = NULL;
+
+
+/**
+ * Create a new WMesaFramebuffer object which will correspond to the
+ * given HDC (Window handle).
+ */
+WMesaFramebuffer
+wmesa_new_framebuffer(HDC hdc, struct gl_config *visual)
+{
+    WMesaFramebuffer pwfb
+        = (WMesaFramebuffer) malloc(sizeof(struct wmesa_framebuffer));
+    if (pwfb) {
+        _mesa_initialize_window_framebuffer(&pwfb->Base, visual);
+        pwfb->hDC = hdc;
+        /* insert at head of list */
+        pwfb->next = FirstFramebuffer;
+        FirstFramebuffer = pwfb;
+    }
+    return pwfb;
+}
+
+/**
+ * Given an hdc, free the corresponding WMesaFramebuffer
+ */
+void
+wmesa_free_framebuffer(HDC hdc)
+{
+    WMesaFramebuffer pwfb, prev;
+    for (pwfb = FirstFramebuffer; pwfb; pwfb = pwfb->next) {
+        if (pwfb->hDC == hdc)
+            break;
+	prev = pwfb;
+    }
+    if (pwfb) {
+        struct gl_framebuffer *fb;
+	if (pwfb == FirstFramebuffer)
+	    FirstFramebuffer = pwfb->next;
+	else
+	    prev->next = pwfb->next;
+        fb = &pwfb->Base;
+        _mesa_reference_framebuffer(&fb, NULL); 
+    }
+}
+
+/**
+ * Given an hdc, return the corresponding WMesaFramebuffer
+ */
+WMesaFramebuffer
+wmesa_lookup_framebuffer(HDC hdc)
+{
+    WMesaFramebuffer pwfb;
+    for (pwfb = FirstFramebuffer; pwfb; pwfb = pwfb->next) {
+        if (pwfb->hDC == hdc)
+            return pwfb;
+    }
+    return NULL;
+}
+
+
+/**
+ * Given a struct gl_framebuffer, return the corresponding WMesaFramebuffer.
+ */
+static WMesaFramebuffer wmesa_framebuffer(struct gl_framebuffer *fb)
+{
+    return (WMesaFramebuffer) fb;
+}
+
+
+/**
+ * Given a struct gl_context, return the corresponding WMesaContext.
+ */
+static WMesaContext wmesa_context(const struct gl_context *ctx)
+{
+    return (WMesaContext) ctx;
+}
+
+
+/*
+ * Every driver should implement a GetString function in order to
+ * return a meaningful GL_RENDERER string.
+ */
+static const GLubyte *wmesa_get_string(struct gl_context *ctx, GLenum name)
+{
+    return (name == GL_RENDERER) ? 
+	(GLubyte *) "Mesa Windows GDI Driver" : NULL;
+}
+
+
+/*
+ * Determine the pixel format based on the pixel size.
+ */
+static void wmSetPixelFormat(WMesaFramebuffer pwfb, HDC hDC)
+{
+    pwfb->cColorBits = GetDeviceCaps(hDC, BITSPIXEL);
+
+    /* Only 16 and 32 bit targets are supported now */
+    assert(pwfb->cColorBits == 0 ||
+	   pwfb->cColorBits == 16 || 
+	   pwfb->cColorBits == 24 || 
+	   pwfb->cColorBits == 32);
+
+    switch(pwfb->cColorBits){
+    case 8:
+	pwfb->pixelformat = PF_INDEX8;
+	break;
+    case 16:
+	pwfb->pixelformat = PF_5R6G5B;
+	break;
+    case 24:
+    case 32:
+	pwfb->pixelformat = PF_8R8G8B;
+	break;
+    default:
+	pwfb->pixelformat = PF_BADFORMAT;
+    }
+}
+
+
+/**
+ * Create DIB for back buffer.
+ * We write into this memory with the span routines and then blit it
+ * to the window on a buffer swap.
+ */
+BOOL wmCreateBackingStore(WMesaFramebuffer pwfb, long lxSize, long lySize)
+{
+    HDC          hdc = pwfb->hDC;
+    LPBITMAPINFO pbmi = &(pwfb->bmi);
+    HDC          hic;
+
+    pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+    pbmi->bmiHeader.biWidth = lxSize;
+    pbmi->bmiHeader.biHeight= -lySize;
+    pbmi->bmiHeader.biPlanes = 1;
+    pbmi->bmiHeader.biBitCount = GetDeviceCaps(pwfb->hDC, BITSPIXEL);
+    pbmi->bmiHeader.biCompression = BI_RGB;
+    pbmi->bmiHeader.biSizeImage = 0;
+    pbmi->bmiHeader.biXPelsPerMeter = 0;
+    pbmi->bmiHeader.biYPelsPerMeter = 0;
+    pbmi->bmiHeader.biClrUsed = 0;
+    pbmi->bmiHeader.biClrImportant = 0;
+    
+    pwfb->cColorBits = pbmi->bmiHeader.biBitCount;
+    pwfb->ScanWidth = (lxSize * (pwfb->cColorBits / 8) + 3) & ~3;
+    
+    hic = CreateIC("display", NULL, NULL, NULL);
+    pwfb->dib_hDC = CreateCompatibleDC(hic);
+    
+    pwfb->hbmDIB = CreateDIBSection(hic,
+				   &pwfb->bmi,
+				   DIB_RGB_COLORS,
+				   (void **)&(pwfb->pbPixels),
+				   0,
+				   0);
+    pwfb->hOldBitmap = SelectObject(pwfb->dib_hDC, pwfb->hbmDIB);
+    
+    DeleteDC(hic);
+
+    wmSetPixelFormat(pwfb, pwfb->hDC);
+    return TRUE;
+}
+
+
+static wmDeleteBackingStore(WMesaFramebuffer pwfb)
+{
+    if (pwfb->hbmDIB) {
+	SelectObject(pwfb->dib_hDC, pwfb->hOldBitmap);
+	DeleteDC(pwfb->dib_hDC);
+	DeleteObject(pwfb->hbmDIB);
+    }
+}
+
+
+/**
+ * Find the width and height of the window named by hdc.
+ */
+static void
+get_window_size(HDC hdc, GLuint *width, GLuint *height)
+{
+    if (WindowFromDC(hdc)) {
+        RECT rect;
+        GetClientRect(WindowFromDC(hdc), &rect);
+        *width = rect.right - rect.left;
+        *height = rect.bottom - rect.top;
+    }
+    else { /* Memory context */
+        /* From contributed code - use the size of the desktop
+         * for the size of a memory context (?) */
+        *width = GetDeviceCaps(hdc, HORZRES);
+        *height = GetDeviceCaps(hdc, VERTRES);
+    }
+}
+
+
+static void
+wmesa_get_buffer_size(struct gl_framebuffer *buffer, GLuint *width, GLuint *height)
+{
+    WMesaFramebuffer pwfb = wmesa_framebuffer(buffer);
+    get_window_size(pwfb->hDC, width, height);
+}
+
+
+static void wmesa_flush(struct gl_context *ctx)
+{
+    WMesaContext pwc = wmesa_context(ctx);
+    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->WinSysDrawBuffer);
+
+    if (ctx->Visual.doubleBufferMode == 1) {
+	BitBlt(pwfb->hDC, 0, 0, pwfb->Base.Width, pwfb->Base.Height,
+	       pwfb->dib_hDC, 0, 0, SRCCOPY);
+    }
+    else {
+	/* Do nothing for single buffer */
+    }
+}
+
+
+/**********************************************************************/
+/*****                   CLEAR Functions                          *****/
+/**********************************************************************/
+
+/* If we do not implement these, Mesa clears the buffers via the pixel
+ * span writing interface, which is very slow for a clear operation.
+ */
+
+/*
+ * Set the color used to clear the color buffer.
+ */
+static void clear_color(struct gl_context *ctx, const GLfloat color[4])
+{
+    WMesaContext pwc = wmesa_context(ctx);
+    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+    GLubyte col[3];
+    UINT    bytesPerPixel = pwfb->cColorBits / 8; 
+
+    CLAMPED_FLOAT_TO_UBYTE(col[0], color[0]);
+    CLAMPED_FLOAT_TO_UBYTE(col[1], color[1]);
+    CLAMPED_FLOAT_TO_UBYTE(col[2], color[2]);
+    pwc->clearColorRef = RGB(col[0], col[1], col[2]);
+    DeleteObject(pwc->clearPen);
+    DeleteObject(pwc->clearBrush);
+    pwc->clearPen = CreatePen(PS_SOLID, 1, pwc->clearColorRef); 
+    pwc->clearBrush = CreateSolidBrush(pwc->clearColorRef); 
+}
+
+
+/* 
+ * Clear the specified region of the color buffer using the clear color 
+ * or index as specified by one of the two functions above. 
+ * 
+ * This procedure clears either the front and/or the back COLOR buffers. 
+ * Only the "left" buffer is cleared since we are not stereo. 
+ * Clearing of the other non-color buffers is left to the swrast. 
+ */ 
+
+static void clear(struct gl_context *ctx, GLbitfield mask)
+{
+#define FLIP(Y)  (ctx->DrawBuffer->Height - (Y) - 1)
+    const GLint x = ctx->DrawBuffer->_Xmin;
+    const GLint y = ctx->DrawBuffer->_Ymin;
+    const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
+    const GLint width  = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
+
+    WMesaContext pwc = wmesa_context(ctx);
+    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+    int done = 0;
+
+    /* Let swrast do all the work if the masks are not set to
+     * clear all channels. */
+    if (!ctx->Color.ColorMask[0][0] ||
+	!ctx->Color.ColorMask[0][1] ||
+	!ctx->Color.ColorMask[0][2] ||
+	!ctx->Color.ColorMask[0][3]) {
+	_swrast_Clear(ctx, mask);
+	return;
+    }
+
+    /* Back buffer */
+    if (mask & BUFFER_BIT_BACK_LEFT) { 
+	
+	int     i, rowSize; 
+	UINT    bytesPerPixel = pwfb->cColorBits / 8; 
+	LPBYTE  lpb, clearRow;
+	LPWORD  lpw;
+	BYTE    bColor; 
+	WORD    wColor; 
+	BYTE    r, g, b; 
+	DWORD   dwColor; 
+	LPDWORD lpdw; 
+	
+	/* Try for a fast clear - clearing entire buffer with a single
+	 * byte value. */
+	if (width == ctx->DrawBuffer->Width &&
+            height == ctx->DrawBuffer->Height) { /* entire buffer */
+	    /* Now check for an easy clear value */
+	    switch (bytesPerPixel) {
+	    case 1:
+		bColor = BGR8(GetRValue(pwc->clearColorRef), 
+			      GetGValue(pwc->clearColorRef), 
+			      GetBValue(pwc->clearColorRef));
+		memset(pwfb->pbPixels, bColor, 
+		       pwfb->ScanWidth * height);
+		done = 1;
+		break;
+	    case 2:
+		wColor = BGR16(GetRValue(pwc->clearColorRef), 
+			       GetGValue(pwc->clearColorRef), 
+			       GetBValue(pwc->clearColorRef)); 
+		if (((wColor >> 8) & 0xff) == (wColor & 0xff)) {
+		    memset(pwfb->pbPixels, wColor & 0xff, 
+			   pwfb->ScanWidth * height);
+		    done = 1;
+		}
+		break;
+	    case 3:
+		/* fall through */
+	    case 4:
+		if (GetRValue(pwc->clearColorRef) == 
+		    GetGValue(pwc->clearColorRef) &&
+		    GetRValue(pwc->clearColorRef) == 
+		    GetBValue(pwc->clearColorRef)) {
+		    memset(pwfb->pbPixels, 
+			   GetRValue(pwc->clearColorRef), 
+			   pwfb->ScanWidth * height);
+		    done = 1;
+		}
+		break;
+	    default:
+		break;
+	    }
+	} /* all */
+
+	if (!done) {
+	    /* Need to clear a row at a time.  Begin by setting the first
+	     * row in the area to be cleared to the clear color. */
+	    
+	    clearRow = pwfb->pbPixels + 
+		pwfb->ScanWidth * FLIP(y) +
+		bytesPerPixel * x; 
+	    switch (bytesPerPixel) {
+	    case 1:
+		lpb = clearRow;
+		bColor = BGR8(GetRValue(pwc->clearColorRef), 
+			      GetGValue(pwc->clearColorRef), 
+			      GetBValue(pwc->clearColorRef));
+		memset(lpb, bColor, width);
+		break;
+	    case 2:
+		lpw = (LPWORD)clearRow;
+		wColor = BGR16(GetRValue(pwc->clearColorRef), 
+			       GetGValue(pwc->clearColorRef), 
+			       GetBValue(pwc->clearColorRef)); 
+		for (i=0; i<width; i++)
+		    *lpw++ = wColor;
+		break;
+	    case 3: 
+		lpb = clearRow;
+		r = GetRValue(pwc->clearColorRef); 
+		g = GetGValue(pwc->clearColorRef); 
+		b = GetBValue(pwc->clearColorRef); 
+		for (i=0; i<width; i++) {
+		    *lpb++ = b; 
+		    *lpb++ = g; 
+		    *lpb++ = r; 
+		} 
+		break;
+	    case 4: 
+		lpdw = (LPDWORD)clearRow; 
+		dwColor = BGR32(GetRValue(pwc->clearColorRef), 
+				GetGValue(pwc->clearColorRef), 
+				GetBValue(pwc->clearColorRef)); 
+		for (i=0; i<width; i++)
+		    *lpdw++ = dwColor;
+		break;
+	    default:
+		break;
+	    } /* switch */
+	    
+	    /* copy cleared row to other rows in buffer */
+	    lpb = clearRow - pwfb->ScanWidth;
+	    rowSize = width * bytesPerPixel;
+	    for (i=1; i<height; i++) { 
+		memcpy(lpb, clearRow, rowSize); 
+		lpb -= pwfb->ScanWidth; 
+	    } 
+	} /* not done */
+	mask &= ~BUFFER_BIT_BACK_LEFT;
+    } /* back buffer */ 
+
+    /* front buffer */
+    if (mask & BUFFER_BIT_FRONT_LEFT) { 
+	HDC DC = pwc->hDC; 
+	HPEN Old_Pen = SelectObject(DC, pwc->clearPen); 
+	HBRUSH Old_Brush = SelectObject(DC, pwc->clearBrush);
+	Rectangle(DC,
+		  x,
+		  FLIP(y) + 1,
+		  x + width + 1,
+		  FLIP(y) - height + 1);
+	SelectObject(DC, Old_Pen); 
+	SelectObject(DC, Old_Brush); 
+	mask &= ~BUFFER_BIT_FRONT_LEFT;
+    } /* front buffer */ 
+    
+    /* Call swrast if there is anything left to clear (like DEPTH) */ 
+    if (mask) 
+	_swrast_Clear(ctx, mask);
+  
+#undef FLIP
+} 
+
+
+/**********************************************************************/
+/*****                   PIXEL Functions                          *****/
+/**********************************************************************/
+
+#define FLIP(Y)  (rb->Height - (Y) - 1)
+
+
+/**
+ ** Front Buffer reading/writing
+ ** These are slow, but work with all non-indexed visual types.
+ **/
+
+/* Write a horizontal span of RGBA color pixels with a boolean mask. */
+static void write_rgba_span_front(const struct gl_context *ctx, 
+				   struct gl_renderbuffer *rb, 
+				   GLuint n, GLint x, GLint y,
+				   const GLubyte rgba[][4], 
+				   const GLubyte mask[] )
+{
+   WMesaContext pwc = wmesa_context(ctx);
+   WMesaFramebuffer pwfb = wmesa_lookup_framebuffer(pwc->hDC);
+   CONST BITMAPINFO bmi=
+   {
+      {
+         sizeof(BITMAPINFOHEADER),
+         n, 1, 1, 32, BI_RGB, 0, 1, 1, 0, 0
+      }
+   };
+   HBITMAP bmp=0;
+   HDC mdc=0;
+   typedef union
+   {
+      unsigned i;
+      struct {
+         unsigned b:8, g:8, r:8, a:8;
+      };
+   } BGRA;
+   BGRA *bgra, c;
+   GLuint i;
+
+   if (n < 16) {   // the value 16 is just guessed
+      y=FLIP(y);
+      if (mask) {
+         for (i=0; i<n; i++)
+            if (mask[i])
+               SetPixel(pwc->hDC, x+i, y,
+                        RGB(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]));
+      }
+      else {
+         for (i=0; i<n; i++)
+            SetPixel(pwc->hDC, x+i, y,
+                     RGB(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]));
+      }
+   }
+   else {
+      if (!pwfb) {
+         _mesa_problem(NULL, "wmesa: write_rgba_span_front on unknown hdc");
+         return;
+      }
+      bgra=malloc(n*sizeof(BGRA));
+      if (!bgra) {
+         _mesa_problem(NULL, "wmesa: write_rgba_span_front: out of memory");
+         return;
+      }
+      c.a=0;
+      if (mask) {
+         for (i=0; i<n; i++) {
+            if (mask[i]) {
+               c.r=rgba[i][RCOMP];
+               c.g=rgba[i][GCOMP];
+               c.b=rgba[i][BCOMP];
+               c.a=rgba[i][ACOMP];
+               bgra[i]=c;
+            }
+            else
+               bgra[i].i=0;
+         }
+      }
+      else {
+         for (i=0; i<n; i++) {
+            c.r=rgba[i][RCOMP];
+            c.g=rgba[i][GCOMP];
+            c.b=rgba[i][BCOMP];
+            c.a=rgba[i][ACOMP];
+            bgra[i]=c;
+         }
+      }
+      bmp=CreateBitmap(n, 1,  1, 32, bgra);
+      mdc=CreateCompatibleDC(pwfb->hDC);
+      SelectObject(mdc, bmp);
+      y=FLIP(y);
+      BitBlt(pwfb->hDC, x, y, n, 1, mdc, 0, 0, SRCCOPY);
+      SelectObject(mdc, 0);
+      DeleteObject(bmp);
+      DeleteDC(mdc);
+      free(bgra);
+   }
+}
+
+/* Write a horizontal span of RGB color pixels with a boolean mask. */
+static void write_rgb_span_front(const struct gl_context *ctx, 
+				  struct gl_renderbuffer *rb, 
+				  GLuint n, GLint x, GLint y,
+				  const GLubyte rgb[][3], 
+				  const GLubyte mask[] )
+{
+    WMesaContext pwc = wmesa_context(ctx);
+    GLuint i;
+    
+    (void) ctx;
+    y=FLIP(y);
+    if (mask) {
+	for (i=0; i<n; i++)
+	    if (mask[i])
+		SetPixel(pwc->hDC, x+i, y, RGB(rgb[i][RCOMP], rgb[i][GCOMP], 
+					       rgb[i][BCOMP]));
+    }
+    else {
+	for (i=0; i<n; i++)
+	    SetPixel(pwc->hDC, x+i, y, RGB(rgb[i][RCOMP], rgb[i][GCOMP], 
+					   rgb[i][BCOMP]));
+    }
+    
+}
+
+/*
+ * Write a horizontal span of pixels with a boolean mask.  The current color
+ * is used for all pixels.
+ */
+static void write_mono_rgba_span_front(const struct gl_context *ctx, 
+					struct gl_renderbuffer *rb,
+					GLuint n, GLint x, GLint y,
+					const GLchan color[4], 
+					const GLubyte mask[])
+{
+    GLuint i;
+    WMesaContext pwc = wmesa_context(ctx);
+    COLORREF colorref;
+
+    (void) ctx;
+    colorref = RGB(color[RCOMP], color[GCOMP], color[BCOMP]);
+    y=FLIP(y);
+    if (mask) {
+	for (i=0; i<n; i++)
+	    if (mask[i])
+		SetPixel(pwc->hDC, x+i, y, colorref);
+    }
+    else
+	for (i=0; i<n; i++)
+	    SetPixel(pwc->hDC, x+i, y, colorref);
+
+}
+
+/* Write an array of RGBA pixels with a boolean mask. */
+static void write_rgba_pixels_front(const struct gl_context *ctx, 
+				     struct gl_renderbuffer *rb,
+				     GLuint n, 
+				     const GLint x[], const GLint y[],
+				     const GLubyte rgba[][4], 
+				     const GLubyte mask[] )
+{
+    GLuint i;
+    WMesaContext pwc = wmesa_context(ctx);
+    (void) ctx;
+    for (i=0; i<n; i++)
+	if (mask[i])
+	    SetPixel(pwc->hDC, x[i], FLIP(y[i]), 
+		     RGB(rgba[i][RCOMP], rgba[i][GCOMP], 
+			 rgba[i][BCOMP]));
+}
+
+
+
+/*
+ * Write an array of pixels with a boolean mask.  The current color
+ * is used for all pixels.
+ */
+static void write_mono_rgba_pixels_front(const struct gl_context *ctx, 
+					  struct gl_renderbuffer *rb,
+					  GLuint n,
+					  const GLint x[], const GLint y[],
+					  const GLchan color[4],
+					  const GLubyte mask[] )
+{
+    GLuint i;
+    WMesaContext pwc = wmesa_context(ctx);
+    COLORREF colorref;
+    (void) ctx;
+    colorref = RGB(color[RCOMP], color[GCOMP], color[BCOMP]);
+    for (i=0; i<n; i++)
+	if (mask[i])
+	    SetPixel(pwc->hDC, x[i], FLIP(y[i]), colorref);
+}
+
+/* Read a horizontal span of color pixels. */
+static void read_rgba_span_front(const struct gl_context *ctx, 
+				  struct gl_renderbuffer *rb,
+				  GLuint n, GLint x, GLint y,
+				  GLubyte rgba[][4] )
+{
+    WMesaContext pwc = wmesa_context(ctx);
+    GLuint i;
+    COLORREF Color;
+    y = FLIP(y);
+    for (i=0; i<n; i++) {
+	Color = GetPixel(pwc->hDC, x+i, y);
+	rgba[i][RCOMP] = GetRValue(Color);
+	rgba[i][GCOMP] = GetGValue(Color);
+	rgba[i][BCOMP] = GetBValue(Color);
+	rgba[i][ACOMP] = 255;
+    }
+}
+
+
+/* Read an array of color pixels. */
+static void read_rgba_pixels_front(const struct gl_context *ctx, 
+				    struct gl_renderbuffer *rb,
+				    GLuint n, const GLint x[], const GLint y[],
+				    GLubyte rgba[][4])
+{
+    WMesaContext pwc = wmesa_context(ctx);
+    GLuint i;
+    COLORREF Color;
+    for (i=0; i<n; i++) {
+        GLint y2 = FLIP(y[i]);
+        Color = GetPixel(pwc->hDC, x[i], y2);
+        rgba[i][RCOMP] = GetRValue(Color);
+        rgba[i][GCOMP] = GetGValue(Color);
+        rgba[i][BCOMP] = GetBValue(Color);
+        rgba[i][ACOMP] = 255;
+    }
+}
+
+/*********************************************************************/
+
+/* DOUBLE BUFFER 32-bit */
+
+#define WMSETPIXEL32(pwc, y, x, r, g, b) { \
+LPDWORD lpdw = ((LPDWORD)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (x)); \
+*lpdw = BGR32((r),(g),(b)); }
+
+
+
+/* Write a horizontal span of RGBA color pixels with a boolean mask. */
+static void write_rgba_span_32(const struct gl_context *ctx, 
+			       struct gl_renderbuffer *rb, 
+			       GLuint n, GLint x, GLint y,
+			       const GLubyte rgba[][4], 
+			       const GLubyte mask[] )
+{
+    WMesaContext pwc = wmesa_context(ctx);
+    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+    GLuint i;
+    LPDWORD lpdw;
+
+    (void) ctx;
+    
+    y=FLIP(y);
+    lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
+    if (mask) {
+	for (i=0; i<n; i++)
+	    if (mask[i])
+                lpdw[i] = BGR32(rgba[i][RCOMP], rgba[i][GCOMP], 
+				rgba[i][BCOMP]);
+    }
+    else {
+	for (i=0; i<n; i++)
+                *lpdw++ = BGR32(rgba[i][RCOMP], rgba[i][GCOMP], 
+				rgba[i][BCOMP]);
+    }
+}
+
+
+/* Write a horizontal span of RGB color pixels with a boolean mask. */
+static void write_rgb_span_32(const struct gl_context *ctx, 
+			      struct gl_renderbuffer *rb, 
+			      GLuint n, GLint x, GLint y,
+			      const GLubyte rgb[][3], 
+			      const GLubyte mask[] )
+{
+    WMesaContext pwc = wmesa_context(ctx);
+    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+    GLuint i;
+    LPDWORD lpdw;
+
+    (void) ctx;
+    
+    y=FLIP(y);
+    lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
+    if (mask) {
+	for (i=0; i<n; i++)
+	    if (mask[i])
+                lpdw[i] = BGR32(rgb[i][RCOMP], rgb[i][GCOMP], 
+				rgb[i][BCOMP]);
+    }
+    else {
+	for (i=0; i<n; i++)
+                *lpdw++ = BGR32(rgb[i][RCOMP], rgb[i][GCOMP], 
+				rgb[i][BCOMP]);
+    }
+}
+
+/*
+ * Write a horizontal span of pixels with a boolean mask.  The current color
+ * is used for all pixels.
+ */
+static void write_mono_rgba_span_32(const struct gl_context *ctx, 
+				    struct gl_renderbuffer *rb,
+				    GLuint n, GLint x, GLint y,
+				    const GLchan color[4], 
+				    const GLubyte mask[])
+{
+    LPDWORD lpdw;
+    DWORD pixel;
+    GLuint i;
+    WMesaContext pwc = wmesa_context(ctx);
+    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+    lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
+    y=FLIP(y);
+    pixel = BGR32(color[RCOMP], color[GCOMP], color[BCOMP]);
+    if (mask) {
+	for (i=0; i<n; i++)
+	    if (mask[i])
+                lpdw[i] = pixel;
+    }
+    else
+	for (i=0; i<n; i++)
+                *lpdw++ = pixel;
+
+}
+
+/* Write an array of RGBA pixels with a boolean mask. */
+static void write_rgba_pixels_32(const struct gl_context *ctx, 
+				 struct gl_renderbuffer *rb,
+				 GLuint n, const GLint x[], const GLint y[],
+				 const GLubyte rgba[][4], 
+				 const GLubyte mask[])
+{
+    GLuint i;
+    WMesaContext pwc = wmesa_context(ctx);
+    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+    for (i=0; i<n; i++)
+	if (mask[i])
+	    WMSETPIXEL32(pwfb, FLIP(y[i]), x[i],
+			 rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
+}
+
+/*
+ * Write an array of pixels with a boolean mask.  The current color
+ * is used for all pixels.
+ */
+static void write_mono_rgba_pixels_32(const struct gl_context *ctx, 
+				      struct gl_renderbuffer *rb,
+				      GLuint n,
+				      const GLint x[], const GLint y[],
+				      const GLchan color[4],
+				      const GLubyte mask[])
+{
+    GLuint i;
+    WMesaContext pwc = wmesa_context(ctx);
+    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+    for (i=0; i<n; i++)
+	if (mask[i])
+	    WMSETPIXEL32(pwfb, FLIP(y[i]),x[i],color[RCOMP],
+			 color[GCOMP], color[BCOMP]);
+}
+
+/* Read a horizontal span of color pixels. */
+static void read_rgba_span_32(const struct gl_context *ctx, 
+			      struct gl_renderbuffer *rb,
+			      GLuint n, GLint x, GLint y,
+			      GLubyte rgba[][4] )
+{
+    GLuint i;
+    DWORD pixel;
+    LPDWORD lpdw;
+    WMesaContext pwc = wmesa_context(ctx);
+    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+    
+    y = FLIP(y);
+    lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
+    for (i=0; i<n; i++) {
+	pixel = lpdw[i];
+	rgba[i][RCOMP] = (GLubyte)((pixel & 0x00ff0000) >> 16);
+	rgba[i][GCOMP] = (GLubyte)((pixel & 0x0000ff00) >> 8);
+	rgba[i][BCOMP] = (GLubyte)(pixel & 0x000000ff);
+	rgba[i][ACOMP] = 255;
+    }
+}
+
+
+/* Read an array of color pixels. */
+static void read_rgba_pixels_32(const struct gl_context *ctx, 
+				struct gl_renderbuffer *rb,
+				GLuint n, const GLint x[], const GLint y[],
+				GLubyte rgba[][4])
+{
+    GLuint i;
+    DWORD pixel;
+    LPDWORD lpdw;
+    WMesaContext pwc = wmesa_context(ctx);
+    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+
+    for (i=0; i<n; i++) {
+	GLint y2 = FLIP(y[i]);
+	lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y2)) + x[i];
+	pixel = *lpdw;
+	rgba[i][RCOMP] = (GLubyte)((pixel & 0x00ff0000) >> 16);
+	rgba[i][GCOMP] = (GLubyte)((pixel & 0x0000ff00) >> 8);
+	rgba[i][BCOMP] = (GLubyte)(pixel & 0x000000ff);
+	rgba[i][ACOMP] = 255;
+  }
+}
+
+
+/*********************************************************************/
+
+/* DOUBLE BUFFER 24-bit */
+
+#define WMSETPIXEL24(pwc, y, x, r, g, b) { \
+LPBYTE lpb = ((LPBYTE)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (3 * x)); \
+lpb[0] = (b); \
+lpb[1] = (g); \
+lpb[2] = (r); }
+
+/* Write a horizontal span of RGBA color pixels with a boolean mask. */
+static void write_rgba_span_24(const struct gl_context *ctx, 
+			       struct gl_renderbuffer *rb, 
+			       GLuint n, GLint x, GLint y,
+			       const GLubyte rgba[][4], 
+			       const GLubyte mask[] )
+{
+    WMesaContext pwc = wmesa_context(ctx);
+    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+    GLuint i;
+    LPBYTE lpb;
+
+    (void) ctx;
+    
+    y=FLIP(y);
+    lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y)) + (3 * x);
+    if (mask) {
+	for (i=0; i<n; i++)
+	    if (mask[i]) {
+                lpb[3*i] = rgba[i][BCOMP];
+                lpb[3*i+1] = rgba[i][GCOMP];
+                lpb[3*i+2] = rgba[i][RCOMP];
+	    }
+    }
+    else {
+	    for (i=0; i<n; i++) {
+            *lpb++ = rgba[i][BCOMP];
+            *lpb++ = rgba[i][GCOMP];
+            *lpb++ = rgba[i][RCOMP];
+	    }
+    }
+}
+
+
+/* Write a horizontal span of RGB color pixels with a boolean mask. */
+static void write_rgb_span_24(const struct gl_context *ctx, 
+			      struct gl_renderbuffer *rb, 
+			      GLuint n, GLint x, GLint y,
+			      const GLubyte rgb[][3], 
+			      const GLubyte mask[] )
+{
+    WMesaContext pwc = wmesa_context(ctx);
+    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+    GLuint i;
+    LPBYTE lpb;
+
+    (void) ctx;
+    
+    y=FLIP(y);
+    lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y)) + (3 * x);
+    if (mask) {
+	for (i=0; i<n; i++)
+	    if (mask[i]) {
+            lpb[3*i] = rgb[i][BCOMP];
+            lpb[3*i+1] = rgb[i][GCOMP];
+            lpb[3*i+2] = rgb[i][RCOMP];
+	    }
+    }
+    else {
+    	for (i=0; i<n; i++) {
+    		*lpb++ = rgb[i][BCOMP];
+    		*lpb++ = rgb[i][GCOMP];
+    		*lpb++ = rgb[i][RCOMP];
+    	}
+    }
+}
+
+/*
+ * Write a horizontal span of pixels with a boolean mask.  The current color
+ * is used for all pixels.
+ */
+static void write_mono_rgba_span_24(const struct gl_context *ctx, 
+				    struct gl_renderbuffer *rb,
+				    GLuint n, GLint x, GLint y,
+				    const GLchan color[4], 
+				    const GLubyte mask[])
+{
+    LPBYTE lpb;
+    GLuint i;
+    WMesaContext pwc = wmesa_context(ctx);
+    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+    lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y)) + (3 * x);
+    y=FLIP(y);
+    if (mask) {
+	for (i=0; i<n; i++)
+	    if (mask[i]) {
+	    	lpb[3*i] = color[BCOMP];
+	    	lpb[3*i+1] = color[GCOMP];
+	    	lpb[3*i+2] = color[RCOMP];
+	    }
+    }
+    else
+	for (i=0; i<n; i++) {
+		*lpb++ = color[BCOMP];
+		*lpb++ = color[GCOMP];
+		*lpb++ = color[RCOMP];		
+	}
+}
+
+/* Write an array of RGBA pixels with a boolean mask. */
+static void write_rgba_pixels_24(const struct gl_context *ctx, 
+				 struct gl_renderbuffer *rb,
+				 GLuint n, const GLint x[], const GLint y[],
+				 const GLubyte rgba[][4], 
+				 const GLubyte mask[])
+{
+    GLuint i;
+    WMesaContext pwc = wmesa_context(ctx);
+    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+    for (i=0; i<n; i++)
+	if (mask[i])
+	    WMSETPIXEL24(pwfb, FLIP(y[i]), x[i],
+			 rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
+}
+
+/*
+ * Write an array of pixels with a boolean mask.  The current color
+ * is used for all pixels.
+ */
+static void write_mono_rgba_pixels_24(const struct gl_context *ctx, 
+				      struct gl_renderbuffer *rb,
+				      GLuint n,
+				      const GLint x[], const GLint y[],
+				      const GLchan color[4],
+				      const GLubyte mask[])
+{
+    GLuint i;
+    WMesaContext pwc = wmesa_context(ctx);
+    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+    for (i=0; i<n; i++)
+	if (mask[i])
+	    WMSETPIXEL24(pwfb, FLIP(y[i]),x[i],color[RCOMP],
+			 color[GCOMP], color[BCOMP]);
+}
+
+/* Read a horizontal span of color pixels. */
+static void read_rgba_span_24(const struct gl_context *ctx, 
+			      struct gl_renderbuffer *rb,
+			      GLuint n, GLint x, GLint y,
+			      GLubyte rgba[][4] )
+{
+    GLuint i;
+    LPBYTE lpb;
+    WMesaContext pwc = wmesa_context(ctx);
+    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+    
+    y = FLIP(y);
+    lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y)) + (3 * x);
+    for (i=0; i<n; i++) {
+	rgba[i][RCOMP] = lpb[3*i+2];
+	rgba[i][GCOMP] = lpb[3*i+1];
+	rgba[i][BCOMP] = lpb[3*i];
+	rgba[i][ACOMP] = 255;
+    }
+}
+
+
+/* Read an array of color pixels. */
+static void read_rgba_pixels_24(const struct gl_context *ctx, 
+				struct gl_renderbuffer *rb,
+				GLuint n, const GLint x[], const GLint y[],
+				GLubyte rgba[][4])
+{
+    GLuint i;
+    LPBYTE lpb;
+    WMesaContext pwc = wmesa_context(ctx);
+    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+
+    for (i=0; i<n; i++) {
+	GLint y2 = FLIP(y[i]);
+	lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y2)) + (3 * x[i]);
+	rgba[i][RCOMP] = lpb[3*i+2];
+	rgba[i][GCOMP] = lpb[3*i+1];
+	rgba[i][BCOMP] = lpb[3*i];
+	rgba[i][ACOMP] = 255;
+  }
+}
+
+
+/*********************************************************************/
+
+/* DOUBLE BUFFER 16-bit */
+
+#define WMSETPIXEL16(pwc, y, x, r, g, b) { \
+LPWORD lpw = ((LPWORD)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (x)); \
+*lpw = BGR16((r),(g),(b)); }
+
+
+
+/* Write a horizontal span of RGBA color pixels with a boolean mask. */
+static void write_rgba_span_16(const struct gl_context *ctx, 
+			       struct gl_renderbuffer *rb, 
+			       GLuint n, GLint x, GLint y,
+			       const GLubyte rgba[][4], 
+			       const GLubyte mask[] )
+{
+    WMesaContext pwc = wmesa_context(ctx);
+    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+    GLuint i;
+    LPWORD lpw;
+
+    (void) ctx;
+    
+    y=FLIP(y);
+    lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
+    if (mask) {
+	for (i=0; i<n; i++)
+	    if (mask[i])
+                lpw[i] = BGR16(rgba[i][RCOMP], rgba[i][GCOMP], 
+			       rgba[i][BCOMP]);
+    }
+    else {
+	for (i=0; i<n; i++)
+                *lpw++ = BGR16(rgba[i][RCOMP], rgba[i][GCOMP], 
+			       rgba[i][BCOMP]);
+    }
+}
+
+
+/* Write a horizontal span of RGB color pixels with a boolean mask. */
+static void write_rgb_span_16(const struct gl_context *ctx, 
+			      struct gl_renderbuffer *rb, 
+			      GLuint n, GLint x, GLint y,
+			      const GLubyte rgb[][3], 
+			      const GLubyte mask[] )
+{
+    WMesaContext pwc = wmesa_context(ctx);
+    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+    GLuint i;
+    LPWORD lpw;
+
+    (void) ctx;
+    
+    y=FLIP(y);
+    lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
+    if (mask) {
+	for (i=0; i<n; i++)
+	    if (mask[i])
+                lpw[i] = BGR16(rgb[i][RCOMP], rgb[i][GCOMP], 
+			       rgb[i][BCOMP]);
+    }
+    else {
+	for (i=0; i<n; i++)
+                *lpw++ = BGR16(rgb[i][RCOMP], rgb[i][GCOMP], 
+			       rgb[i][BCOMP]);
+    }
+}
+
+/*
+ * Write a horizontal span of pixels with a boolean mask.  The current color
+ * is used for all pixels.
+ */
+static void write_mono_rgba_span_16(const struct gl_context *ctx, 
+				    struct gl_renderbuffer *rb,
+				    GLuint n, GLint x, GLint y,
+				    const GLchan color[4], 
+				    const GLubyte mask[])
+{
+    LPWORD lpw;
+    WORD pixel;
+    GLuint i;
+    WMesaContext pwc = wmesa_context(ctx);
+    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+    (void) ctx;
+    lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
+    y=FLIP(y);
+    pixel = BGR16(color[RCOMP], color[GCOMP], color[BCOMP]);
+    if (mask) {
+	for (i=0; i<n; i++)
+	    if (mask[i])
+                lpw[i] = pixel;
+    }
+    else
+	for (i=0; i<n; i++)
+                *lpw++ = pixel;
+
+}
+
+/* Write an array of RGBA pixels with a boolean mask. */
+static void write_rgba_pixels_16(const struct gl_context *ctx, 
+				 struct gl_renderbuffer *rb,
+				 GLuint n, const GLint x[], const GLint y[],
+				 const GLubyte rgba[][4], 
+				 const GLubyte mask[])
+{
+    GLuint i;
+    WMesaContext pwc = wmesa_context(ctx);
+    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+    (void) ctx;
+    for (i=0; i<n; i++)
+	if (mask[i])
+	    WMSETPIXEL16(pwfb, FLIP(y[i]), x[i],
+			 rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
+}
+
+/*
+ * Write an array of pixels with a boolean mask.  The current color
+ * is used for all pixels.
+ */
+static void write_mono_rgba_pixels_16(const struct gl_context *ctx, 
+				      struct gl_renderbuffer *rb,
+				      GLuint n,
+				      const GLint x[], const GLint y[],
+				      const GLchan color[4],
+				      const GLubyte mask[])
+{
+    GLuint i;
+    WMesaContext pwc = wmesa_context(ctx);
+    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+    (void) ctx;
+    for (i=0; i<n; i++)
+	if (mask[i])
+	    WMSETPIXEL16(pwfb, FLIP(y[i]),x[i],color[RCOMP],
+			 color[GCOMP], color[BCOMP]);
+}
+
+/* Read a horizontal span of color pixels. */
+static void read_rgba_span_16(const struct gl_context *ctx, 
+			      struct gl_renderbuffer *rb,
+			      GLuint n, GLint x, GLint y,
+			      GLubyte rgba[][4] )
+{
+    GLuint i, pixel;
+    LPWORD lpw;
+    WMesaContext pwc = wmesa_context(ctx);
+    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+    
+    y = FLIP(y);
+    lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
+    for (i=0; i<n; i++) {
+	pixel = lpw[i];
+	/* Windows uses 5,5,5 for 16-bit */
+	rgba[i][RCOMP] = (pixel & 0x7c00) >> 7;
+	rgba[i][GCOMP] = (pixel & 0x03e0) >> 2;
+	rgba[i][BCOMP] = (pixel & 0x001f) << 3;
+	rgba[i][ACOMP] = 255;
+    }
+}
+
+
+/* Read an array of color pixels. */
+static void read_rgba_pixels_16(const struct gl_context *ctx, 
+				struct gl_renderbuffer *rb,
+				GLuint n, const GLint x[], const GLint y[],
+				GLubyte rgba[][4])
+{
+    GLuint i, pixel;
+    LPWORD lpw;
+    WMesaContext pwc = wmesa_context(ctx);
+    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+
+    for (i=0; i<n; i++) {
+	GLint y2 = FLIP(y[i]);
+	lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y2)) + x[i];
+	pixel = *lpw;
+	/* Windows uses 5,5,5 for 16-bit */
+	rgba[i][RCOMP] = (pixel & 0x7c00) >> 7;
+	rgba[i][GCOMP] = (pixel & 0x03e0) >> 2;
+	rgba[i][BCOMP] = (pixel & 0x001f) << 3;
+	rgba[i][ACOMP] = 255;
+  }
+}
+
+
+
+
+/**********************************************************************/
+/*****                   BUFFER Functions                         *****/
+/**********************************************************************/
+
+
+
+
+static void
+wmesa_delete_renderbuffer(struct gl_renderbuffer *rb)
+{
+    free(rb);
+}
+
+
+/**
+ * This is called by Mesa whenever it determines that the window size
+ * has changed.  Do whatever's needed to cope with that.
+ */
+static GLboolean
+wmesa_renderbuffer_storage(struct gl_context *ctx, 
+			   struct gl_renderbuffer *rb,
+			   GLenum internalFormat, 
+			   GLuint width, 
+			   GLuint height)
+{
+    rb->Width = width;
+    rb->Height = height;
+    return GL_TRUE;
+}
+
+
+/**
+ * Plug in the Get/PutRow/Values functions for a renderbuffer depending
+ * on if we're drawing to the front or back color buffer.
+ */
+void wmesa_set_renderbuffer_funcs(struct gl_renderbuffer *rb, int pixelformat,
+                                  int cColorBits, int double_buffer)
+{
+    if (double_buffer) {
+        /* back buffer */
+	/* Picking the correct span functions is important because
+	 * the DIB was allocated with the indicated depth. */
+	switch(pixelformat) {
+	case PF_5R6G5B:
+	    rb->PutRow = write_rgba_span_16;
+	    rb->PutRowRGB = write_rgb_span_16;
+	    rb->PutMonoRow = write_mono_rgba_span_16;
+	    rb->PutValues = write_rgba_pixels_16;
+	    rb->PutMonoValues = write_mono_rgba_pixels_16;
+	    rb->GetRow = read_rgba_span_16;
+	    rb->GetValues = read_rgba_pixels_16;
+	    break;
+	case PF_8R8G8B:
+		if (cColorBits == 24)
+		{
+		    rb->PutRow = write_rgba_span_24;
+		    rb->PutRowRGB = write_rgb_span_24;
+		    rb->PutMonoRow = write_mono_rgba_span_24;
+		    rb->PutValues = write_rgba_pixels_24;
+		    rb->PutMonoValues = write_mono_rgba_pixels_24;
+		    rb->GetRow = read_rgba_span_24;
+		    rb->GetValues = read_rgba_pixels_24;
+		}
+		else
+		{
+	        rb->PutRow = write_rgba_span_32;
+	        rb->PutRowRGB = write_rgb_span_32;
+	        rb->PutMonoRow = write_mono_rgba_span_32;
+	        rb->PutValues = write_rgba_pixels_32;
+	        rb->PutMonoValues = write_mono_rgba_pixels_32;
+	        rb->GetRow = read_rgba_span_32;
+	        rb->GetValues = read_rgba_pixels_32;
+		}
+	    break;
+	default:
+	    break;
+	}
+    }
+    else {
+        /* front buffer (actual Windows window) */
+	rb->PutRow = write_rgba_span_front;
+	rb->PutRowRGB = write_rgb_span_front;
+	rb->PutMonoRow = write_mono_rgba_span_front;
+	rb->PutValues = write_rgba_pixels_front;
+	rb->PutMonoValues = write_mono_rgba_pixels_front;
+	rb->GetRow = read_rgba_span_front;
+	rb->GetValues = read_rgba_pixels_front;
+    }
+}
+
+/**
+ * Called by ctx->Driver.ResizeBuffers()
+ * Resize the front/back colorbuffers to match the latest window size.
+ */
+static void
+wmesa_resize_buffers(struct gl_context *ctx, struct gl_framebuffer *buffer,
+                     GLuint width, GLuint height)
+{
+    WMesaContext pwc = wmesa_context(ctx);
+    WMesaFramebuffer pwfb = wmesa_framebuffer(buffer);
+
+    if (pwfb->Base.Width != width || pwfb->Base.Height != height) {
+	/* Realloc back buffer */
+	if (ctx->Visual.doubleBufferMode == 1) {
+	    wmDeleteBackingStore(pwfb);
+	    wmCreateBackingStore(pwfb, width, height);
+	}
+    }
+    _mesa_resize_framebuffer(ctx, buffer, width, height);
+}
+
+
+/**
+ * Called by glViewport.
+ * This is a good time for us to poll the current window size and adjust
+ * our renderbuffers to match the current window size.
+ * Remember, we have no opportunity to respond to conventional
+ * resize events since the driver has no event loop.
+ * Thus, we poll.
+ * MakeCurrent also ends up making a call here, so that ensures
+ * we get the viewport set correctly, even if the app does not call
+ * glViewport and relies on the defaults.
+ */
+static void wmesa_viewport(struct gl_context *ctx, 
+			   GLint x, GLint y, 
+			   GLsizei width, GLsizei height)
+{
+    WMesaContext pwc = wmesa_context(ctx);
+    GLuint new_width, new_height;
+
+    wmesa_get_buffer_size(ctx->WinSysDrawBuffer, &new_width, &new_height);
+
+    /**
+     * Resize buffers if the window size changed.
+     */
+    wmesa_resize_buffers(ctx, ctx->WinSysDrawBuffer, new_width, new_height);
+    ctx->NewState |= _NEW_BUFFERS;  /* to update scissor / window bounds */
+}
+
+
+
+
+/**
+ * Called when the driver should update it's state, based on the new_state
+ * flags.
+ */
+static void wmesa_update_state(struct gl_context *ctx, GLuint new_state)
+{
+    _swrast_InvalidateState(ctx, new_state);
+    _swsetup_InvalidateState(ctx, new_state);
+    _vbo_InvalidateState(ctx, new_state);
+    _tnl_InvalidateState(ctx, new_state);
+
+    /* TODO - This code is not complete yet because I 
+     * don't know what to do for all state updates.
+     */
+
+    if (new_state & _NEW_BUFFERS) {
+    }
+}
+
+
+
+
+
+/**********************************************************************/
+/*****                   WMESA Functions                          *****/
+/**********************************************************************/
+
+WMesaContext WMesaCreateContext(HDC hDC, 
+				HPALETTE* Pal,
+				GLboolean rgb_flag,
+				GLboolean db_flag,
+				GLboolean alpha_flag)
+{
+    WMesaContext c;
+    struct dd_function_table functions;
+    GLint red_bits, green_bits, blue_bits, alpha_bits;
+    struct gl_context *ctx;
+    struct gl_config *visual;
+
+    (void) Pal;
+    
+    /* Indexed mode not supported */
+    if (!rgb_flag)
+	return NULL;
+
+    /* Allocate wmesa context */
+    c = CALLOC_STRUCT(wmesa_context);
+    if (!c)
+	return NULL;
+
+#if 0
+    /* I do not understand this contributed code */
+    /* Support memory and device contexts */
+    if(WindowFromDC(hDC) != NULL) {
+	c->hDC = GetDC(WindowFromDC(hDC)); /* huh ???? */
+    }
+    else {
+	c->hDC = hDC;
+    }
+#else
+    c->hDC = hDC;
+#endif
+
+    /* Get data for visual */
+    /* Dealing with this is actually a bit of overkill because Mesa will end
+     * up treating all color component size requests less than 8 by using 
+     * a single byte per channel.  In addition, the interface to the span
+     * routines passes colors as an entire byte per channel anyway, so there
+     * is nothing to be saved by telling the visual to be 16 bits if the device
+     * is 16 bits.  That is, Mesa is going to compute colors down to 8 bits per
+     * channel anyway.
+     * But we go through the motions here anyway.
+     */
+    switch (GetDeviceCaps(c->hDC, BITSPIXEL)) {
+    case 16:
+	red_bits = green_bits = blue_bits = 5;
+	alpha_bits = 0;
+	break;
+    default:
+	red_bits = green_bits = blue_bits = 8;
+	alpha_bits = 8;
+	break;
+    }
+    /* Create visual based on flags */
+    visual = _mesa_create_visual(db_flag,    /* db_flag */
+                                 GL_FALSE,   /* stereo */
+                                 red_bits, green_bits, blue_bits, /* color RGB */
+                                 alpha_flag ? alpha_bits : 0, /* color A */
+                                 DEFAULT_SOFTWARE_DEPTH_BITS, /* depth_bits */
+                                 8,          /* stencil_bits */
+                                 16,16,16,   /* accum RGB */
+                                 alpha_flag ? 16 : 0, /* accum A */
+                                 1);         /* num samples */
+    
+    if (!visual) {
+	free(c);
+	return NULL;
+    }
+
+    /* Set up driver functions */
+    _mesa_init_driver_functions(&functions);
+    functions.GetString = wmesa_get_string;
+    functions.UpdateState = wmesa_update_state;
+    functions.GetBufferSize = wmesa_get_buffer_size;
+    functions.Flush = wmesa_flush;
+    functions.Clear = clear;
+    functions.ClearColor = clear_color;
+    functions.ResizeBuffers = wmesa_resize_buffers;
+    functions.Viewport = wmesa_viewport;
+
+    /* initialize the Mesa context data */
+    ctx = &c->gl_ctx;
+    _mesa_initialize_context(ctx, API_OPENGL, visual,
+                             NULL, &functions, (void *)c);
+
+    /* visual no longer needed - it was copied by _mesa_initialize_context() */
+    _mesa_destroy_visual(visual);
+
+    _mesa_enable_sw_extensions(ctx);
+    _mesa_enable_1_3_extensions(ctx);
+    _mesa_enable_1_4_extensions(ctx);
+    _mesa_enable_1_5_extensions(ctx);
+    _mesa_enable_2_0_extensions(ctx);
+    _mesa_enable_2_1_extensions(ctx);
+  
+    _mesa_meta_init(ctx);
+
+    /* Initialize the software rasterizer and helper modules. */
+    if (!_swrast_CreateContext(ctx) ||
+        !_vbo_CreateContext(ctx) ||
+        !_tnl_CreateContext(ctx) ||
+	!_swsetup_CreateContext(ctx)) {
+	_mesa_free_context_data(ctx);
+	free(c);
+	return NULL;
+    }
+    _swsetup_Wakeup(ctx);
+    TNL_CONTEXT(ctx)->Driver.RunPipeline = _tnl_run_pipeline;
+
+    return c;
+}
+
+
+void WMesaDestroyContext( WMesaContext pwc )
+{
+    struct gl_context *ctx = &pwc->gl_ctx;
+    WMesaFramebuffer pwfb;
+    GET_CURRENT_CONTEXT(cur_ctx);
+
+    if (cur_ctx == ctx) {
+        /* unbind current if deleting current context */
+        WMesaMakeCurrent(NULL, NULL);
+    }
+
+    /* clean up frame buffer resources */
+    pwfb = wmesa_lookup_framebuffer(pwc->hDC);
+    if (pwfb) {
+	if (ctx->Visual.doubleBufferMode == 1)
+	    wmDeleteBackingStore(pwfb);
+	wmesa_free_framebuffer(pwc->hDC);
+    }
+
+    /* Release for device, not memory contexts */
+    if (WindowFromDC(pwc->hDC) != NULL)
+    {
+      ReleaseDC(WindowFromDC(pwc->hDC), pwc->hDC);
+    }
+    DeleteObject(pwc->clearPen); 
+    DeleteObject(pwc->clearBrush); 
+    
+    _mesa_meta_free(ctx);
+
+    _swsetup_DestroyContext(ctx);
+    _tnl_DestroyContext(ctx);
+    _vbo_DestroyContext(ctx);
+    _swrast_DestroyContext(ctx);
+    
+    _mesa_free_context_data(ctx);
+    free(pwc);
+}
+
+
+/**
+ * Create a new color renderbuffer.
+ */
+struct gl_renderbuffer *
+wmesa_new_renderbuffer(void)
+{
+    struct gl_renderbuffer *rb = CALLOC_STRUCT(gl_renderbuffer);
+    if (!rb)
+        return NULL;
+
+    _mesa_init_renderbuffer(rb, (GLuint)0);
+    
+    rb->_BaseFormat = GL_RGBA;
+    rb->InternalFormat = GL_RGBA;
+    rb->DataType = CHAN_TYPE;
+    rb->Delete = wmesa_delete_renderbuffer;
+    rb->AllocStorage = wmesa_renderbuffer_storage;
+    return rb;
+}
+
+
+void WMesaMakeCurrent(WMesaContext c, HDC hdc)
+{
+    WMesaFramebuffer pwfb;
+
+    {
+        /* return if already current */
+        GET_CURRENT_CONTEXT(ctx);
+        WMesaContext pwc = wmesa_context(ctx);
+        if (pwc && c == pwc && pwc->hDC == hdc)
+            return;
+    }
+
+    pwfb = wmesa_lookup_framebuffer(hdc);
+
+    /* Lazy creation of framebuffers */
+    if (c && !pwfb && hdc) {
+        struct gl_renderbuffer *rb;
+        struct gl_config *visual = &c->gl_ctx.Visual;
+        GLuint width, height;
+
+        get_window_size(hdc, &width, &height);
+
+	c->clearPen = CreatePen(PS_SOLID, 1, 0); 
+	c->clearBrush = CreateSolidBrush(0); 
+
+        pwfb = wmesa_new_framebuffer(hdc, visual);
+
+	/* Create back buffer if double buffered */
+	if (visual->doubleBufferMode == 1) {
+	    wmCreateBackingStore(pwfb, width, height);
+	}
+	
+        /* make render buffers */
+        if (visual->doubleBufferMode == 1) {
+            rb = wmesa_new_renderbuffer();
+            _mesa_add_renderbuffer(&pwfb->Base, BUFFER_BACK_LEFT, rb);
+            wmesa_set_renderbuffer_funcs(rb, pwfb->pixelformat, pwfb->cColorBits, 1);
+	}
+        rb = wmesa_new_renderbuffer();
+        _mesa_add_renderbuffer(&pwfb->Base, BUFFER_FRONT_LEFT, rb);
+        wmesa_set_renderbuffer_funcs(rb, pwfb->pixelformat, pwfb->cColorBits, 0);
+
+	/* Let Mesa own the Depth, Stencil, and Accum buffers */
+        _mesa_add_soft_renderbuffers(&pwfb->Base,
+                                     GL_FALSE, /* color */
+                                     visual->depthBits > 0,
+                                     visual->stencilBits > 0,
+                                     visual->accumRedBits > 0,
+                                     visual->alphaBits >0, 
+                                     GL_FALSE);
+    }
+
+    if (c && pwfb)
+	_mesa_make_current(&c->gl_ctx, &pwfb->Base, &pwfb->Base);
+    else
+        _mesa_make_current(NULL, NULL, NULL);
+}
+
+
+void WMesaSwapBuffers( HDC hdc )
+{
+    GET_CURRENT_CONTEXT(ctx);
+    WMesaContext pwc = wmesa_context(ctx);
+    WMesaFramebuffer pwfb = wmesa_lookup_framebuffer(hdc);
+
+    if (!pwfb) {
+        _mesa_problem(NULL, "wmesa: swapbuffers on unknown hdc");
+        return;
+    }
+
+    /* If we're swapping the buffer associated with the current context
+     * we have to flush any pending rendering commands first.
+     */
+    if (pwc->hDC == hdc) {
+	_mesa_notifySwapBuffers(ctx);
+
+	BitBlt(pwfb->hDC, 0, 0, pwfb->Base.Width, pwfb->Base.Height,
+	       pwfb->dib_hDC, 0, 0, SRCCOPY);
+    }
+    else {
+        /* XXX for now only allow swapping current window */
+        _mesa_problem(NULL, "wmesa: can't swap non-current window");
+    }
+}
+
+void WMesaShareLists(WMesaContext ctx_to_share, WMesaContext ctx)
+{
+	_mesa_share_state(&ctx->gl_ctx, &ctx_to_share->gl_ctx);	
+}
+
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/dglcontext.c b/mesalib/src/mesa/drivers/windows/gldirect/dglcontext.c
index fabce4c0b..9aedd2e3c 100644
--- a/mesalib/src/mesa/drivers/windows/gldirect/dglcontext.c
+++ b/mesalib/src/mesa/drivers/windows/gldirect/dglcontext.c
@@ -1,2212 +1,2212 @@
-/****************************************************************************
-*
-*                        Mesa 3-D graphics library
-*                        Direct3D Driver Interface
-*
-*  ========================================================================
-*
-*   Copyright (C) 1991-2004 SciTech Software, Inc. 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"),
-*   to deal in the Software without restriction, including without limitation
-*   the rights to use, copy, modify, merge, publish, distribute, sublicense,
-*   and/or sell copies of the Software, and to permit persons to whom the
-*   Software is furnished to do so, subject to the following conditions:
-*
-*   The above copyright notice and this permission notice shall be included
-*   in all copies or substantial portions of the Software.
-*
-*   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-*   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-*   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-*   SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-*   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
-*   OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-*   SOFTWARE.
-*
-*  ======================================================================
-*
-* Language:     ANSI C
-* Environment:  Windows 9x (Win32)
-*
-* Description:  Context handling.
-*
-****************************************************************************/
-
-#include "dglcontext.h"
-
-// Get compile errors without this. KeithH
-//#include "scitech.h"	// ibool, etc.
-
-#ifdef _USE_GLD3_WGL
-#include "gld_driver.h"
-
-extern void _gld_mesa_warning(struct gl_context *, char *);
-extern void _gld_mesa_fatal(struct gl_context *, char *);
-#endif // _USE_GLD3_WGL
-
-// TODO: Clean out old DX6-specific code from GLD 2.x CAD driver
-// if it is no longer being built as part of GLDirect. (DaveM)
-
-// ***********************************************************************
-
-#define GLDERR_NONE     0
-#define GLDERR_MEM      1
-#define GLDERR_DDRAW    2
-#define GLDERR_D3D      3
-#define GLDERR_BPP      4
-
-char szResourceWarning[] =
-"GLDirect does not have enough video memory resources\n"
-"to support the requested OpenGL rendering context.\n\n"
-"You may have to reduce the current display resolution\n"
-"to obtain satisfactory OpenGL performance.\n";
-
-char szDDrawWarning[] =
-"GLDirect is unable to initialize DirectDraw for the\n"
-"requested OpenGL rendering context.\n\n"
-"You will have to check the DirectX control panel\n"
-"for further information.\n";
-
-char szD3DWarning[] =
-"GLDirect is unable to initialize Direct3D for the\n"
-"requested OpenGL rendering context.\n\n"
-"You may have to change the display mode resolution\n"
-"color depth or check the DirectX control panel for\n"
-"further information.\n";
-
-char szBPPWarning[] =
-"GLDirect is unable to use the selected color depth for\n"
-"the requested OpenGL rendering context.\n\n"
-"You will have to change the display mode resolution\n"
-"color depth with the Display Settings control panel.\n";
-
-int nContextError = GLDERR_NONE;
-
-// ***********************************************************************
-
-#define VENDORID_ATI 0x1002
-
-static DWORD devATIRagePro[] = {
-	0x4742, // 3D RAGE PRO BGA AGP 1X/2X
-	0x4744, // 3D RAGE PRO BGA AGP 1X only
-	0x4749, // 3D RAGE PRO BGA PCI 33 MHz
-	0x4750, // 3D RAGE PRO PQFP PCI 33 MHz
-	0x4751, // 3D RAGE PRO PQFP PCI 33 MHz limited 3D
-	0x4C42, // 3D RAGE LT PRO BGA-312 AGP 133 MHz
-	0x4C44, // 3D RAGE LT PRO BGA-312 AGP 66 MHz
-	0x4C49, // 3D RAGE LT PRO BGA-312 PCI 33 MHz
-	0x4C50, // 3D RAGE LT PRO BGA-256 PCI 33 MHz
-	0x4C51, // 3D RAGE LT PRO BGA-256 PCI 33 MHz limited 3D
-};
-
-static DWORD devATIRageIIplus[] = {
-	0x4755, // 3D RAGE II+
-	0x4756, // 3D RAGE IIC PQFP PCI
-	0x4757, // 3D RAGE IIC BGA AGP
-	0x475A, // 3D RAGE IIC PQFP AGP
-	0x4C47, // 3D RAGE LT-G
-};
-
-// ***********************************************************************
-
-#ifndef _USE_GLD3_WGL
-extern DGL_mesaFuncs mesaFuncs;
-#endif
-
-extern DWORD dwLogging;
-
-#ifdef GLD_THREADS
-#pragma message("compiling DGLCONTEXT.C vars for multi-threaded support")
-CRITICAL_SECTION CriticalSection;		// for serialized access
-DWORD		dwTLSCurrentContext = 0xFFFFFFFF;	// TLS index for current context
-DWORD		dwTLSPixelFormat = 0xFFFFFFFF;		// TLS index for current pixel format
-#endif
-HGLRC		iCurrentContext = 0;		// Index of current context (static)
-BOOL		bContextReady = FALSE;		// Context state ready ?
-
-DGL_ctx		ctxlist[DGL_MAX_CONTEXTS];	// Context list
-
-// ***********************************************************************
-
-static BOOL bHaveWin95 = FALSE;
-static BOOL bHaveWinNT = FALSE;
-static BOOL bHaveWin2K = FALSE;
-
-/****************************************************************************
-REMARKS:
-Detect the installed OS type.
-****************************************************************************/
-static void DetectOS(void)
-{
-    OSVERSIONINFO VersionInformation;
-    LPOSVERSIONINFO lpVersionInformation = &VersionInformation;
-
-    VersionInformation.dwOSVersionInfoSize = sizeof(VersionInformation);
-
-	GetVersionEx(lpVersionInformation);
-
-    switch (VersionInformation.dwPlatformId) {
-    	case VER_PLATFORM_WIN32_WINDOWS:
-			bHaveWin95 = TRUE;
-			bHaveWinNT = FALSE;
-			bHaveWin2K = FALSE;
-            break;
-    	case VER_PLATFORM_WIN32_NT:
-			bHaveWin95 = FALSE;
-			if (VersionInformation.dwMajorVersion <= 4) {
-				bHaveWinNT = TRUE;
-				bHaveWin2K = FALSE;
-                }
-            else {
-				bHaveWinNT = FALSE;
-				bHaveWin2K = TRUE;
-                }
-			break;
-		case VER_PLATFORM_WIN32s:
-			bHaveWin95 = FALSE;
-			bHaveWinNT = FALSE;
-			bHaveWin2K = FALSE;
-			break;
-        }
-}
-
-// ***********************************************************************
-
-HWND hWndEvent = NULL;					// event monitor window
-HWND hWndLastActive = NULL;				// last active client window
-LONG __stdcall GLD_EventWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam);
-
-// ***********************************************************************
-
-// Checks if the HGLRC is valid in range of context list.
-BOOL dglIsValidContext(
-	HGLRC a)
-{
-	return ((int)a > 0 && (int)a <= DGL_MAX_CONTEXTS);
-}
-
-// ***********************************************************************
-
-// Convert a HGLRC to a pointer into the context list.
-DGL_ctx* dglGetContextAddress(
-	const HGLRC a)
-{
-	if (dglIsValidContext(a))
-		return &ctxlist[(int)a-1];
-	return NULL;
-}
-
-// ***********************************************************************
-
-// Return the current HGLRC (however it may be stored for multi-threading).
-HGLRC dglGetCurrentContext(void)
-{
-#ifdef GLD_THREADS
-	HGLRC hGLRC;
-	// load from thread-specific instance
-	if (glb.bMultiThreaded) {
-		// protect against calls from arbitrary threads
-		__try {
-			hGLRC = (HGLRC)TlsGetValue(dwTLSCurrentContext);
-		}
-		__except(EXCEPTION_EXECUTE_HANDLER) {
-			hGLRC = iCurrentContext;
-		}
-	}
-	// load from global static var
-	else {
-		hGLRC = iCurrentContext;
-	}
-	return hGLRC;
-#else
-	return iCurrentContext;
-#endif
-}
-
-// ***********************************************************************
-
-// Set the current HGLRC (however it may be stored for multi-threading).
-void dglSetCurrentContext(HGLRC hGLRC)
-{
-#ifdef GLD_THREADS
-	// store in thread-specific instance
-	if (glb.bMultiThreaded) {
-		// protect against calls from arbitrary threads
-		__try {
-			TlsSetValue(dwTLSCurrentContext, (LPVOID)hGLRC);
-		}
-		__except(EXCEPTION_EXECUTE_HANDLER) {
-			iCurrentContext = hGLRC;
-		}
-	}
-	// store in global static var
-	else {
-		iCurrentContext = hGLRC;
-	}
-#else
-	iCurrentContext = hGLRC;
-#endif
-}
-
-// ***********************************************************************
-
-// Return the current HDC only for a currently active HGLRC.
-HDC dglGetCurrentDC(void)
-{
-	HGLRC hGLRC;
-	DGL_ctx* lpCtx;
-
-	hGLRC = dglGetCurrentContext();
-	if (hGLRC) {
-		lpCtx = dglGetContextAddress(hGLRC);
-		return lpCtx->hDC;
-	}
-	return 0;
-}
-
-// ***********************************************************************
-
-void dglInitContextState()
-{
-	int i;
-	WNDCLASS wc;
-
-#ifdef GLD_THREADS
-	// Allocate thread local storage indexes for current context and pixel format
-	dwTLSCurrentContext = TlsAlloc();
-	dwTLSPixelFormat = TlsAlloc();
-#endif
-
-	dglSetCurrentContext(NULL); // No current rendering context
-
-	 // Clear all context data
-	ZeroMemory(ctxlist, sizeof(ctxlist[0]) * DGL_MAX_CONTEXTS);
-
-	for (i=0; i<DGL_MAX_CONTEXTS; i++)
-		ctxlist[i].bAllocated = FALSE; // Flag context as unused
-
-	// This section of code crashes the dll in circumstances where the app
-	// creates and destroys contexts.
-/*
-	// Register the class for our event monitor window
-	wc.style = 0;
-	wc.lpfnWndProc = GLD_EventWndProc;
-	wc.cbClsExtra = 0;
-	wc.cbWndExtra = 0;
-	wc.hInstance = GetModuleHandle(NULL);
-	wc.hIcon = LoadIcon(GetModuleHandle(NULL), IDI_APPLICATION);
-	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
-	wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
-	wc.lpszMenuName = NULL;
-	wc.lpszClassName = "GLDIRECT";
-	RegisterClass(&wc);
-
-	// Create the non-visible window to monitor all broadcast messages
-	hWndEvent = CreateWindowEx(
-		WS_EX_TOOLWINDOW,"GLDIRECT","GLDIRECT",WS_POPUP,
-		0,0,0,0,
-		NULL,NULL,GetModuleHandle(NULL),NULL);
-*/
-
-#ifdef GLD_THREADS
-	// Create a critical section object for serializing access to
-	// DirectDraw and DDStereo create/destroy functions in multiple threads
-	if (glb.bMultiThreaded)
-		InitializeCriticalSection(&CriticalSection);
-#endif
-
-	// Context state is now initialized and ready
-	bContextReady = TRUE;
-}
-
-// ***********************************************************************
-
-void dglDeleteContextState()
-{
-	int i;
-	static BOOL bOnceIsEnough = FALSE;
-
-	// Only call once, from either DGL_exitDriver(), or DLL_PROCESS_DETACH
-	if (bOnceIsEnough)
-		return;
-	bOnceIsEnough = TRUE;
-
-	for (i=0; i<DGL_MAX_CONTEXTS; i++) {
-		if (ctxlist[i].bAllocated == TRUE) {
-			ddlogPrintf(DDLOG_WARN, "** Context %i not deleted - cleaning up.", (i+1));
-			dglDeleteContext((HGLRC)(i+1));
-		}
-	}
-
-	// Context state is no longer ready
-	bContextReady = FALSE;
-
-    // If executed when DLL unloads, DDraw objects may be invalid.
-    // So catch any page faults with this exception handler.
-__try {
-
-	// Release final DirectDraw interfaces
-	if (glb.bDirectDrawPersistant) {
-//		RELEASE(glb.lpGlobalPalette);
-//		RELEASE(glb.lpDepth4);
-//		RELEASE(glb.lpBack4);
-//		RELEASE(glb.lpPrimary4);
-//	    RELEASE(glb.lpDD4);
-    }
-}
-__except(EXCEPTION_EXECUTE_HANDLER) {
-    ddlogPrintf(DDLOG_WARN, "Exception raised in dglDeleteContextState.");
-}
-
-	// Destroy our event monitor window
-	if (hWndEvent) {
-		DestroyWindow(hWndEvent);
-		hWndEvent = hWndLastActive = NULL;
-	}
-
-#ifdef GLD_THREADS
-	// Destroy the critical section object
-	if (glb.bMultiThreaded)
-		DeleteCriticalSection(&CriticalSection);
-
-	// Release thread local storage indexes for current HGLRC and pixel format
-	TlsFree(dwTLSPixelFormat);
-	TlsFree(dwTLSCurrentContext);
-#endif
-}
-
-// ***********************************************************************
-
-// Application Window message handler interception
-static LONG __stdcall dglWndProc(
-	HWND hwnd,
-	UINT msg,
-	WPARAM wParam,
-	LPARAM lParam)
-{
-	DGL_ctx* 	lpCtx = NULL;
-	LONG 		lpfnWndProc = 0L;
-	int  		i;
-	HGLRC 		hGLRC;
-	RECT 		rect;
-	PAINTSTRUCT	ps;
-    BOOL        bQuit = FALSE;
-    BOOL        bMain = FALSE;
-    LONG        rc;
-
-    // Get the window's message handler *before* it is unhooked in WM_DESTROY
-
-    // Is this the main window?
-    if (hwnd == glb.hWndActive) {
-        bMain = TRUE;
-        lpfnWndProc = glb.lpfnWndProc;
-    }
-    // Search for DGL context matching window handle
-    for (i=0; i<DGL_MAX_CONTEXTS; i++) {
-	    if (ctxlist[i].hWnd == hwnd) {
-	        lpCtx = &ctxlist[i];
-	        lpfnWndProc = lpCtx->lpfnWndProc;
-		    break;
-        }
-    }
-	// Not one of ours...
-	if (!lpfnWndProc)
-	    return DefWindowProc(hwnd, msg, wParam, lParam);
-
-    // Intercept messages amd process *before* passing on to window
-	switch (msg) {
-#ifdef _USE_GLD3_WGL
-	case WM_DISPLAYCHANGE:
-		glb.bPixelformatsDirty = TRUE;
-		break;
-#endif
-	case WM_ACTIVATEAPP:
-		glb.bAppActive = (BOOL)wParam;
-		ddlogPrintf(DDLOG_INFO, "Calling app has been %s", glb.bAppActive ? "activated" : "de-activated");
-		break;
-	case WM_ERASEBKGND:
-		// Eat the GDI erase event for the GL window
-        if (!lpCtx || !lpCtx->bHasBeenCurrent)
-            break;
-		lpCtx->bGDIEraseBkgnd = TRUE;
-		return TRUE;
-	case WM_PAINT:
-		// Eat the invalidated update region if render scene is in progress
-        if (!lpCtx || !lpCtx->bHasBeenCurrent)
-            break;
-		if (lpCtx->bFrameStarted) {
-			if (GetUpdateRect(hwnd, &rect, FALSE)) {
-				BeginPaint(hwnd, &ps);
-				EndPaint(hwnd, &ps);
-				ValidateRect(hwnd, &rect);
-				return TRUE;
-				}
-			}
-		break;
-	}
-	// Call the appropriate window message handler
-	rc = CallWindowProc((WNDPROC)lpfnWndProc, hwnd, msg, wParam, lParam);
-
-    // Intercept messages and process *after* passing on to window
-	switch (msg) {
-    case WM_QUIT:
-	case WM_DESTROY:
-        bQuit = TRUE;
-		if (lpCtx && lpCtx->bAllocated) {
-			ddlogPrintf(DDLOG_WARN, "WM_DESTROY detected for HWND=%X, HDC=%X, HGLRC=%d", hwnd, lpCtx->hDC, i+1);
-			dglDeleteContext((HGLRC)(i+1));
-		}
-		break;
-#if 0
-	case WM_SIZE:
-		// Resize surfaces to fit window but not viewport (in case app did not bother)
-        if (!lpCtx || !lpCtx->bHasBeenCurrent)
-            break;
-		w = LOWORD(lParam);
-		h = HIWORD(lParam);
-		if (lpCtx->dwWidth < w || lpCtx->dwHeight < h) {
-			if (!dglWglResizeBuffers(lpCtx->glCtx, TRUE))
-                 dglWglResizeBuffers(lpCtx->glCtx, FALSE);
-        }
-		break;
-#endif
-    }
-
-    // If the main window is quitting, then so should we...
-    if (bMain && bQuit) {
-		ddlogPrintf(DDLOG_SYSTEM, "shutting down after WM_DESTROY detected for main HWND=%X", hwnd);
-        dglDeleteContextState();
-        dglExitDriver();
-    }
-
-    return rc;
-}
-
-// ***********************************************************************
-
-// Driver Window message handler
-static LONG __stdcall GLD_EventWndProc(
-	HWND hwnd,
-	UINT msg,
-	WPARAM wParam,
-	LPARAM lParam)
-{
-	switch (msg) {
-        // May be sent by splash screen dialog on exit
-        case WM_ACTIVATE:
-            if (LOWORD(wParam) == WA_ACTIVE && glb.hWndActive) {
-                SetForegroundWindow(glb.hWndActive);
-                return 0;
-                }
-            break;
-	}
-	return DefWindowProc(hwnd, msg, wParam, lParam);
-}
-
-// ***********************************************************************
-
-// Intercepted Keyboard handler for detecting hot keys.
-LRESULT CALLBACK dglKeyProc(
-	int code,
-	WPARAM wParam,
-	LPARAM lParam)
-{
-	HWND hWnd, hWndFrame;
-	HGLRC hGLRC = NULL;
-	DGL_ctx* lpCtx = NULL;
-	int cmd = 0, dx1 = 0, dx2 = 0, i;
-	static BOOL bAltPressed = FALSE;
-	static BOOL bCtrlPressed = FALSE;
-	static BOOL bShiftPressed = FALSE;
-    RECT r, rf, rc;
-    POINT pt;
-    BOOL bForceReshape = FALSE;
-
-	return CallNextHookEx(hKeyHook, code, wParam, lParam);
-}
-
-// ***********************************************************************
-
-HWND hWndMatch;
-
-// Window handle enumeration procedure.
-BOOL CALLBACK dglEnumChildProc(
-    HWND hWnd,
-    LPARAM lParam)
-{
-    RECT rect;
-
-    // Find window handle with matching client rect.
-    GetClientRect(hWnd, &rect);
-    if (EqualRect(&rect, (RECT*)lParam)) {
-        hWndMatch = hWnd;
-        return FALSE;
-        }
-    // Continue with next child window.
-    return TRUE;
-}
-
-// ***********************************************************************
-
-// Find window handle with matching client rect.
-HWND dglFindWindowRect(
-    RECT* pRect)
-{
-    hWndMatch = NULL;
-    EnumChildWindows(GetForegroundWindow(), dglEnumChildProc, (LPARAM)pRect);
-    return hWndMatch;
-}
-
-// ***********************************************************************
-#ifndef _USE_GLD3_WGL
-void dglChooseDisplayMode(
-	DGL_ctx *lpCtx)
-{
-	// Note: Choose an exact match if possible.
-
-	int				i;
-	DWORD			area;
-	DWORD			bestarea;
-	DDSURFACEDESC2	*lpDDSD		= NULL;	// Mode list pointer
-	DDSURFACEDESC2	*lpBestDDSD = NULL;	// Pointer to best
-
-	lpDDSD = glb.lpDisplayModes;
-	for (i=0; i<glb.nDisplayModeCount; i++, lpDDSD++) {
-		if ((lpDDSD->dwWidth == lpCtx->dwWidth) &&
-			(lpDDSD->dwHeight == lpCtx->dwHeight))
-			goto matched; // Mode has been exactly matched
-		// Choose modes that are larger in both dimensions than
-		// the window, but smaller in area than the current best.
-		if ( (lpDDSD->dwWidth >= lpCtx->dwWidth) &&
-			 (lpDDSD->dwHeight >= lpCtx->dwHeight))
-		{
-			if (lpBestDDSD == NULL) {
-				lpBestDDSD = lpDDSD;
-				bestarea = lpDDSD->dwWidth * lpDDSD->dwHeight;
-				continue;
-			}
-			area = lpDDSD->dwWidth * lpDDSD->dwHeight;
-			if (area < bestarea) {
-				lpBestDDSD = lpDDSD;
-				bestarea = area;
-			}
-		}
-	}
-
-	// Safety check
-	if (lpBestDDSD == NULL) {
-		ddlogMessage(DDLOG_CRITICAL, "dglChooseDisplayMode");
-		return;
-	}
-
-	lpCtx->dwModeWidth = lpBestDDSD->dwWidth;
-	lpCtx->dwModeHeight = lpBestDDSD->dwHeight;
-matched:
-	ddlogPrintf(DDLOG_INFO, "Matched (%ldx%ld) to (%ldx%ld)",
-		lpCtx->dwWidth, lpCtx->dwHeight, lpCtx->dwModeWidth, lpCtx->dwModeHeight);
-}
-#endif // _USE_GLD3_WGL
-// ***********************************************************************
-
-static BOOL IsDevice(
-	DWORD *lpDeviceIdList,
-	DWORD dwDeviceId,
-	int count)
-{
-	int i;
-
-	for (i=0; i<count; i++)
-		if (dwDeviceId == lpDeviceIdList[i])
-			return TRUE;
-
-	return FALSE;
-}
-
-// ***********************************************************************
-
-void dglTestForBrokenCards(
-	DGL_ctx *lpCtx)
-{
-#ifndef _GLD3
-	DDDEVICEIDENTIFIER	dddi; // DX6 device identifier
-
-	// Sanity check.
-	if (lpCtx == NULL) {
-		// Testing for broken cards is sensitive area, so we don't want
-		// anything saying "broken cards" in the error message. ;)
-		ddlogMessage(DDLOG_ERROR, "Null context passed to TFBC\n");
-		return;
-	}
-
-	if (lpCtx->lpDD4 == NULL) {
-		// Testing for broken cards is sensitive area, so we don't want
-		// anything saying "broken cards" in the error message. ;)
-		ddlogMessage(DDLOG_ERROR, "Null DD4 passed to TFBC\n");
-		return;
-	}
-
-	// Microsoft really fucked up with the GetDeviceIdentifier function
-	// on Windows 2000, since it locks up on stock driers on the CD. Updated
-	// drivers from vendors appear to work, but we can't identify the drivers
-	// without this function!!! For now we skip these tests on Windows 2000.
-	if ((GetVersion() & 0x80000000UL) == 0)
-		return;
-
-	// Obtain device info
-	if (FAILED(IDirectDraw4_GetDeviceIdentifier(lpCtx->lpDD4, &dddi, 0)))
-		return;
-
-	// Useful info. Log it.
-	ddlogPrintf(DDLOG_INFO, "DirectDraw: VendorId=0x%x, DeviceId=0x%x", dddi.dwVendorId, dddi.dwDeviceId);
-
-	// Vendor 1: ATI
-	if (dddi.dwVendorId == VENDORID_ATI) {
-		// Test A: ATI Rage PRO
-		if (IsDevice(devATIRagePro, dddi.dwDeviceId, sizeof(devATIRagePro)))
-			glb.bUseMipmaps = FALSE;
-		// Test B: ATI Rage II+
-		if (IsDevice(devATIRageIIplus, dddi.dwDeviceId, sizeof(devATIRageIIplus)))
-			glb.bEmulateAlphaTest = TRUE;
-	}
-
-	// Vendor 2: Matrox
-	if (dddi.dwVendorId == 0x102B) {
-		// Test: Matrox G400 stencil buffer support does not work for AutoCAD
-		if (dddi.dwDeviceId == 0x0525) {
-			lpCtx->lpPF->pfd.cStencilBits = 0;
-			if (lpCtx->lpPF->iZBufferPF != -1) {
-				glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF].dwStencilBitDepth = 0;
-				glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF].dwStencilBitMask = 0;
-				glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF].dwFlags &= ~DDPF_STENCILBUFFER;
-			}
-		}
-	}
-#endif // _GLD3
-}
-
-// ***********************************************************************
-
-BOOL dglCreateContextBuffers(
-	HDC a,
-	DGL_ctx *lpCtx,
-	BOOL bFallback)
-{
-	HRESULT				hResult;
-
-	int					i;
-//	HGLRC				hGLRC;
-//	DGL_ctx*			lpCtx;
-
-#ifndef _USE_GLD3_WGL
-	DWORD				dwFlags;
-	DDSURFACEDESC2		ddsd2;
-	DDSCAPS2			ddscaps2;
-	LPDIRECTDRAWCLIPPER	lpddClipper;
-	D3DDEVICEDESC		D3DHWDevDesc;	// Direct3D Hardware description
-	D3DDEVICEDESC		D3DHELDevDesc;	// Direct3D Hardware Emulation Layer
-#endif // _USE_GLD3_WGL
-
-	float				inv_aspect;
-
-	GLenum				bDoubleBuffer;	// TRUE if double buffer required
-	GLenum				bDepthBuffer;	// TRUE if depth buffer required
-
-	const PIXELFORMATDESCRIPTOR	*lpPFD = &lpCtx->lpPF->pfd;
-
-	// Vars for Mesa visual
-	DWORD				dwDepthBits		= 0;
-	DWORD				dwStencilBits	= 0;
-	DWORD				dwAlphaBits		= 0;
-	DWORD				bAlphaSW		= GL_FALSE;
-	DWORD				bDouble			= GL_FALSE;
-
-	DDSURFACEDESC2 		ddsd2DisplayMode;
-	BOOL				bFullScrnWin	= FALSE;	// fullscreen-size window ?
-	DDBLTFX 			ddbltfx;
-	DWORD				dwMemoryType 	= (bFallback) ? DDSCAPS_SYSTEMMEMORY : glb.dwMemoryType;
-	BOOL				bBogusWindow	= FALSE;	// non-drawable window ?
-	DWORD               dwColorRef      = 0;        // GDI background color
-	RECT				rcDst;						// GDI window rect
-	POINT				pt;							// GDI window point
-
-	// Palette used for creating default global palette
-	PALETTEENTRY	ppe[256];
-
-#ifndef _USE_GLD3_WGL
-	// Vertex buffer description. Used for creation of vertex buffers
-	D3DVERTEXBUFFERDESC vbufdesc;
-#endif // _USE_GLD3_WGL
-
-#define DDLOG_CRITICAL_OR_WARN	(bFallback ? DDLOG_CRITICAL : DDLOG_WARN)
-
-	ddlogPrintf(DDLOG_SYSTEM, "dglCreateContextBuffers for HDC=%X", a);
-    nContextError = GLDERR_NONE;
-
-#ifdef GLD_THREADS
-	// Serialize access to DirectDraw object creation or DDS start
-	if (glb.bMultiThreaded)
-		EnterCriticalSection(&CriticalSection);
-#endif
-
-	// Check for back buffer
-	bDoubleBuffer = GL_TRUE; //(lpPFD->dwFlags & PFD_DOUBLEBUFFER) ? GL_TRUE : GL_FALSE;
-	// Since we always do back buffering, check if we emulate front buffering
-	lpCtx->EmulateSingle =
-		(lpPFD->dwFlags & PFD_DOUBLEBUFFER) ? FALSE : TRUE;
-#if 0	// Don't have to mimic MS OpenGL behavior for front-buffering (DaveM)
-	lpCtx->EmulateSingle |=
-		(lpPFD->dwFlags & PFD_SUPPORT_GDI) ? TRUE : FALSE;
-#endif
-
-	// Check for depth buffer
-	bDepthBuffer = (lpPFD->cDepthBits) ? GL_TRUE : GL_FALSE;
-
-	lpCtx->bDoubleBuffer = bDoubleBuffer;
-	lpCtx->bDepthBuffer = bDepthBuffer;
-
-	// Set the Fullscreen flag for the context.
-//	lpCtx->bFullscreen = glb.bFullscreen;
-
-	// Obtain the dimensions of the rendering window
-	lpCtx->hDC = a; // Cache DC
-	lpCtx->hWnd = WindowFromDC(lpCtx->hDC);
-	// Check for non-window DC = memory DC ?
-	if (lpCtx->hWnd == NULL) {
-        // bitmap memory contexts are always single-buffered
-        lpCtx->EmulateSingle = TRUE;
-		bBogusWindow = TRUE;
-		ddlogPrintf(DDLOG_INFO, "Non-Window Memory Device Context");
-		if (GetClipBox(lpCtx->hDC, &lpCtx->rcScreenRect) == ERROR) {
-			ddlogMessage(DDLOG_WARN, "GetClipBox failed in dglCreateContext\n");
-			SetRect(&lpCtx->rcScreenRect, 0, 0, 0, 0);
-		}
-	}
-	else if (!GetClientRect(lpCtx->hWnd, &lpCtx->rcScreenRect)) {
-		bBogusWindow = TRUE;
-		ddlogMessage(DDLOG_WARN, "GetClientRect failed in dglCreateContext\n");
-		SetRect(&lpCtx->rcScreenRect, 0, 0, 0, 0);
-	}
-	lpCtx->dwWidth = lpCtx->rcScreenRect.right - lpCtx->rcScreenRect.left;
-	lpCtx->dwHeight = lpCtx->rcScreenRect.bottom - lpCtx->rcScreenRect.top;
-
-	ddlogPrintf(DDLOG_INFO, "Input window %X: w=%i, h=%i",
-							lpCtx->hWnd, lpCtx->dwWidth, lpCtx->dwHeight);
-
-	// What if app only zeroes one dimension instead of both? (DaveM)
-	if ( (lpCtx->dwWidth == 0) || (lpCtx->dwHeight == 0) ) {
-		// Make the buffer size something sensible
-		lpCtx->dwWidth = 8;
-		lpCtx->dwHeight = 8;
-	}
-
-	// Set defaults
-	lpCtx->dwModeWidth = lpCtx->dwWidth;
-	lpCtx->dwModeHeight = lpCtx->dwHeight;
-/*
-	// Find best display mode for fullscreen
-	if (glb.bFullscreen || !glb.bPrimary) {
-		dglChooseDisplayMode(lpCtx);
-	}
-*/
-	// Misc initialisation
-	lpCtx->bCanRender = FALSE; // No rendering allowed yet
-	lpCtx->bSceneStarted = FALSE;
-	lpCtx->bFrameStarted = FALSE;
-
-	// Detect OS (specifically 'Windows 2000' or 'Windows XP')
-	DetectOS();
-
-	// NOTE: WinNT not supported
-	ddlogPrintf(DDLOG_INFO, "OS: %s", bHaveWin95 ? "Win9x" : (bHaveWin2K ? "Win2000/XP" : "Unsupported") );
-
-	// Test for Fullscreen
-	if (bHaveWin95) { // Problems with fullscreen on Win2K/XP
-		if ((GetSystemMetrics(SM_CXSCREEN) == lpCtx->dwWidth) && 
-			(GetSystemMetrics(SM_CYSCREEN) == lpCtx->dwHeight))
-		{
-			// Workaround for some apps that crash when going fullscreen.
-			//lpCtx->bFullscreen = TRUE;
-		}
-		
-	}
-
-#ifdef _USE_GLD3_WGL
-	_gldDriver.CreateDrawable(lpCtx, glb.bDirectDrawPersistant, glb.bPersistantBuffers);
-#else
-	// Check if DirectDraw has already been created by original GLRC (DaveM)
-	if (glb.bDirectDrawPersistant && glb.bDirectDraw) {
-		lpCtx->lpDD4 = glb.lpDD4;
-		IDirectDraw4_AddRef(lpCtx->lpDD4);
-		goto SkipDirectDrawCreate;
-	}
-
-	// Create DirectDraw object
-	if (glb.bPrimary)
-		hResult = DirectDrawCreate(NULL, &lpCtx->lpDD1, NULL);
-	else {
-		// A non-primary device is to be used.
-		// Force context to be Fullscreen, secondary adaptors can not
-		// be used in a window.
-		hResult = DirectDrawCreate(&glb.ddGuid, &lpCtx->lpDD1, NULL);
-		lpCtx->bFullscreen = TRUE;
-	}
-	if (FAILED(hResult)) {
-		MessageBox(NULL, "Unable to initialize DirectDraw", "GLDirect", MB_OK);
-		ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to create DirectDraw interface", hResult);
-        nContextError = GLDERR_DDRAW;
-		goto return_with_error;
-	}
-
-	// Query for DX6 IDirectDraw4.
-	hResult = IDirectDraw_QueryInterface(lpCtx->lpDD1,
-										 &IID_IDirectDraw4,
-										 (void**)&lpCtx->lpDD4);
-	if (FAILED(hResult)) {
-		MessageBox(NULL, "GLDirect requires DirectX 6.0 or above", "GLDirect", MB_OK);
-		ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to create DirectDraw4 interface", hResult);
-        nContextError = GLDERR_DDRAW;
-		goto return_with_error;
-	}
-
-	// Cache DirectDraw interface for subsequent GLRCs
-	if (glb.bDirectDrawPersistant && !glb.bDirectDraw) {
-		glb.lpDD4 = lpCtx->lpDD4;
-		IDirectDraw4_AddRef(glb.lpDD4);
-		glb.bDirectDraw = TRUE;
-	}
-SkipDirectDrawCreate:
-
-	// Now we have a DD4 interface we can check for broken cards
-	dglTestForBrokenCards(lpCtx);
-
-	// Test if primary device can use flipping instead of blitting
-	ZeroMemory(&ddsd2DisplayMode, sizeof(ddsd2DisplayMode));
-	ddsd2DisplayMode.dwSize = sizeof(ddsd2DisplayMode);
-	hResult = IDirectDraw4_GetDisplayMode(
-					lpCtx->lpDD4,
-					&ddsd2DisplayMode);
-	if (SUCCEEDED(hResult)) {
-		if ( (lpCtx->dwWidth == ddsd2DisplayMode.dwWidth) &&
-				 (lpCtx->dwHeight == ddsd2DisplayMode.dwHeight) ) {
-			// We have a fullscreen-size window
-			bFullScrnWin = TRUE;
-			// OK to use DirectDraw fullscreen mode ?
-			if (glb.bPrimary && !glb.bFullscreenBlit && !lpCtx->EmulateSingle && !glb.bDirectDrawPersistant) {
-				lpCtx->bFullscreen = TRUE;
-				ddlogMessage(DDLOG_INFO, "Primary upgraded to page flipping.\n");
-			}
-		}
-		// Cache the display mode dimensions
-		lpCtx->dwModeWidth = ddsd2DisplayMode.dwWidth;
-		lpCtx->dwModeHeight = ddsd2DisplayMode.dwHeight;
-	}
-
-	// Clamp the effective window dimensions to primary surface.
-	// We need to do this for D3D viewport dimensions even if wide
-	// surfaces are supported. This also is a good idea for handling
-	// whacked-out window dimensions passed for non-drawable windows
-	// like Solid Edge. (DaveM)
-	if (lpCtx->dwWidth > ddsd2DisplayMode.dwWidth)
-		lpCtx->dwWidth = ddsd2DisplayMode.dwWidth;
-	if (lpCtx->dwHeight > ddsd2DisplayMode.dwHeight)
-		lpCtx->dwHeight = ddsd2DisplayMode.dwHeight;
-
-	// Check for non-RGB desktop resolution
-	if (!lpCtx->bFullscreen && ddsd2DisplayMode.ddpfPixelFormat.dwRGBBitCount <= 8) {
-		ddlogPrintf(DDLOG_CRITICAL_OR_WARN, "Desktop color depth %d bpp not supported",
-			ddsd2DisplayMode.ddpfPixelFormat.dwRGBBitCount);
-        nContextError = GLDERR_BPP;
-		goto return_with_error;
-	}
-#endif // _USE_GLD3_WGL
-
-	ddlogPrintf(DDLOG_INFO, "Window: w=%i, h=%i (%s)",
-							lpCtx->dwWidth,
-							lpCtx->dwHeight,
-							lpCtx->bFullscreen ? "fullscreen" : "windowed");
-
-#ifndef _USE_GLD3_WGL
-	// Obtain ddraw caps
-    ZeroMemory(&lpCtx->ddCaps, sizeof(DDCAPS));
-	lpCtx->ddCaps.dwSize = sizeof(DDCAPS);
-	if (glb.bHardware) {
-		// Get HAL caps
-		IDirectDraw4_GetCaps(lpCtx->lpDD4, &lpCtx->ddCaps, NULL);
-	} else {
-		// Get HEL caps
-		IDirectDraw4_GetCaps(lpCtx->lpDD4, NULL, &lpCtx->ddCaps);
-	}
-
-	// If this flag is present then we can't default to Mesa
-	// SW rendering between BeginScene() and EndScene().
-	if (lpCtx->ddCaps.dwCaps2 & DDCAPS2_NO2DDURING3DSCENE) {
-		ddlogMessage(DDLOG_INFO,
-			"Warning          : No 2D allowed during 3D scene.\n");
-	}
-
-	// Query for DX6 Direct3D3 interface
-	hResult = IDirectDraw4_QueryInterface(lpCtx->lpDD4,
-										  &IID_IDirect3D3,
-										  (void**)&lpCtx->lpD3D3);
-	if (FAILED(hResult)) {
-		MessageBox(NULL, "Unable to initialize Direct3D", "GLDirect", MB_OK);
-		ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to create Direct3D interface", hResult);
-        nContextError = GLDERR_D3D;
-		goto return_with_error;
-	}
-
-	// Context creation
-	if (lpCtx->bFullscreen) {
-		// FULLSCREEN
-
-        // Disable warning popups when in fullscreen mode
-        ddlogWarnOption(FALSE);
-
-		// Have to release persistant primary surface if fullscreen mode
-		if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary) {
-			RELEASE(glb.lpPrimary4);
-			glb.bDirectDrawPrimary = FALSE;
-		}
-
-		dwFlags = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT;
-		if (glb.bFastFPU)
-			dwFlags |= DDSCL_FPUSETUP;	// fast FPU setup optional (DaveM)
-		hResult = IDirectDraw4_SetCooperativeLevel(lpCtx->lpDD4, lpCtx->hWnd, dwFlags);
-		if (FAILED(hResult)) {
-			ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to set Exclusive Fullscreen mode", hResult);
-			goto return_with_error;
-		}
-
-		hResult = IDirectDraw4_SetDisplayMode(lpCtx->lpDD4,
-											  lpCtx->dwModeWidth,
-											  lpCtx->dwModeHeight,
-											  lpPFD->cColorBits,
-											  0,
-											  0);
-		if (FAILED(hResult)) {
-			ddlogError(DDLOG_CRITICAL_OR_WARN, "SetDisplayMode failed", hResult);
-			goto return_with_error;
-		}
-
-		// ** The display mode has changed, so dont use MessageBox! **
-
-		ZeroMemory(&ddsd2, sizeof(ddsd2));
-		ddsd2.dwSize = sizeof(ddsd2);
-
-		if (bDoubleBuffer) {
-			// Double buffered
-			// Primary surface
-			ddsd2.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
-			ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
-								   DDSCAPS_FLIP |
-								   DDSCAPS_COMPLEX |
-								   DDSCAPS_3DDEVICE |
-								   dwMemoryType;
-			ddsd2.dwBackBufferCount = 1;
-
-			hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpFront4, NULL);
-			if (FAILED(hResult)) {
-				ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateSurface (primary) failed", hResult);
-                nContextError = GLDERR_MEM;
-				goto return_with_error;
-			}
-
-			// Render target surface
-			ZeroMemory(&ddscaps2, sizeof(ddscaps2)); // Clear the entire struct.
-			ddscaps2.dwCaps = DDSCAPS_BACKBUFFER;
-			hResult = IDirectDrawSurface4_GetAttachedSurface(lpCtx->lpFront4, &ddscaps2, &lpCtx->lpBack4);
-			if (FAILED(hResult)) {
-				ddlogError(DDLOG_CRITICAL_OR_WARN, "GetAttachedSurface failed", hResult);
-                nContextError = GLDERR_MEM;
-				goto return_with_error;
-			}
-		} else {
-			// Single buffered
-			// Primary surface
-			ddsd2.dwFlags = DDSD_CAPS;
-			ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
-								   //DDSCAPS_3DDEVICE |
-								   dwMemoryType;
-
-			hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpFront4, NULL);
-			if (FAILED(hResult)) {
-				ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateSurface (primary) failed", hResult);
-                nContextError = GLDERR_MEM;
-				goto return_with_error;
-			}
-
-			lpCtx->lpBack4 = NULL;
-		}
-	} else {
-		// WINDOWED
-
-        // OK to enable warning popups in windowed mode
-        ddlogWarnOption(glb.bMessageBoxWarnings);
-
-		dwFlags = DDSCL_NORMAL;
-		if (glb.bMultiThreaded)
-			dwFlags |= DDSCL_MULTITHREADED;
-		if (glb.bFastFPU)
-			dwFlags |= DDSCL_FPUSETUP;	// fast FPU setup optional (DaveM)
-		hResult = IDirectDraw4_SetCooperativeLevel(lpCtx->lpDD4,
-												  lpCtx->hWnd,
-												  dwFlags);
-		if (FAILED(hResult)) {
-			ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to set Normal coop level", hResult);
-			goto return_with_error;
-		}
-		// Has Primary surface already been created for original GLRC ?
-		// Note this can only be applicable for windowed modes
-		if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary) {
-			lpCtx->lpFront4 = glb.lpPrimary4;
-			IDirectDrawSurface4_AddRef(lpCtx->lpFront4);
-			// Update the window on the default clipper
-			IDirectDrawSurface4_GetClipper(lpCtx->lpFront4, &lpddClipper);
-			IDirectDrawClipper_SetHWnd(lpddClipper, 0, lpCtx->hWnd);
-			IDirectDrawClipper_Release(lpddClipper);
-			goto SkipPrimaryCreate;
-		}
-
-		// Primary surface
-		ZeroMemory(&ddsd2, sizeof(ddsd2));
-		ddsd2.dwSize = sizeof(ddsd2);
-		ddsd2.dwFlags = DDSD_CAPS;
-		ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
-		hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpFront4, NULL);
-		if (FAILED(hResult)) {
-			ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateSurface (primary) failed", hResult);
-            nContextError = GLDERR_MEM;
-			goto return_with_error;
-		}
-
-		// Cache Primary surface for subsequent GLRCs
-		// Note this can only be applicable to subsequent windowed modes
-		if (glb.bDirectDrawPersistant && !glb.bDirectDrawPrimary) {
-			glb.lpPrimary4 = lpCtx->lpFront4;
-			IDirectDrawSurface4_AddRef(glb.lpPrimary4);
-			glb.bDirectDrawPrimary = TRUE;
-		}
-
-		// Clipper object
-		hResult = DirectDrawCreateClipper(0, &lpddClipper, NULL);
-		if (FAILED(hResult)) {
-			ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateClipper failed", hResult);
-			goto return_with_error;
-		}
-		hResult = IDirectDrawClipper_SetHWnd(lpddClipper, 0, lpCtx->hWnd);
-		if (FAILED(hResult)) {
-			RELEASE(lpddClipper);
-			ddlogError(DDLOG_CRITICAL_OR_WARN, "SetHWnd failed", hResult);
-			goto return_with_error;
-		}
-		hResult = IDirectDrawSurface4_SetClipper(lpCtx->lpFront4, lpddClipper);
-		RELEASE(lpddClipper); // We have finished with it.
-		if (FAILED(hResult)) {
-			ddlogError(DDLOG_CRITICAL_OR_WARN, "SetClipper failed", hResult);
-			goto return_with_error;
-		}
-SkipPrimaryCreate:
-
-		if (bDoubleBuffer) {
-			// Render target surface
-			ZeroMemory(&ddsd2, sizeof(ddsd2));
-			ddsd2.dwSize = sizeof(ddsd2);
-			ddsd2.dwFlags        = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
-			ddsd2.dwWidth        = lpCtx->dwWidth;
-			ddsd2.dwHeight       = lpCtx->dwHeight;
-			ddsd2.ddsCaps.dwCaps = DDSCAPS_3DDEVICE |
-								   DDSCAPS_OFFSCREENPLAIN |
-								   dwMemoryType;
-
-			// Reserve the entire desktop size for persistant buffers option
-			if (glb.bDirectDrawPersistant && glb.bPersistantBuffers) {
-				ddsd2.dwWidth = ddsd2DisplayMode.dwWidth;
-				ddsd2.dwHeight = ddsd2DisplayMode.dwHeight;
-			}
-			// Re-use original back buffer if persistant buffers exist
-			if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && glb.lpBack4)
-				hResult = IDirectDrawSurface4_AddRef(lpCtx->lpBack4 = glb.lpBack4);
-			else
-				hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpBack4, NULL);
-			if (FAILED(hResult)) {
-				ddlogError(DDLOG_CRITICAL_OR_WARN, "Create Backbuffer failed", hResult);
-                nContextError = GLDERR_MEM;
-				goto return_with_error;
-			}
-			if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && !glb.lpBack4)
-				IDirectDrawSurface4_AddRef(glb.lpBack4 = lpCtx->lpBack4);
-		} else {
-			lpCtx->lpBack4 = NULL;
-		}
-	}
-
-	//
-	// Now create the Z-buffer
-	//
-	lpCtx->bStencil = FALSE; // Default to no stencil buffer
-	if (bDepthBuffer && (lpCtx->lpPF->iZBufferPF != -1)) {
-		// Get z-buffer dimensions from the render target
-		// Setup the surface desc for the z-buffer.
-		ZeroMemory(&ddsd2, sizeof(ddsd2));
-		ddsd2.dwSize = sizeof(ddsd2);
-		ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
-		ddsd2.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | dwMemoryType;
-		ddsd2.dwWidth = lpCtx->dwWidth;
-		ddsd2.dwHeight = lpCtx->dwHeight;
-		memcpy(&ddsd2.ddpfPixelFormat,
-			&glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF],
-			sizeof(DDPIXELFORMAT) );
-
-		// Reserve the entire desktop size for persistant buffers option
-		if (glb.bDirectDrawPersistant && glb.bPersistantBuffers) {
-			ddsd2.dwWidth = ddsd2DisplayMode.dwWidth;
-			ddsd2.dwHeight = ddsd2DisplayMode.dwHeight;
-		}
-
-		// Create a z-buffer
-		if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && glb.lpDepth4)
-			hResult = IDirectDrawSurface4_AddRef(lpCtx->lpDepth4 = glb.lpDepth4);
-		else
-			hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpDepth4, NULL);
-		if (FAILED(hResult)) {
-			ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateSurface (ZBuffer) failed", hResult);
-            nContextError = GLDERR_MEM;
-			goto return_with_error;
-		}
-		if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && !glb.lpDepth4)
-			IDirectDrawSurface4_AddRef(glb.lpDepth4 = lpCtx->lpDepth4);
-		else if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && glb.lpDepth4 && glb.lpBack4)
-			IDirectDrawSurface4_DeleteAttachedSurface(glb.lpBack4, 0, glb.lpDepth4);
-
-		// Attach Zbuffer to render target
-		TRY(IDirectDrawSurface4_AddAttachedSurface(
-			bDoubleBuffer ? lpCtx->lpBack4 : lpCtx->lpFront4,
-			lpCtx->lpDepth4),
-			"dglCreateContext: Attach Zbuffer");
-		if (glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF].dwFlags & DDPF_STENCILBUFFER) {
-			lpCtx->bStencil = TRUE;
-			ddlogMessage(DDLOG_INFO, "Depth buffer has stencil\n");
-		}
-	}
-
-	// Clear all back buffers and Z-buffers in case of memory recycling.
-	ZeroMemory(&ddbltfx, sizeof(ddbltfx));
-	ddbltfx.dwSize = sizeof(ddbltfx);
-	IDirectDrawSurface4_Blt(lpCtx->lpBack4, NULL, NULL, NULL,
-		DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
-	if (lpCtx->lpDepth4)
-		IDirectDrawSurface4_Blt(lpCtx->lpDepth4, NULL, NULL, NULL,
-			DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
-
-	// Now that we have a Z-buffer we can create the 3D device
-	hResult = IDirect3D3_CreateDevice(lpCtx->lpD3D3,
-									  &glb.d3dGuid,
-									  bDoubleBuffer ? lpCtx->lpBack4 : lpCtx->lpFront4,
-									  &lpCtx->lpDev3,
-									  NULL);
-	if (FAILED(hResult)) {
-		ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to create Direct3D device", hResult);
-        nContextError = GLDERR_D3D;
-		goto return_with_error;
-	}
-
-	// We must do this as soon as the device is created
-	dglInitStateCaches(lpCtx);
-
-	// Obtain the D3D Device Description
-	D3DHWDevDesc.dwSize = D3DHELDevDesc.dwSize = sizeof(D3DDEVICEDESC);
-	TRY(IDirect3DDevice3_GetCaps(lpCtx->lpDev3,
-								 &D3DHWDevDesc,
-								 &D3DHELDevDesc),
-								 "dglCreateContext: GetCaps failed");
-
-	// Choose the relevant description and cache it in the context.
-	// We will use this description later for caps checking
-	memcpy(	&lpCtx->D3DDevDesc,
-			glb.bHardware ? &D3DHWDevDesc : &D3DHELDevDesc,
-			sizeof(D3DDEVICEDESC));
-
-	// Now we can examine the texture formats
-	if (!dglBuildTextureFormatList(lpCtx->lpDev3)) {
-		ddlogMessage(DDLOG_CRITICAL_OR_WARN, "dglBuildTextureFormatList failed\n");
-		goto return_with_error;
-	}
-
-	// Get the pixel format of the back buffer
-	lpCtx->ddpfRender.dwSize = sizeof(lpCtx->ddpfRender);
-	if (bDoubleBuffer)
-		hResult = IDirectDrawSurface4_GetPixelFormat(
-					lpCtx->lpBack4,
-					&lpCtx->ddpfRender);
-	else
-		hResult = IDirectDrawSurface4_GetPixelFormat(
-					lpCtx->lpFront4,
-					&lpCtx->ddpfRender);
-
-	if (FAILED(hResult)) {
-		ddlogError(DDLOG_CRITICAL_OR_WARN, "GetPixelFormat failed", hResult);
-		goto return_with_error;
-	}
-	// Find a pixel packing function suitable for this surface
-	pxClassifyPixelFormat(&lpCtx->ddpfRender,
-						  &lpCtx->fnPackFunc,
-						  &lpCtx->fnUnpackFunc,
-						  &lpCtx->fnPackSpanFunc);
-
-	// Viewport
-	hResult = IDirect3D3_CreateViewport(lpCtx->lpD3D3, &lpCtx->lpViewport3, NULL);
-	if (FAILED(hResult)) {
-		ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateViewport failed", hResult);
-		goto return_with_error;
-	}
-
-	hResult = IDirect3DDevice3_AddViewport(lpCtx->lpDev3, lpCtx->lpViewport3);
-	if (FAILED(hResult)) {
-		ddlogError(DDLOG_CRITICAL_OR_WARN, "AddViewport failed", hResult);
-		goto return_with_error;
-	}
-
-	// Initialise the viewport
-	// Note screen coordinates are used for viewport clipping since D3D
-	// transform operations are not used in the GLD CAD driver. (DaveM)
-	inv_aspect = (float)lpCtx->dwHeight/(float)lpCtx->dwWidth;
-
-	lpCtx->d3dViewport.dwSize = sizeof(lpCtx->d3dViewport);
-	lpCtx->d3dViewport.dwX = 0;
-	lpCtx->d3dViewport.dwY = 0;
-	lpCtx->d3dViewport.dwWidth = lpCtx->dwWidth;
-	lpCtx->d3dViewport.dwHeight = lpCtx->dwHeight;
-	lpCtx->d3dViewport.dvClipX = 0; // -1.0f;
-	lpCtx->d3dViewport.dvClipY = 0; // inv_aspect;
-	lpCtx->d3dViewport.dvClipWidth = lpCtx->dwWidth; // 2.0f;
-	lpCtx->d3dViewport.dvClipHeight = lpCtx->dwHeight; // 2.0f * inv_aspect;
-	lpCtx->d3dViewport.dvMinZ = 0.0f;
-	lpCtx->d3dViewport.dvMaxZ = 1.0f;
-	TRY(IDirect3DViewport3_SetViewport2(lpCtx->lpViewport3, &lpCtx->d3dViewport), "dglCreateContext: SetViewport2");
-
-	hResult = IDirect3DDevice3_SetCurrentViewport(lpCtx->lpDev3, lpCtx->lpViewport3);
-	if (FAILED(hResult)) {
-		ddlogError(DDLOG_CRITICAL_OR_WARN, "SetCurrentViewport failed", hResult);
-		goto return_with_error;
-	}
-
-	lpCtx->dwBPP = lpPFD->cColorBits;
-	lpCtx->iZBufferPF = lpCtx->lpPF->iZBufferPF;
-
-	// Set last texture to NULL
-	for (i=0; i<MAX_TEXTURE_UNITS; i++) {
-		lpCtx->ColorOp[i] = D3DTOP_DISABLE;
-		lpCtx->AlphaOp[i] = D3DTOP_DISABLE;
-		lpCtx->tObj[i] = NULL;
-	}
-
-	// Default to perspective correct texture mapping
-	dglSetRenderState(lpCtx, D3DRENDERSTATE_TEXTUREPERSPECTIVE, TRUE, "TexturePersp");
-
-	// Set the default culling mode
-	lpCtx->cullmode = D3DCULL_NONE;
-	dglSetRenderState(lpCtx, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE, "CullMode");
-
-	// Disable specular
-	dglSetRenderState(lpCtx, D3DRENDERSTATE_SPECULARENABLE, FALSE, "SpecularEnable");
-	// Disable subpixel correction
-//	dglSetRenderState(lpCtx, D3DRENDERSTATE_SUBPIXEL, FALSE, "SubpixelEnable");
-	// Disable dithering
-	dglSetRenderState(lpCtx, D3DRENDERSTATE_DITHERENABLE, FALSE, "DitherEnable");
-
-	// Initialise the primitive caches
-//	lpCtx->dwNextLineVert	= 0;
-//	lpCtx->dwNextTriVert	= 0;
-
-	// Init the global texture palette
-	lpCtx->lpGlobalPalette = NULL;
-
-	// Init the HW/SW usage counters
-//	lpCtx->dwHWUsageCount = lpCtx->dwSWUsageCount = 0L;
-
-	//
-	// Create two D3D vertex buffers.
-	// One will hold the pre-transformed data with the other one
-	// being used to hold the post-transformed & clipped verts.
-	//
-#if 0  // never used (DaveM)
-	vbufdesc.dwSize = sizeof(D3DVERTEXBUFFERDESC);
-	vbufdesc.dwCaps = D3DVBCAPS_WRITEONLY;
-	if (glb.bHardware == FALSE)
-		vbufdesc.dwCaps = D3DVBCAPS_SYSTEMMEMORY;
-	vbufdesc.dwNumVertices = 32768; // For the time being
-
-	// Source vertex buffer
-	vbufdesc.dwFVF = DGL_LVERTEX;
-	hResult = IDirect3D3_CreateVertexBuffer(lpCtx->lpD3D3, &vbufdesc, &lpCtx->m_vbuf, 0, NULL);
-	if (FAILED(hResult)) {
-		ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateVertexBuffer(src) failed", hResult);
-		goto return_with_error;
-	}
-
-	// Destination vertex buffer
-	vbufdesc.dwFVF = (glb.bMultitexture == FALSE) ? D3DFVF_TLVERTEX : (D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX2);
-	hResult = IDirect3D3_CreateVertexBuffer(lpCtx->lpD3D3, &vbufdesc, &lpCtx->m_pvbuf, 0, NULL);
-	if(FAILED(hResult)) {
-		ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateVertexBuffer(dst) failed", hResult);
-		goto return_with_error;
-	}
-#endif
-
-#endif _USE_GLD3_WGL
-
-	//
-	//	Now create the Mesa context
-	//
-
-	// Create the Mesa visual
-	if (lpPFD->cDepthBits)
-		dwDepthBits = 16;
-	if (lpPFD->cStencilBits)
-		dwStencilBits = 8;
-	if (lpPFD->cAlphaBits) {
-		dwAlphaBits = 8;
-		bAlphaSW = GL_TRUE;
-	}
-	if (lpPFD->dwFlags & PFD_DOUBLEBUFFER)
-		bDouble = GL_TRUE;
-//	lpCtx->EmulateSingle =
-//		(lpPFD->dwFlags & PFD_DOUBLEBUFFER) ? FALSE : TRUE;
-
-#ifdef _USE_GLD3_WGL
-	lpCtx->glVis = _mesa_create_visual(
-		bDouble,    /* double buffer */
-		GL_FALSE,			// stereo
-		lpPFD->cRedBits,
-		lpPFD->cGreenBits,
-		lpPFD->cBlueBits,
-		dwAlphaBits,
-		dwDepthBits,
-		dwStencilBits,
-		lpPFD->cAccumRedBits,	// accum bits
-		lpPFD->cAccumGreenBits,	// accum bits
-		lpPFD->cAccumBlueBits,	// accum bits
-		lpPFD->cAccumAlphaBits,	// accum alpha bits
-		1				// num samples
-		);
-#else // _USE_GLD3_WGL
-	lpCtx->glVis = (*mesaFuncs.gl_create_visual)(
-		GL_TRUE,			// RGB mode
-		bAlphaSW,			// Is an alpha buffer required?
-		bDouble,			// Is an double-buffering required?
-		GL_FALSE,			// stereo
-		dwDepthBits,		// depth_size
-		dwStencilBits,		// stencil_size
-		lpPFD->cAccumBits,	// accum_size
-		0,					// colour-index bits
-		lpPFD->cRedBits,	// Red bit count
-		lpPFD->cGreenBits,	// Green bit count
-		lpPFD->cBlueBits,	// Blue bit count
-		dwAlphaBits			// Alpha bit count
-		);
-#endif // _USE_GLD3_WGL
-
-	if (lpCtx->glVis == NULL) {
-		ddlogMessage(DDLOG_CRITICAL_OR_WARN, "gl_create_visual failed\n");
-		goto return_with_error;
-	}
-
-#ifdef _USE_GLD3_WGL
-	lpCtx->glCtx = _mesa_create_context(lpCtx->glVis, NULL, (void *)lpCtx, GL_TRUE);
-#else
-	// Create the Mesa context
-	lpCtx->glCtx = (*mesaFuncs.gl_create_context)(
-					lpCtx->glVis,	// Mesa visual
-					NULL,			// share list context
-					(void *)lpCtx,	// Pointer to our driver context
-					GL_TRUE			// Direct context flag
-				   );
-#endif // _USE_GLD3_WGL
-
-	if (lpCtx->glCtx == NULL) {
-		ddlogMessage(DDLOG_CRITICAL_OR_WARN, "gl_create_context failed\n");
-		goto return_with_error;
-	}
-
-	// Create the Mesa framebuffer
-#ifdef _USE_GLD3_WGL
-	lpCtx->glBuffer = _mesa_create_framebuffer(
-		lpCtx->glVis,
-		lpCtx->glVis->depthBits > 0,
-		lpCtx->glVis->stencilBits > 0,
-		lpCtx->glVis->accumRedBits > 0,
-		GL_FALSE //swalpha
-		);
-#else
-	lpCtx->glBuffer = (*mesaFuncs.gl_create_framebuffer)(lpCtx->glVis);
-#endif // _USE_GLD3_WGL
-
-	if (lpCtx->glBuffer == NULL) {
-		ddlogMessage(DDLOG_CRITICAL_OR_WARN, "gl_create_framebuffer failed\n");
-		goto return_with_error;
-	}
-
-#ifdef _USE_GLD3_WGL
-	// Init Mesa internals
-	_swrast_CreateContext( lpCtx->glCtx );
-	_vbo_CreateContext( lpCtx->glCtx );
-	_tnl_CreateContext( lpCtx->glCtx );
-	_swsetup_CreateContext( lpCtx->glCtx );
-
-	_gldDriver.InitialiseMesa(lpCtx);
-	
-	lpCtx->glCtx->imports.warning	= _gld_mesa_warning;
-	lpCtx->glCtx->imports.fatal		= _gld_mesa_fatal;
-
-#else
-	// Tell Mesa how many texture stages we have
-	glb.wMaxSimultaneousTextures = lpCtx->D3DDevDesc.wMaxSimultaneousTextures;
-	// Only use as many Units as the spec requires
-	if (glb.wMaxSimultaneousTextures > MAX_TEXTURE_UNITS)
-		glb.wMaxSimultaneousTextures = MAX_TEXTURE_UNITS;
-	lpCtx->glCtx->Const.MaxTextureUnits = glb.wMaxSimultaneousTextures;
-	ddlogPrintf(DDLOG_INFO, "Texture stages   : %d", glb.wMaxSimultaneousTextures);
-
-	// Set the max texture size.
-	// NOTE: clamped to a max of 1024 for extra performance!
-	lpCtx->dwMaxTextureSize = (lpCtx->D3DDevDesc.dwMaxTextureWidth <= 1024) ? lpCtx->D3DDevDesc.dwMaxTextureWidth : 1024;
-
-// Texture resize takes place elsewhere. KH
-// NOTE: This was added to workaround an issue with the Intel app.
-#if 0
-	lpCtx->glCtx->Const.MaxTextureSize = lpCtx->dwMaxTextureSize;
-#else
-	lpCtx->glCtx->Const.MaxTextureSize = 1024;
-#endif
-	lpCtx->glCtx->Const.MaxDrawBuffers = 1;
-
-	// Setup the Display Driver pointers
-	dglSetupDDPointers(lpCtx->glCtx);
-
-	// Initialise all the Direct3D renderstates
-	dglInitStateD3D(lpCtx->glCtx);
-
-#if 0
-	// Signal a reload of texture state on next glBegin
-	lpCtx->m_texHandleValid = FALSE;
-	lpCtx->m_mtex = FALSE;
-	lpCtx->m_texturing = FALSE;
-#else
-	// Set default texture unit state
-//	dglSetTexture(lpCtx, 0, NULL);
-//	dglSetTexture(lpCtx, 1, NULL);
-#endif
-
-	//
-	// Set the global texture palette to default values.
-	//
-
-	// Clear the entire palette
-	ZeroMemory(ppe, sizeof(PALETTEENTRY) * 256);
-
-	// Fill the palette with a default colour.
-	// A garish colour is used to catch bugs. Here Magenta is used.
-	for (i=0; i < 256; i++) {
-		ppe[i].peRed	= 255;
-		ppe[i].peGreen	= 0;
-		ppe[i].peBlue	= 255;
-	}
-
-	RELEASE(lpCtx->lpGlobalPalette);
-
-	if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && glb.lpGlobalPalette)
-		hResult = IDirectDrawPalette_AddRef(lpCtx->lpGlobalPalette = glb.lpGlobalPalette);
-	else
-		hResult = IDirectDraw4_CreatePalette(
-				lpCtx->lpDD4,
-				DDPCAPS_INITIALIZE | DDPCAPS_8BIT | DDPCAPS_ALLOW256,
-				ppe,
-				&(lpCtx->lpGlobalPalette),
-				NULL);
-	if (FAILED(hResult)) {
-		ddlogError(DDLOG_ERROR, "Default CreatePalette failed\n", hResult);
-		lpCtx->lpGlobalPalette = NULL;
-		goto return_with_error;
-	}
-	if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && !glb.lpGlobalPalette)
-		IDirectDrawPalette_AddRef(glb.lpGlobalPalette = lpCtx->lpGlobalPalette);
-
-#endif // _USE_GLD3_WGL
-
-	// ** If we have made it to here then we can enable rendering **
-	lpCtx->bCanRender = TRUE;
-
-//	ddlogMessage(DDLOG_SYSTEM, "dglCreateContextBuffers succeded\n");
-
-#ifdef GLD_THREADS
-	// Release serialized access
-	if (glb.bMultiThreaded)
-		LeaveCriticalSection(&CriticalSection);
-#endif
-
-	return TRUE;
-
-return_with_error:
-	// Clean up before returning.
-	// This is critical for secondary devices.
-
-	lpCtx->bCanRender = FALSE;
-
-#ifdef _USE_GLD3_WGL
-	// Destroy the Mesa context
-	if (lpCtx->glBuffer)
-		_mesa_destroy_framebuffer(lpCtx->glBuffer);
-	if (lpCtx->glCtx)
-		_mesa_destroy_context(lpCtx->glCtx);
-	if (lpCtx->glVis)
-		_mesa_destroy_visual(lpCtx->glVis);
-
-	// Destroy driver data
-	_gldDriver.DestroyDrawable(lpCtx);
-#else
-	// Destroy the Mesa context
-	if (lpCtx->glBuffer)
-		(*mesaFuncs.gl_destroy_framebuffer)(lpCtx->glBuffer);
-	if (lpCtx->glCtx)
-		(*mesaFuncs.gl_destroy_context)(lpCtx->glCtx);
-	if (lpCtx->glVis)
-		(*mesaFuncs.gl_destroy_visual)(lpCtx->glVis);
-
-	RELEASE(lpCtx->m_pvbuf); // Release D3D vertex buffer
-	RELEASE(lpCtx->m_vbuf); // Release D3D vertex buffer
-
-	if (lpCtx->lpViewport3) {
-		if (lpCtx->lpDev3) IDirect3DDevice3_DeleteViewport(lpCtx->lpDev3, lpCtx->lpViewport3);
-		RELEASE(lpCtx->lpViewport3);
-		lpCtx->lpViewport3 = NULL;
-	}
-
-	RELEASE(lpCtx->lpDev3);
-	if (lpCtx->lpDepth4) {
-		if (lpCtx->lpBack4)
-			IDirectDrawSurface4_DeleteAttachedSurface(lpCtx->lpBack4, 0L, lpCtx->lpDepth4);
-		else
-			IDirectDrawSurface4_DeleteAttachedSurface(lpCtx->lpFront4, 0L, lpCtx->lpDepth4);
-		RELEASE(lpCtx->lpDepth4);
-		lpCtx->lpDepth4 = NULL;
-	}
-	RELEASE(lpCtx->lpBack4);
-	RELEASE(lpCtx->lpFront4);
-	else
-	if (lpCtx->bFullscreen) {
-		IDirectDraw4_RestoreDisplayMode(lpCtx->lpDD4);
-		IDirectDraw4_SetCooperativeLevel(lpCtx->lpDD4, NULL, DDSCL_NORMAL);
-	}
-	RELEASE(lpCtx->lpD3D3);
-	RELEASE(lpCtx->lpDD4);
-	RELEASE(lpCtx->lpDD1);
-#endif // _USE_GLD3_WGL
-
-	lpCtx->bAllocated = FALSE;
-
-#ifdef GLD_THREADS
-	// Release serialized access
-	if (glb.bMultiThreaded)
-		LeaveCriticalSection(&CriticalSection);
-#endif
-
-	return FALSE;
-
-#undef DDLOG_CRITICAL_OR_WARN
-}
-
-// ***********************************************************************
-
-HGLRC dglCreateContext(
-	HDC a,
-	const DGL_pixelFormat *lpPF)
-{
-	int i;
-	HGLRC				hGLRC;
-	DGL_ctx*			lpCtx;
-	static BOOL			bWarnOnce = TRUE;
-	DWORD				dwThreadId = GetCurrentThreadId();
-    char                szMsg[256];
-    HWND                hWnd;
-    LONG                lpfnWndProc;
-
-	// Validate license
-	if (!dglValidate())
-		return NULL;
-
-	// Is context state ready ?
-	if (!bContextReady)
-		return NULL;
-
-	ddlogPrintf(DDLOG_SYSTEM, "dglCreateContext for HDC=%X, ThreadId=%X", a, dwThreadId);
-
-	// Find next free context.
-	// Also ensure that only one Fullscreen context is created at any one time.
-	hGLRC = 0; // Default to Not Found
-	for (i=0; i<DGL_MAX_CONTEXTS; i++) {
-		if (ctxlist[i].bAllocated) {
-			if (/*glb.bFullscreen && */ctxlist[i].bFullscreen)
-				break;
-		} else {
-			hGLRC = (HGLRC)(i+1);
-			break;
-		}
-	}
-
-	// Bail if no GLRC was found
-	if (!hGLRC)
-		return NULL;
-
-	// Set the context pointer
-	lpCtx = dglGetContextAddress(hGLRC);
-	// Make sure that context is zeroed before we do anything.
-	// MFC and C++ apps call wglCreateContext() and wglDeleteContext() multiple times,
-	// even though only one context is ever used by the app, so keep it clean. (DaveM)
-	ZeroMemory(lpCtx, sizeof(DGL_ctx));
-	lpCtx->bAllocated = TRUE;
-	// Flag that buffers need creating on next wglMakeCurrent call.
-	lpCtx->bHasBeenCurrent = FALSE;
-	lpCtx->lpPF = (DGL_pixelFormat *)lpPF;	// cache pixel format
-	lpCtx->bCanRender = FALSE;
-
-	// Create all the internal resources here, not in dglMakeCurrent().
-	// We do a re-size check in dglMakeCurrent in case of re-allocations. (DaveM)
-	// We now try context allocations twice, first with video memory,
-	// then again with system memory. This is similar to technique
-	// used for dglWglResizeBuffers(). (DaveM)
-	if (lpCtx->bHasBeenCurrent == FALSE) {
-		if (!dglCreateContextBuffers(a, lpCtx, FALSE)) {
-			if (glb.bMessageBoxWarnings && bWarnOnce && dwLogging) {
-				bWarnOnce = FALSE;
-                switch (nContextError) {
-                   case GLDERR_DDRAW: strcpy(szMsg, szDDrawWarning); break;
-                   case GLDERR_D3D: strcpy(szMsg, szD3DWarning); break;
-                   case GLDERR_MEM: strcpy(szMsg, szResourceWarning); break;
-                   case GLDERR_BPP: strcpy(szMsg, szBPPWarning); break;
-                   default: strcpy(szMsg, "");
-                }
-                if (strlen(szMsg))
-                    MessageBox(NULL, szMsg, "GLDirect", MB_OK | MB_ICONWARNING);
-			}
-            // Only need to try again if memory error
-            if (nContextError == GLDERR_MEM) {
-			    ddlogPrintf(DDLOG_WARN, "dglCreateContext failed 1st time with video memory");
-            }
-            else {
-			    ddlogPrintf(DDLOG_ERROR, "dglCreateContext failed");
-                return NULL;
-            }
-		}
-	}
-
-	// Now that we have a hWnd, we can intercept the WindowProc.
-    hWnd = lpCtx->hWnd;
-    if (hWnd) {
-		// Only hook individual window handler once if not hooked before.
-		lpfnWndProc = GetWindowLong(hWnd, GWL_WNDPROC);
-		if (lpfnWndProc != (LONG)dglWndProc) {
-			lpCtx->lpfnWndProc = lpfnWndProc;
-			SetWindowLong(hWnd, GWL_WNDPROC, (LONG)dglWndProc);
-			}
-        // Find the parent window of the app too.
-        if (glb.hWndActive == NULL) {
-            while (hWnd != NULL) {
-                glb.hWndActive = hWnd;
-                hWnd = GetParent(hWnd);
-            }
-            // Hook the parent window too.
-            lpfnWndProc = GetWindowLong(glb.hWndActive, GWL_WNDPROC);
-            if (glb.hWndActive == lpCtx->hWnd)
-                glb.lpfnWndProc = lpCtx->lpfnWndProc;
-            else if (lpfnWndProc != (LONG)dglWndProc)
-                glb.lpfnWndProc = lpfnWndProc;
-            if (glb.lpfnWndProc)
-                SetWindowLong(glb.hWndActive, GWL_WNDPROC, (LONG)dglWndProc);
-        }
-    }
-
-	ddlogPrintf(DDLOG_SYSTEM, "dglCreateContext succeeded for HGLRC=%d", (int)hGLRC);
-
-	return hGLRC;
-}
-
-// ***********************************************************************
-// Make a DirectGL context current
-// Used by wgl functions and dgl functions
-BOOL dglMakeCurrent(
-	HDC a,
-	HGLRC b)
-{
-	int context;
-	DGL_ctx* lpCtx;
-	HWND hWnd;
-	BOOL bNeedResize = FALSE;
-	BOOL bWindowChanged, bContextChanged;
-	LPDIRECTDRAWCLIPPER	lpddClipper;
-	DWORD dwThreadId = GetCurrentThreadId();
-	LONG lpfnWndProc;
-
-	// Validate license
-	if (!dglValidate())
-		return FALSE;
-
-	// Is context state ready ?
-	if (!bContextReady)
-		return FALSE;
-
-	context = (int)b; // This is as a result of STRICT!
-	ddlogPrintf(DDLOG_SYSTEM, "dglMakeCurrent: HDC=%X, HGLRC=%d, ThreadId=%X", a, context, dwThreadId);
-
-	// If the HGLRC is NULL then make no context current;
-	// Ditto if the HDC is NULL either. (DaveM)
-	if (context == 0 || a == 0) {
-		// Corresponding Mesa operation
-#ifdef _USE_GLD3_WGL
-		_mesa_make_current(NULL, NULL);
-#else
-		(*mesaFuncs.gl_make_current)(NULL, NULL);
-#endif
-		dglSetCurrentContext(0);
-		return TRUE;
-	}
-
-	// Make sure the HGLRC is in range
-	if ((context > DGL_MAX_CONTEXTS) || (context < 0)) {
-		ddlogMessage(DDLOG_ERROR, "dglMakeCurrent: HGLRC out of range\n");
-		return FALSE;
-	}
-
-	// Find address of context and make sure that it has been allocated
-	lpCtx = dglGetContextAddress(b);
-	if (!lpCtx->bAllocated) {
-		ddlogMessage(DDLOG_ERROR, "dglMakeCurrent: Context not allocated\n");
-//		return FALSE;
-		return TRUE; // HACK: Shuts up "WebLab Viewer Pro". KeithH
-	}
-
-#ifdef GLD_THREADS
-	// Serialize access to DirectDraw or DDS operations
-	if (glb.bMultiThreaded)
-		EnterCriticalSection(&CriticalSection);
-#endif
-
-	// Check if window has changed
-	hWnd = (a != lpCtx->hDC) ? WindowFromDC(a) : lpCtx->hWnd;
-	bWindowChanged = (hWnd != lpCtx->hWnd) ? TRUE : FALSE;
-	bContextChanged = (b != dglGetCurrentContext()) ? TRUE : FALSE;
-
-	// If the window has changed, make sure the clipper is updated. (DaveM)
-	if (glb.bDirectDrawPersistant && !lpCtx->bFullscreen && (bWindowChanged || bContextChanged)) {
-		lpCtx->hWnd = hWnd;
-#ifndef _USE_GLD3_WGL
-		IDirectDrawSurface4_GetClipper(lpCtx->lpFront4, &lpddClipper);
-		IDirectDrawClipper_SetHWnd(lpddClipper, 0, lpCtx->hWnd);
-		IDirectDrawClipper_Release(lpddClipper);
-#endif // _USE_GLD3_WGL
-	}
-
-	// Make sure hDC and hWnd is current. (DaveM)
-	// Obtain the dimensions of the rendering window
-	lpCtx->hDC = a; // Cache DC
-	lpCtx->hWnd = hWnd;
-	hWndLastActive = hWnd;
-
-	// Check for non-window DC = memory DC ?
-	if (hWnd == NULL) {
-		if (GetClipBox(a, &lpCtx->rcScreenRect) == ERROR) {
-			ddlogMessage(DDLOG_WARN, "GetClipBox failed in dglMakeCurrent\n");
-			SetRect(&lpCtx->rcScreenRect, 0, 0, 0, 0);
-		}
-	}
-	else if (!GetClientRect(lpCtx->hWnd, &lpCtx->rcScreenRect)) {
-		ddlogMessage(DDLOG_WARN, "GetClientRect failed in dglMakeCurrent\n");
-		SetRect(&lpCtx->rcScreenRect, 0, 0, 0, 0);
-	}
-	// Check if buffers need to be re-sized;
-	// If so, wait until Mesa GL stuff is setup before re-sizing;
-	if (lpCtx->dwWidth != lpCtx->rcScreenRect.right - lpCtx->rcScreenRect.left ||
-		lpCtx->dwHeight != lpCtx->rcScreenRect.bottom - lpCtx->rcScreenRect.top)
-		bNeedResize = TRUE;
-
-	// Now we can update our globals
-	dglSetCurrentContext(b);
-
-	// Corresponding Mesa operation
-#ifdef _USE_GLD3_WGL
-	_mesa_make_current(lpCtx->glCtx, lpCtx->glBuffer);
-	lpCtx->glCtx->Driver.UpdateState(lpCtx->glCtx, _NEW_ALL);
-	if (bNeedResize) {
-		// Resize buffers (Note Mesa GL needs to be setup beforehand);
-		// Resize Mesa internal buffer too via glViewport() command,
-		// which subsequently calls dglWglResizeBuffers() too.
-		lpCtx->glCtx->Driver.Viewport(lpCtx->glCtx, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
-		lpCtx->bHasBeenCurrent = TRUE;
-	}
-#else
-	(*mesaFuncs.gl_make_current)(lpCtx->glCtx, lpCtx->glBuffer);
-
-	dglSetupDDPointers(lpCtx->glCtx);
-
-	// Insure DirectDraw surfaces fit current window DC
-	if (bNeedResize) {
-		// Resize buffers (Note Mesa GL needs to be setup beforehand);
-		// Resize Mesa internal buffer too via glViewport() command,
-		// which subsequently calls dglWglResizeBuffers() too.
-		(*mesaFuncs.gl_Viewport)(lpCtx->glCtx, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
-		lpCtx->bHasBeenCurrent = TRUE;
-	}
-#endif // _USE_GLD3_WGL
-	ddlogPrintf(DDLOG_SYSTEM, "dglMakeCurrent: width = %d, height = %d", lpCtx->dwWidth, lpCtx->dwHeight);
-
-	// We have to clear D3D back buffer and render state if emulated front buffering
-	// for different window (but not context) like in Solid Edge.
-	if (glb.bDirectDrawPersistant && glb.bPersistantBuffers
-		&& (bWindowChanged /* || bContextChanged */) && lpCtx->EmulateSingle) {
-#ifdef _USE_GLD3_WGL
-//		IDirect3DDevice8_EndScene(lpCtx->pDev);
-//		lpCtx->bSceneStarted = FALSE;
-		lpCtx->glCtx->Driver.Clear(lpCtx->glCtx, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
-			GL_TRUE, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
-#else
-		IDirect3DDevice3_EndScene(lpCtx->lpDev3);
-		lpCtx->bSceneStarted = FALSE;
-		dglClearD3D(lpCtx->glCtx, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
-			GL_TRUE, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
-#endif // _USE_GLD3_WGL
-	}
-
-	// The first time we call MakeCurrent we set the initial viewport size
-	if (lpCtx->bHasBeenCurrent == FALSE)
-#ifdef _USE_GLD3_WGL
-		lpCtx->glCtx->Driver.Viewport(lpCtx->glCtx, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
-#else
-		(*mesaFuncs.gl_Viewport)(lpCtx->glCtx, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
-#endif // _USE_GLD3_WGL
-	lpCtx->bHasBeenCurrent = TRUE;
-
-#ifdef GLD_THREADS
-	// Release serialized access
-	if (glb.bMultiThreaded)
-		LeaveCriticalSection(&CriticalSection);
-#endif
-
-	return TRUE;
-}
-
-// ***********************************************************************
-
-BOOL dglDeleteContext(
-	HGLRC a)
-{
-	DGL_ctx* lpCtx;
-	DWORD dwThreadId = GetCurrentThreadId();
-    char argstr[256];
-
-#if 0	// We have enough trouble throwing exceptions as it is... (DaveM)
-	// Validate license
-	if (!dglValidate())
-		return FALSE;
-#endif
-
-	// Is context state ready ?
-	if (!bContextReady)
-		return FALSE;
-
-	ddlogPrintf(DDLOG_SYSTEM, "dglDeleteContext: Deleting context HGLRC=%d, ThreadId=%X", (int)a, dwThreadId);
-
-	// Make sure the HGLRC is in range
-	if (((int) a> DGL_MAX_CONTEXTS) || ((int)a < 0)) {
-		ddlogMessage(DDLOG_ERROR, "dglDeleteCurrent: HGLRC out of range\n");
-		return FALSE;
-	}
-
-	// Make sure context is valid
-	lpCtx = dglGetContextAddress(a);
-	if (!lpCtx->bAllocated) {
-		ddlogPrintf(DDLOG_WARN, "Tried to delete unallocated context HGLRC=%d", (int)a);
-//		return FALSE;
-		return TRUE; // HACK: Shuts up "WebLab Viewer Pro". KeithH
-	}
-
-	// Make sure context is de-activated
-	if (a == dglGetCurrentContext()) {
-		ddlogPrintf(DDLOG_WARN, "dglDeleteContext: context HGLRC=%d still active", (int)a);
-		dglMakeCurrent(NULL, NULL);
-	}
-
-#ifdef GLD_THREADS
-	// Serialize access to DirectDraw or DDS operations
-	if (glb.bMultiThreaded)
-		EnterCriticalSection(&CriticalSection);
-#endif
-
-	// We are about to destroy all Direct3D objects.
-	// Therefore we must disable rendering
-	lpCtx->bCanRender = FALSE;
-
-	// This exception handler was installed to catch some
-	// particularly nasty apps. Console apps that call exit()
-	// fall into this catagory (i.e. Win32 Glut).
-
-    // VC cannot successfully implement multiple exception handlers
-    // if more than one exception occurs. Therefore reverting back to
-    // single exception handler as Keith originally had it. (DaveM)
-
-#define WARN_MESSAGE(p) strcpy(argstr, (#p));
-#define SAFE_RELEASE(p) WARN_MESSAGE(p); RELEASE(p);
-
-__try {
-#ifdef _USE_GLD3_WGL
-    WARN_MESSAGE(gl_destroy_framebuffer);
-	if (lpCtx->glBuffer)
-		_mesa_destroy_framebuffer(lpCtx->glBuffer);
-    WARN_MESSAGE(gl_destroy_context);
-	if (lpCtx->glCtx)
-		_mesa_destroy_context(lpCtx->glCtx);
-    WARN_MESSAGE(gl_destroy_visual);
-	if (lpCtx->glVis)
-		_mesa_destroy_visual(lpCtx->glVis);
-
-	_gldDriver.DestroyDrawable(lpCtx);
-#else
-	// Destroy the Mesa context
-    WARN_MESSAGE(gl_destroy_framebuffer);
-	if (lpCtx->glBuffer)
-		(*mesaFuncs.gl_destroy_framebuffer)(lpCtx->glBuffer);
-    WARN_MESSAGE(gl_destroy_context);
-	if (lpCtx->glCtx)
-		(*mesaFuncs.gl_destroy_context)(lpCtx->glCtx);
-    WARN_MESSAGE(gl_destroy_visual);
-	if (lpCtx->glVis)
-		(*mesaFuncs.gl_destroy_visual)(lpCtx->glVis);
-
-	SAFE_RELEASE(lpCtx->m_pvbuf); // release D3D vertex buffer
-	SAFE_RELEASE(lpCtx->m_vbuf); // release D3D vertex buffer
-
-	// Delete the global palette
-	SAFE_RELEASE(lpCtx->lpGlobalPalette);
-
-	// Clean up.
-	if (lpCtx->lpViewport3) {
-		if (lpCtx->lpDev3) IDirect3DDevice3_DeleteViewport(lpCtx->lpDev3, lpCtx->lpViewport3);
-		SAFE_RELEASE(lpCtx->lpViewport3);
-		lpCtx->lpViewport3 = NULL;
-	}
-
-	SAFE_RELEASE(lpCtx->lpDev3);
-	if (lpCtx->lpDepth4) {
-		if (lpCtx->lpBack4)
-			IDirectDrawSurface4_DeleteAttachedSurface(lpCtx->lpBack4, 0L, lpCtx->lpDepth4);
-		else
-			IDirectDrawSurface4_DeleteAttachedSurface(lpCtx->lpFront4, 0L, lpCtx->lpDepth4);
-		SAFE_RELEASE(lpCtx->lpDepth4);
-		lpCtx->lpDepth4 = NULL;
-	}
-	SAFE_RELEASE(lpCtx->lpBack4);
-	SAFE_RELEASE(lpCtx->lpFront4);
-	if (lpCtx->bFullscreen) {
-		IDirectDraw4_RestoreDisplayMode(lpCtx->lpDD4);
-		IDirectDraw4_SetCooperativeLevel(lpCtx->lpDD4, NULL, DDSCL_NORMAL);
-	}
-	SAFE_RELEASE(lpCtx->lpD3D3);
-	SAFE_RELEASE(lpCtx->lpDD4);
-	SAFE_RELEASE(lpCtx->lpDD1);
-#endif // _ULSE_GLD3_WGL
-
-}
-__except(EXCEPTION_EXECUTE_HANDLER) {
-    ddlogPrintf(DDLOG_WARN, "Exception raised in dglDeleteContext: %s", argstr);
-}
-
-	// Restore the window message handler because this context may be used
-	// again by another window with a *different* message handler. (DaveM)
-	if (lpCtx->lpfnWndProc) {
-		SetWindowLong(lpCtx->hWnd, GWL_WNDPROC, (LONG)lpCtx->lpfnWndProc);
-		lpCtx->lpfnWndProc = (LONG)NULL;
-		}
-
-	lpCtx->bAllocated = FALSE; // This context is now free for use
-
-#ifdef GLD_THREADS
-	// Release serialized access
-	if (glb.bMultiThreaded)
-		LeaveCriticalSection(&CriticalSection);
-#endif
-
-	return TRUE;
-}
-
-// ***********************************************************************
-
-BOOL dglSwapBuffers(
-	HDC hDC)
-{
-	RECT		rSrcRect;	// Source rectangle
-	RECT		rDstRect;	// Destination rectangle
-	POINT		pt;
-	HRESULT		hResult;
-
-	DDBLTFX		bltFX;
-	DWORD		dwBlitFlags;
-	DDBLTFX		*lpBltFX;
-
-//	DWORD		dwThreadId = GetCurrentThreadId();
-	HGLRC		hGLRC = dglGetCurrentContext();
-	DGL_ctx		*lpCtx = dglGetContextAddress(hGLRC);
-	HWND		hWnd;
-
-	HDC 		hDCAux;		// for memory DC
-	int 		x,y,w,h;	// for memory DC BitBlt
-
-#if 0	// Perhaps not a good idea. Called too often. KH
-	// Validate license
-	if (!dglValidate())
-		return FALSE;
-#endif
-
-	if (!lpCtx) {
-		return TRUE; //FALSE; // No current context
-	}
-
-	if (!lpCtx->bCanRender) {
-		// Don't return false else some apps will bail.
-		return TRUE;
-	}
-
-	hWnd = lpCtx->hWnd;
-	if (hDC != lpCtx->hDC) {
-		ddlogPrintf(DDLOG_WARN, "dglSwapBuffers: HDC=%X does not match HDC=%X for HGLRC=%d", hDC, lpCtx->hDC, hGLRC);
-		hWnd = WindowFromDC(hDC);
-	}
-
-#ifndef _USE_GLD3_WGL
-	// Ensure that the surfaces exist before we tell
-	// the device to render to them.
-	IDirectDraw4_RestoreAllSurfaces(lpCtx->lpDD4);
-
-	// Make sure that the vertex caches have been emptied
-//	dglStateChange(lpCtx);
-
-	// Some OpenGL programs don't issue a glFinish - check for it here.
-	if (lpCtx->bSceneStarted) {
-		IDirect3DDevice3_EndScene(lpCtx->lpDev3);
-		lpCtx->bSceneStarted = FALSE;
-	}
-#endif
-
-#if 0
-	// If the calling app is not active then we don't need to Blit/Flip.
-	// We can therefore simply return TRUE.
-	if (!glb.bAppActive)
-		return TRUE;
-	// Addendum: This is WRONG! We should bail if the app is *minimized*,
-	//           not merely if the app is just plain 'not active'.
-	//           KeithH, 27/May/2000.
-#endif
-
-	// Check for non-window DC = memory DC ?
-	if (hWnd == NULL) {
-		if (GetClipBox(hDC, &rSrcRect) == ERROR)
-			return TRUE;
-		// Use GDI BitBlt instead from compatible DirectDraw DC
-		x = rSrcRect.left;
-		y = rSrcRect.top;
-		w = rSrcRect.right - rSrcRect.left;
-		h = rSrcRect.bottom - rSrcRect.top;
-
-		// Ack. DX8 does not have a GetDC() function...
-                // TODO: Defer to DX7 or DX9 drivers... (DaveM)
-		return TRUE;
-	}
-
-	// Bail if window client region is not drawable, like in Solid Edge
-	if (!IsWindow(hWnd) /* || !IsWindowVisible(hWnd) */ || !GetClientRect(hWnd, &rSrcRect))
-		return TRUE;
-
-#ifdef GLD_THREADS
-	// Serialize access to DirectDraw or DDS operations
-	if (glb.bMultiThreaded)
-		EnterCriticalSection(&CriticalSection);
-#endif
-
-#ifdef _USE_GLD3_WGL
-	// Notify Mesa of impending swap, so Mesa can flush internal buffers.
-	_mesa_notifySwapBuffers(lpCtx->glCtx);
-	// Now perform driver buffer swap
-	_gldDriver.SwapBuffers(lpCtx, hDC, hWnd);
-#else
-	if (lpCtx->bFullscreen) {
-		// Sync with retrace if required
-		if (glb.bWaitForRetrace) {
-			IDirectDraw4_WaitForVerticalBlank(
-				lpCtx->lpDD4,
-				DDWAITVB_BLOCKBEGIN,
-				0);
-		}
-
-		// Perform the fullscreen flip
-		TRY(IDirectDrawSurface4_Flip(
-			lpCtx->lpFront4,
-			NULL,
-			DDFLIP_WAIT),
-			"dglSwapBuffers: Flip");
-	} else {
-		// Calculate current window position and size
-		pt.x = pt.y = 0;
-		ClientToScreen(hWnd, &pt);
-		GetClientRect(hWnd, &rDstRect);
-		if (rDstRect.right > lpCtx->dwModeWidth)
-			rDstRect.right = lpCtx->dwModeWidth;
-		if (rDstRect.bottom > lpCtx->dwModeHeight)
-			rDstRect.bottom = lpCtx->dwModeHeight;
-		OffsetRect(&rDstRect, pt.x, pt.y);
-		rSrcRect.left = rSrcRect.top = 0;
-		rSrcRect.right = lpCtx->dwWidth;
-		rSrcRect.bottom = lpCtx->dwHeight;
-		if (rSrcRect.right > lpCtx->dwModeWidth)
-			rSrcRect.right = lpCtx->dwModeWidth;
-		if (rSrcRect.bottom > lpCtx->dwModeHeight)
-			rSrcRect.bottom = lpCtx->dwModeHeight;
-
-		if (glb.bWaitForRetrace) {
-			// Sync the blit to the vertical retrace
-			ZeroMemory(&bltFX, sizeof(bltFX));
-			bltFX.dwSize = sizeof(bltFX);
-			bltFX.dwDDFX = DDBLTFX_NOTEARING;
-			dwBlitFlags = DDBLT_WAIT | DDBLT_DDFX;
-			lpBltFX = &bltFX;
-		} else {
-			dwBlitFlags = DDBLT_WAIT;
-			lpBltFX = NULL;
-		}
-
-		// Perform the actual blit
-		TRY(IDirectDrawSurface4_Blt(
-			lpCtx->lpFront4,
-			&rDstRect,
-			lpCtx->lpBack4, // Blit source
-			&rSrcRect,
-			dwBlitFlags,
-			lpBltFX),
-			"dglSwapBuffers: Blt");
-	}
-#endif // _USE_GLD3_WGL
-
-#ifdef GLD_THREADS
-	// Release serialized access
-	if (glb.bMultiThreaded)
-		LeaveCriticalSection(&CriticalSection);
-#endif
-
-    // TODO: Re-instate rendering bitmap snapshot feature??? (DaveM)
-
-	// Render frame is completed
-	ValidateRect(hWnd, NULL);
-	lpCtx->bFrameStarted = FALSE;
-
-	return TRUE;
-}
-
-// ***********************************************************************
+/****************************************************************************
+*
+*                        Mesa 3-D graphics library
+*                        Direct3D Driver Interface
+*
+*  ========================================================================
+*
+*   Copyright (C) 1991-2004 SciTech Software, Inc. 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"),
+*   to deal in the Software without restriction, including without limitation
+*   the rights to use, copy, modify, merge, publish, distribute, sublicense,
+*   and/or sell copies of the Software, and to permit persons to whom the
+*   Software is furnished to do so, subject to the following conditions:
+*
+*   The above copyright notice and this permission notice shall be included
+*   in all copies or substantial portions of the Software.
+*
+*   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+*   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+*   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+*   SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+*   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+*   OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+*   SOFTWARE.
+*
+*  ======================================================================
+*
+* Language:     ANSI C
+* Environment:  Windows 9x (Win32)
+*
+* Description:  Context handling.
+*
+****************************************************************************/
+
+#include "dglcontext.h"
+
+// Get compile errors without this. KeithH
+//#include "scitech.h"	// ibool, etc.
+
+#ifdef _USE_GLD3_WGL
+#include "gld_driver.h"
+
+extern void _gld_mesa_warning(struct gl_context *, char *);
+extern void _gld_mesa_fatal(struct gl_context *, char *);
+#endif // _USE_GLD3_WGL
+
+// TODO: Clean out old DX6-specific code from GLD 2.x CAD driver
+// if it is no longer being built as part of GLDirect. (DaveM)
+
+// ***********************************************************************
+
+#define GLDERR_NONE     0
+#define GLDERR_MEM      1
+#define GLDERR_DDRAW    2
+#define GLDERR_D3D      3
+#define GLDERR_BPP      4
+
+char szResourceWarning[] =
+"GLDirect does not have enough video memory resources\n"
+"to support the requested OpenGL rendering context.\n\n"
+"You may have to reduce the current display resolution\n"
+"to obtain satisfactory OpenGL performance.\n";
+
+char szDDrawWarning[] =
+"GLDirect is unable to initialize DirectDraw for the\n"
+"requested OpenGL rendering context.\n\n"
+"You will have to check the DirectX control panel\n"
+"for further information.\n";
+
+char szD3DWarning[] =
+"GLDirect is unable to initialize Direct3D for the\n"
+"requested OpenGL rendering context.\n\n"
+"You may have to change the display mode resolution\n"
+"color depth or check the DirectX control panel for\n"
+"further information.\n";
+
+char szBPPWarning[] =
+"GLDirect is unable to use the selected color depth for\n"
+"the requested OpenGL rendering context.\n\n"
+"You will have to change the display mode resolution\n"
+"color depth with the Display Settings control panel.\n";
+
+int nContextError = GLDERR_NONE;
+
+// ***********************************************************************
+
+#define VENDORID_ATI 0x1002
+
+static DWORD devATIRagePro[] = {
+	0x4742, // 3D RAGE PRO BGA AGP 1X/2X
+	0x4744, // 3D RAGE PRO BGA AGP 1X only
+	0x4749, // 3D RAGE PRO BGA PCI 33 MHz
+	0x4750, // 3D RAGE PRO PQFP PCI 33 MHz
+	0x4751, // 3D RAGE PRO PQFP PCI 33 MHz limited 3D
+	0x4C42, // 3D RAGE LT PRO BGA-312 AGP 133 MHz
+	0x4C44, // 3D RAGE LT PRO BGA-312 AGP 66 MHz
+	0x4C49, // 3D RAGE LT PRO BGA-312 PCI 33 MHz
+	0x4C50, // 3D RAGE LT PRO BGA-256 PCI 33 MHz
+	0x4C51, // 3D RAGE LT PRO BGA-256 PCI 33 MHz limited 3D
+};
+
+static DWORD devATIRageIIplus[] = {
+	0x4755, // 3D RAGE II+
+	0x4756, // 3D RAGE IIC PQFP PCI
+	0x4757, // 3D RAGE IIC BGA AGP
+	0x475A, // 3D RAGE IIC PQFP AGP
+	0x4C47, // 3D RAGE LT-G
+};
+
+// ***********************************************************************
+
+#ifndef _USE_GLD3_WGL
+extern DGL_mesaFuncs mesaFuncs;
+#endif
+
+extern DWORD dwLogging;
+
+#ifdef GLD_THREADS
+#pragma message("compiling DGLCONTEXT.C vars for multi-threaded support")
+CRITICAL_SECTION CriticalSection;		// for serialized access
+DWORD		dwTLSCurrentContext = 0xFFFFFFFF;	// TLS index for current context
+DWORD		dwTLSPixelFormat = 0xFFFFFFFF;		// TLS index for current pixel format
+#endif
+HGLRC		iCurrentContext = 0;		// Index of current context (static)
+BOOL		bContextReady = FALSE;		// Context state ready ?
+
+DGL_ctx		ctxlist[DGL_MAX_CONTEXTS];	// Context list
+
+// ***********************************************************************
+
+static BOOL bHaveWin95 = FALSE;
+static BOOL bHaveWinNT = FALSE;
+static BOOL bHaveWin2K = FALSE;
+
+/****************************************************************************
+REMARKS:
+Detect the installed OS type.
+****************************************************************************/
+static void DetectOS(void)
+{
+    OSVERSIONINFO VersionInformation;
+    LPOSVERSIONINFO lpVersionInformation = &VersionInformation;
+
+    VersionInformation.dwOSVersionInfoSize = sizeof(VersionInformation);
+
+	GetVersionEx(lpVersionInformation);
+
+    switch (VersionInformation.dwPlatformId) {
+    	case VER_PLATFORM_WIN32_WINDOWS:
+			bHaveWin95 = TRUE;
+			bHaveWinNT = FALSE;
+			bHaveWin2K = FALSE;
+            break;
+    	case VER_PLATFORM_WIN32_NT:
+			bHaveWin95 = FALSE;
+			if (VersionInformation.dwMajorVersion <= 4) {
+				bHaveWinNT = TRUE;
+				bHaveWin2K = FALSE;
+                }
+            else {
+				bHaveWinNT = FALSE;
+				bHaveWin2K = TRUE;
+                }
+			break;
+		case VER_PLATFORM_WIN32s:
+			bHaveWin95 = FALSE;
+			bHaveWinNT = FALSE;
+			bHaveWin2K = FALSE;
+			break;
+        }
+}
+
+// ***********************************************************************
+
+HWND hWndEvent = NULL;					// event monitor window
+HWND hWndLastActive = NULL;				// last active client window
+LONG __stdcall GLD_EventWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam);
+
+// ***********************************************************************
+
+// Checks if the HGLRC is valid in range of context list.
+BOOL dglIsValidContext(
+	HGLRC a)
+{
+	return ((int)a > 0 && (int)a <= DGL_MAX_CONTEXTS);
+}
+
+// ***********************************************************************
+
+// Convert a HGLRC to a pointer into the context list.
+DGL_ctx* dglGetContextAddress(
+	const HGLRC a)
+{
+	if (dglIsValidContext(a))
+		return &ctxlist[(int)a-1];
+	return NULL;
+}
+
+// ***********************************************************************
+
+// Return the current HGLRC (however it may be stored for multi-threading).
+HGLRC dglGetCurrentContext(void)
+{
+#ifdef GLD_THREADS
+	HGLRC hGLRC;
+	// load from thread-specific instance
+	if (glb.bMultiThreaded) {
+		// protect against calls from arbitrary threads
+		__try {
+			hGLRC = (HGLRC)TlsGetValue(dwTLSCurrentContext);
+		}
+		__except(EXCEPTION_EXECUTE_HANDLER) {
+			hGLRC = iCurrentContext;
+		}
+	}
+	// load from global static var
+	else {
+		hGLRC = iCurrentContext;
+	}
+	return hGLRC;
+#else
+	return iCurrentContext;
+#endif
+}
+
+// ***********************************************************************
+
+// Set the current HGLRC (however it may be stored for multi-threading).
+void dglSetCurrentContext(HGLRC hGLRC)
+{
+#ifdef GLD_THREADS
+	// store in thread-specific instance
+	if (glb.bMultiThreaded) {
+		// protect against calls from arbitrary threads
+		__try {
+			TlsSetValue(dwTLSCurrentContext, (LPVOID)hGLRC);
+		}
+		__except(EXCEPTION_EXECUTE_HANDLER) {
+			iCurrentContext = hGLRC;
+		}
+	}
+	// store in global static var
+	else {
+		iCurrentContext = hGLRC;
+	}
+#else
+	iCurrentContext = hGLRC;
+#endif
+}
+
+// ***********************************************************************
+
+// Return the current HDC only for a currently active HGLRC.
+HDC dglGetCurrentDC(void)
+{
+	HGLRC hGLRC;
+	DGL_ctx* lpCtx;
+
+	hGLRC = dglGetCurrentContext();
+	if (hGLRC) {
+		lpCtx = dglGetContextAddress(hGLRC);
+		return lpCtx->hDC;
+	}
+	return 0;
+}
+
+// ***********************************************************************
+
+void dglInitContextState()
+{
+	int i;
+	WNDCLASS wc;
+
+#ifdef GLD_THREADS
+	// Allocate thread local storage indexes for current context and pixel format
+	dwTLSCurrentContext = TlsAlloc();
+	dwTLSPixelFormat = TlsAlloc();
+#endif
+
+	dglSetCurrentContext(NULL); // No current rendering context
+
+	 // Clear all context data
+	ZeroMemory(ctxlist, sizeof(ctxlist[0]) * DGL_MAX_CONTEXTS);
+
+	for (i=0; i<DGL_MAX_CONTEXTS; i++)
+		ctxlist[i].bAllocated = FALSE; // Flag context as unused
+
+	// This section of code crashes the dll in circumstances where the app
+	// creates and destroys contexts.
+/*
+	// Register the class for our event monitor window
+	wc.style = 0;
+	wc.lpfnWndProc = GLD_EventWndProc;
+	wc.cbClsExtra = 0;
+	wc.cbWndExtra = 0;
+	wc.hInstance = GetModuleHandle(NULL);
+	wc.hIcon = LoadIcon(GetModuleHandle(NULL), IDI_APPLICATION);
+	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+	wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
+	wc.lpszMenuName = NULL;
+	wc.lpszClassName = "GLDIRECT";
+	RegisterClass(&wc);
+
+	// Create the non-visible window to monitor all broadcast messages
+	hWndEvent = CreateWindowEx(
+		WS_EX_TOOLWINDOW,"GLDIRECT","GLDIRECT",WS_POPUP,
+		0,0,0,0,
+		NULL,NULL,GetModuleHandle(NULL),NULL);
+*/
+
+#ifdef GLD_THREADS
+	// Create a critical section object for serializing access to
+	// DirectDraw and DDStereo create/destroy functions in multiple threads
+	if (glb.bMultiThreaded)
+		InitializeCriticalSection(&CriticalSection);
+#endif
+
+	// Context state is now initialized and ready
+	bContextReady = TRUE;
+}
+
+// ***********************************************************************
+
+void dglDeleteContextState()
+{
+	int i;
+	static BOOL bOnceIsEnough = FALSE;
+
+	// Only call once, from either DGL_exitDriver(), or DLL_PROCESS_DETACH
+	if (bOnceIsEnough)
+		return;
+	bOnceIsEnough = TRUE;
+
+	for (i=0; i<DGL_MAX_CONTEXTS; i++) {
+		if (ctxlist[i].bAllocated == TRUE) {
+			ddlogPrintf(DDLOG_WARN, "** Context %i not deleted - cleaning up.", (i+1));
+			dglDeleteContext((HGLRC)(i+1));
+		}
+	}
+
+	// Context state is no longer ready
+	bContextReady = FALSE;
+
+    // If executed when DLL unloads, DDraw objects may be invalid.
+    // So catch any page faults with this exception handler.
+__try {
+
+	// Release final DirectDraw interfaces
+	if (glb.bDirectDrawPersistant) {
+//		RELEASE(glb.lpGlobalPalette);
+//		RELEASE(glb.lpDepth4);
+//		RELEASE(glb.lpBack4);
+//		RELEASE(glb.lpPrimary4);
+//	    RELEASE(glb.lpDD4);
+    }
+}
+__except(EXCEPTION_EXECUTE_HANDLER) {
+    ddlogPrintf(DDLOG_WARN, "Exception raised in dglDeleteContextState.");
+}
+
+	// Destroy our event monitor window
+	if (hWndEvent) {
+		DestroyWindow(hWndEvent);
+		hWndEvent = hWndLastActive = NULL;
+	}
+
+#ifdef GLD_THREADS
+	// Destroy the critical section object
+	if (glb.bMultiThreaded)
+		DeleteCriticalSection(&CriticalSection);
+
+	// Release thread local storage indexes for current HGLRC and pixel format
+	TlsFree(dwTLSPixelFormat);
+	TlsFree(dwTLSCurrentContext);
+#endif
+}
+
+// ***********************************************************************
+
+// Application Window message handler interception
+static LONG __stdcall dglWndProc(
+	HWND hwnd,
+	UINT msg,
+	WPARAM wParam,
+	LPARAM lParam)
+{
+	DGL_ctx* 	lpCtx = NULL;
+	LONG 		lpfnWndProc = 0L;
+	int  		i;
+	HGLRC 		hGLRC;
+	RECT 		rect;
+	PAINTSTRUCT	ps;
+    BOOL        bQuit = FALSE;
+    BOOL        bMain = FALSE;
+    LONG        rc;
+
+    // Get the window's message handler *before* it is unhooked in WM_DESTROY
+
+    // Is this the main window?
+    if (hwnd == glb.hWndActive) {
+        bMain = TRUE;
+        lpfnWndProc = glb.lpfnWndProc;
+    }
+    // Search for DGL context matching window handle
+    for (i=0; i<DGL_MAX_CONTEXTS; i++) {
+	    if (ctxlist[i].hWnd == hwnd) {
+	        lpCtx = &ctxlist[i];
+	        lpfnWndProc = lpCtx->lpfnWndProc;
+		    break;
+        }
+    }
+	// Not one of ours...
+	if (!lpfnWndProc)
+	    return DefWindowProc(hwnd, msg, wParam, lParam);
+
+    // Intercept messages amd process *before* passing on to window
+	switch (msg) {
+#ifdef _USE_GLD3_WGL
+	case WM_DISPLAYCHANGE:
+		glb.bPixelformatsDirty = TRUE;
+		break;
+#endif
+	case WM_ACTIVATEAPP:
+		glb.bAppActive = (BOOL)wParam;
+		ddlogPrintf(DDLOG_INFO, "Calling app has been %s", glb.bAppActive ? "activated" : "de-activated");
+		break;
+	case WM_ERASEBKGND:
+		// Eat the GDI erase event for the GL window
+        if (!lpCtx || !lpCtx->bHasBeenCurrent)
+            break;
+		lpCtx->bGDIEraseBkgnd = TRUE;
+		return TRUE;
+	case WM_PAINT:
+		// Eat the invalidated update region if render scene is in progress
+        if (!lpCtx || !lpCtx->bHasBeenCurrent)
+            break;
+		if (lpCtx->bFrameStarted) {
+			if (GetUpdateRect(hwnd, &rect, FALSE)) {
+				BeginPaint(hwnd, &ps);
+				EndPaint(hwnd, &ps);
+				ValidateRect(hwnd, &rect);
+				return TRUE;
+				}
+			}
+		break;
+	}
+	// Call the appropriate window message handler
+	rc = CallWindowProc((WNDPROC)lpfnWndProc, hwnd, msg, wParam, lParam);
+
+    // Intercept messages and process *after* passing on to window
+	switch (msg) {
+    case WM_QUIT:
+	case WM_DESTROY:
+        bQuit = TRUE;
+		if (lpCtx && lpCtx->bAllocated) {
+			ddlogPrintf(DDLOG_WARN, "WM_DESTROY detected for HWND=%X, HDC=%X, HGLRC=%d", hwnd, lpCtx->hDC, i+1);
+			dglDeleteContext((HGLRC)(i+1));
+		}
+		break;
+#if 0
+	case WM_SIZE:
+		// Resize surfaces to fit window but not viewport (in case app did not bother)
+        if (!lpCtx || !lpCtx->bHasBeenCurrent)
+            break;
+		w = LOWORD(lParam);
+		h = HIWORD(lParam);
+		if (lpCtx->dwWidth < w || lpCtx->dwHeight < h) {
+			if (!dglWglResizeBuffers(lpCtx->glCtx, TRUE))
+                 dglWglResizeBuffers(lpCtx->glCtx, FALSE);
+        }
+		break;
+#endif
+    }
+
+    // If the main window is quitting, then so should we...
+    if (bMain && bQuit) {
+		ddlogPrintf(DDLOG_SYSTEM, "shutting down after WM_DESTROY detected for main HWND=%X", hwnd);
+        dglDeleteContextState();
+        dglExitDriver();
+    }
+
+    return rc;
+}
+
+// ***********************************************************************
+
+// Driver Window message handler
+static LONG __stdcall GLD_EventWndProc(
+	HWND hwnd,
+	UINT msg,
+	WPARAM wParam,
+	LPARAM lParam)
+{
+	switch (msg) {
+        // May be sent by splash screen dialog on exit
+        case WM_ACTIVATE:
+            if (LOWORD(wParam) == WA_ACTIVE && glb.hWndActive) {
+                SetForegroundWindow(glb.hWndActive);
+                return 0;
+                }
+            break;
+	}
+	return DefWindowProc(hwnd, msg, wParam, lParam);
+}
+
+// ***********************************************************************
+
+// Intercepted Keyboard handler for detecting hot keys.
+LRESULT CALLBACK dglKeyProc(
+	int code,
+	WPARAM wParam,
+	LPARAM lParam)
+{
+	HWND hWnd, hWndFrame;
+	HGLRC hGLRC = NULL;
+	DGL_ctx* lpCtx = NULL;
+	int cmd = 0, dx1 = 0, dx2 = 0, i;
+	static BOOL bAltPressed = FALSE;
+	static BOOL bCtrlPressed = FALSE;
+	static BOOL bShiftPressed = FALSE;
+    RECT r, rf, rc;
+    POINT pt;
+    BOOL bForceReshape = FALSE;
+
+	return CallNextHookEx(hKeyHook, code, wParam, lParam);
+}
+
+// ***********************************************************************
+
+HWND hWndMatch;
+
+// Window handle enumeration procedure.
+BOOL CALLBACK dglEnumChildProc(
+    HWND hWnd,
+    LPARAM lParam)
+{
+    RECT rect;
+
+    // Find window handle with matching client rect.
+    GetClientRect(hWnd, &rect);
+    if (EqualRect(&rect, (RECT*)lParam)) {
+        hWndMatch = hWnd;
+        return FALSE;
+        }
+    // Continue with next child window.
+    return TRUE;
+}
+
+// ***********************************************************************
+
+// Find window handle with matching client rect.
+HWND dglFindWindowRect(
+    RECT* pRect)
+{
+    hWndMatch = NULL;
+    EnumChildWindows(GetForegroundWindow(), dglEnumChildProc, (LPARAM)pRect);
+    return hWndMatch;
+}
+
+// ***********************************************************************
+#ifndef _USE_GLD3_WGL
+void dglChooseDisplayMode(
+	DGL_ctx *lpCtx)
+{
+	// Note: Choose an exact match if possible.
+
+	int				i;
+	DWORD			area;
+	DWORD			bestarea;
+	DDSURFACEDESC2	*lpDDSD		= NULL;	// Mode list pointer
+	DDSURFACEDESC2	*lpBestDDSD = NULL;	// Pointer to best
+
+	lpDDSD = glb.lpDisplayModes;
+	for (i=0; i<glb.nDisplayModeCount; i++, lpDDSD++) {
+		if ((lpDDSD->dwWidth == lpCtx->dwWidth) &&
+			(lpDDSD->dwHeight == lpCtx->dwHeight))
+			goto matched; // Mode has been exactly matched
+		// Choose modes that are larger in both dimensions than
+		// the window, but smaller in area than the current best.
+		if ( (lpDDSD->dwWidth >= lpCtx->dwWidth) &&
+			 (lpDDSD->dwHeight >= lpCtx->dwHeight))
+		{
+			if (lpBestDDSD == NULL) {
+				lpBestDDSD = lpDDSD;
+				bestarea = lpDDSD->dwWidth * lpDDSD->dwHeight;
+				continue;
+			}
+			area = lpDDSD->dwWidth * lpDDSD->dwHeight;
+			if (area < bestarea) {
+				lpBestDDSD = lpDDSD;
+				bestarea = area;
+			}
+		}
+	}
+
+	// Safety check
+	if (lpBestDDSD == NULL) {
+		ddlogMessage(DDLOG_CRITICAL, "dglChooseDisplayMode");
+		return;
+	}
+
+	lpCtx->dwModeWidth = lpBestDDSD->dwWidth;
+	lpCtx->dwModeHeight = lpBestDDSD->dwHeight;
+matched:
+	ddlogPrintf(DDLOG_INFO, "Matched (%ldx%ld) to (%ldx%ld)",
+		lpCtx->dwWidth, lpCtx->dwHeight, lpCtx->dwModeWidth, lpCtx->dwModeHeight);
+}
+#endif // _USE_GLD3_WGL
+// ***********************************************************************
+
+static BOOL IsDevice(
+	DWORD *lpDeviceIdList,
+	DWORD dwDeviceId,
+	int count)
+{
+	int i;
+
+	for (i=0; i<count; i++)
+		if (dwDeviceId == lpDeviceIdList[i])
+			return TRUE;
+
+	return FALSE;
+}
+
+// ***********************************************************************
+
+void dglTestForBrokenCards(
+	DGL_ctx *lpCtx)
+{
+#ifndef _GLD3
+	DDDEVICEIDENTIFIER	dddi; // DX6 device identifier
+
+	// Sanity check.
+	if (lpCtx == NULL) {
+		// Testing for broken cards is sensitive area, so we don't want
+		// anything saying "broken cards" in the error message. ;)
+		ddlogMessage(DDLOG_ERROR, "Null context passed to TFBC\n");
+		return;
+	}
+
+	if (lpCtx->lpDD4 == NULL) {
+		// Testing for broken cards is sensitive area, so we don't want
+		// anything saying "broken cards" in the error message. ;)
+		ddlogMessage(DDLOG_ERROR, "Null DD4 passed to TFBC\n");
+		return;
+	}
+
+	// Microsoft really fucked up with the GetDeviceIdentifier function
+	// on Windows 2000, since it locks up on stock driers on the CD. Updated
+	// drivers from vendors appear to work, but we can't identify the drivers
+	// without this function!!! For now we skip these tests on Windows 2000.
+	if ((GetVersion() & 0x80000000UL) == 0)
+		return;
+
+	// Obtain device info
+	if (FAILED(IDirectDraw4_GetDeviceIdentifier(lpCtx->lpDD4, &dddi, 0)))
+		return;
+
+	// Useful info. Log it.
+	ddlogPrintf(DDLOG_INFO, "DirectDraw: VendorId=0x%x, DeviceId=0x%x", dddi.dwVendorId, dddi.dwDeviceId);
+
+	// Vendor 1: ATI
+	if (dddi.dwVendorId == VENDORID_ATI) {
+		// Test A: ATI Rage PRO
+		if (IsDevice(devATIRagePro, dddi.dwDeviceId, sizeof(devATIRagePro)))
+			glb.bUseMipmaps = FALSE;
+		// Test B: ATI Rage II+
+		if (IsDevice(devATIRageIIplus, dddi.dwDeviceId, sizeof(devATIRageIIplus)))
+			glb.bEmulateAlphaTest = TRUE;
+	}
+
+	// Vendor 2: Matrox
+	if (dddi.dwVendorId == 0x102B) {
+		// Test: Matrox G400 stencil buffer support does not work for AutoCAD
+		if (dddi.dwDeviceId == 0x0525) {
+			lpCtx->lpPF->pfd.cStencilBits = 0;
+			if (lpCtx->lpPF->iZBufferPF != -1) {
+				glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF].dwStencilBitDepth = 0;
+				glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF].dwStencilBitMask = 0;
+				glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF].dwFlags &= ~DDPF_STENCILBUFFER;
+			}
+		}
+	}
+#endif // _GLD3
+}
+
+// ***********************************************************************
+
+BOOL dglCreateContextBuffers(
+	HDC a,
+	DGL_ctx *lpCtx,
+	BOOL bFallback)
+{
+	HRESULT				hResult;
+
+	int					i;
+//	HGLRC				hGLRC;
+//	DGL_ctx*			lpCtx;
+
+#ifndef _USE_GLD3_WGL
+	DWORD				dwFlags;
+	DDSURFACEDESC2		ddsd2;
+	DDSCAPS2			ddscaps2;
+	LPDIRECTDRAWCLIPPER	lpddClipper;
+	D3DDEVICEDESC		D3DHWDevDesc;	// Direct3D Hardware description
+	D3DDEVICEDESC		D3DHELDevDesc;	// Direct3D Hardware Emulation Layer
+#endif // _USE_GLD3_WGL
+
+	float				inv_aspect;
+
+	GLenum				bDoubleBuffer;	// TRUE if double buffer required
+	GLenum				bDepthBuffer;	// TRUE if depth buffer required
+
+	const PIXELFORMATDESCRIPTOR	*lpPFD = &lpCtx->lpPF->pfd;
+
+	// Vars for Mesa visual
+	DWORD				dwDepthBits		= 0;
+	DWORD				dwStencilBits	= 0;
+	DWORD				dwAlphaBits		= 0;
+	DWORD				bAlphaSW		= GL_FALSE;
+	DWORD				bDouble			= GL_FALSE;
+
+	DDSURFACEDESC2 		ddsd2DisplayMode;
+	BOOL				bFullScrnWin	= FALSE;	// fullscreen-size window ?
+	DDBLTFX 			ddbltfx;
+	DWORD				dwMemoryType 	= (bFallback) ? DDSCAPS_SYSTEMMEMORY : glb.dwMemoryType;
+	BOOL				bBogusWindow	= FALSE;	// non-drawable window ?
+	DWORD               dwColorRef      = 0;        // GDI background color
+	RECT				rcDst;						// GDI window rect
+	POINT				pt;							// GDI window point
+
+	// Palette used for creating default global palette
+	PALETTEENTRY	ppe[256];
+
+#ifndef _USE_GLD3_WGL
+	// Vertex buffer description. Used for creation of vertex buffers
+	D3DVERTEXBUFFERDESC vbufdesc;
+#endif // _USE_GLD3_WGL
+
+#define DDLOG_CRITICAL_OR_WARN	(bFallback ? DDLOG_CRITICAL : DDLOG_WARN)
+
+	ddlogPrintf(DDLOG_SYSTEM, "dglCreateContextBuffers for HDC=%X", a);
+    nContextError = GLDERR_NONE;
+
+#ifdef GLD_THREADS
+	// Serialize access to DirectDraw object creation or DDS start
+	if (glb.bMultiThreaded)
+		EnterCriticalSection(&CriticalSection);
+#endif
+
+	// Check for back buffer
+	bDoubleBuffer = GL_TRUE; //(lpPFD->dwFlags & PFD_DOUBLEBUFFER) ? GL_TRUE : GL_FALSE;
+	// Since we always do back buffering, check if we emulate front buffering
+	lpCtx->EmulateSingle =
+		(lpPFD->dwFlags & PFD_DOUBLEBUFFER) ? FALSE : TRUE;
+#if 0	// Don't have to mimic MS OpenGL behavior for front-buffering (DaveM)
+	lpCtx->EmulateSingle |=
+		(lpPFD->dwFlags & PFD_SUPPORT_GDI) ? TRUE : FALSE;
+#endif
+
+	// Check for depth buffer
+	bDepthBuffer = (lpPFD->cDepthBits) ? GL_TRUE : GL_FALSE;
+
+	lpCtx->bDoubleBuffer = bDoubleBuffer;
+	lpCtx->bDepthBuffer = bDepthBuffer;
+
+	// Set the Fullscreen flag for the context.
+//	lpCtx->bFullscreen = glb.bFullscreen;
+
+	// Obtain the dimensions of the rendering window
+	lpCtx->hDC = a; // Cache DC
+	lpCtx->hWnd = WindowFromDC(lpCtx->hDC);
+	// Check for non-window DC = memory DC ?
+	if (lpCtx->hWnd == NULL) {
+        // bitmap memory contexts are always single-buffered
+        lpCtx->EmulateSingle = TRUE;
+		bBogusWindow = TRUE;
+		ddlogPrintf(DDLOG_INFO, "Non-Window Memory Device Context");
+		if (GetClipBox(lpCtx->hDC, &lpCtx->rcScreenRect) == ERROR) {
+			ddlogMessage(DDLOG_WARN, "GetClipBox failed in dglCreateContext\n");
+			SetRect(&lpCtx->rcScreenRect, 0, 0, 0, 0);
+		}
+	}
+	else if (!GetClientRect(lpCtx->hWnd, &lpCtx->rcScreenRect)) {
+		bBogusWindow = TRUE;
+		ddlogMessage(DDLOG_WARN, "GetClientRect failed in dglCreateContext\n");
+		SetRect(&lpCtx->rcScreenRect, 0, 0, 0, 0);
+	}
+	lpCtx->dwWidth = lpCtx->rcScreenRect.right - lpCtx->rcScreenRect.left;
+	lpCtx->dwHeight = lpCtx->rcScreenRect.bottom - lpCtx->rcScreenRect.top;
+
+	ddlogPrintf(DDLOG_INFO, "Input window %X: w=%i, h=%i",
+							lpCtx->hWnd, lpCtx->dwWidth, lpCtx->dwHeight);
+
+	// What if app only zeroes one dimension instead of both? (DaveM)
+	if ( (lpCtx->dwWidth == 0) || (lpCtx->dwHeight == 0) ) {
+		// Make the buffer size something sensible
+		lpCtx->dwWidth = 8;
+		lpCtx->dwHeight = 8;
+	}
+
+	// Set defaults
+	lpCtx->dwModeWidth = lpCtx->dwWidth;
+	lpCtx->dwModeHeight = lpCtx->dwHeight;
+/*
+	// Find best display mode for fullscreen
+	if (glb.bFullscreen || !glb.bPrimary) {
+		dglChooseDisplayMode(lpCtx);
+	}
+*/
+	// Misc initialisation
+	lpCtx->bCanRender = FALSE; // No rendering allowed yet
+	lpCtx->bSceneStarted = FALSE;
+	lpCtx->bFrameStarted = FALSE;
+
+	// Detect OS (specifically 'Windows 2000' or 'Windows XP')
+	DetectOS();
+
+	// NOTE: WinNT not supported
+	ddlogPrintf(DDLOG_INFO, "OS: %s", bHaveWin95 ? "Win9x" : (bHaveWin2K ? "Win2000/XP" : "Unsupported") );
+
+	// Test for Fullscreen
+	if (bHaveWin95) { // Problems with fullscreen on Win2K/XP
+		if ((GetSystemMetrics(SM_CXSCREEN) == lpCtx->dwWidth) && 
+			(GetSystemMetrics(SM_CYSCREEN) == lpCtx->dwHeight))
+		{
+			// Workaround for some apps that crash when going fullscreen.
+			//lpCtx->bFullscreen = TRUE;
+		}
+		
+	}
+
+#ifdef _USE_GLD3_WGL
+	_gldDriver.CreateDrawable(lpCtx, glb.bDirectDrawPersistant, glb.bPersistantBuffers);
+#else
+	// Check if DirectDraw has already been created by original GLRC (DaveM)
+	if (glb.bDirectDrawPersistant && glb.bDirectDraw) {
+		lpCtx->lpDD4 = glb.lpDD4;
+		IDirectDraw4_AddRef(lpCtx->lpDD4);
+		goto SkipDirectDrawCreate;
+	}
+
+	// Create DirectDraw object
+	if (glb.bPrimary)
+		hResult = DirectDrawCreate(NULL, &lpCtx->lpDD1, NULL);
+	else {
+		// A non-primary device is to be used.
+		// Force context to be Fullscreen, secondary adaptors can not
+		// be used in a window.
+		hResult = DirectDrawCreate(&glb.ddGuid, &lpCtx->lpDD1, NULL);
+		lpCtx->bFullscreen = TRUE;
+	}
+	if (FAILED(hResult)) {
+		MessageBox(NULL, "Unable to initialize DirectDraw", "GLDirect", MB_OK);
+		ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to create DirectDraw interface", hResult);
+        nContextError = GLDERR_DDRAW;
+		goto return_with_error;
+	}
+
+	// Query for DX6 IDirectDraw4.
+	hResult = IDirectDraw_QueryInterface(lpCtx->lpDD1,
+										 &IID_IDirectDraw4,
+										 (void**)&lpCtx->lpDD4);
+	if (FAILED(hResult)) {
+		MessageBox(NULL, "GLDirect requires DirectX 6.0 or above", "GLDirect", MB_OK);
+		ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to create DirectDraw4 interface", hResult);
+        nContextError = GLDERR_DDRAW;
+		goto return_with_error;
+	}
+
+	// Cache DirectDraw interface for subsequent GLRCs
+	if (glb.bDirectDrawPersistant && !glb.bDirectDraw) {
+		glb.lpDD4 = lpCtx->lpDD4;
+		IDirectDraw4_AddRef(glb.lpDD4);
+		glb.bDirectDraw = TRUE;
+	}
+SkipDirectDrawCreate:
+
+	// Now we have a DD4 interface we can check for broken cards
+	dglTestForBrokenCards(lpCtx);
+
+	// Test if primary device can use flipping instead of blitting
+	ZeroMemory(&ddsd2DisplayMode, sizeof(ddsd2DisplayMode));
+	ddsd2DisplayMode.dwSize = sizeof(ddsd2DisplayMode);
+	hResult = IDirectDraw4_GetDisplayMode(
+					lpCtx->lpDD4,
+					&ddsd2DisplayMode);
+	if (SUCCEEDED(hResult)) {
+		if ( (lpCtx->dwWidth == ddsd2DisplayMode.dwWidth) &&
+				 (lpCtx->dwHeight == ddsd2DisplayMode.dwHeight) ) {
+			// We have a fullscreen-size window
+			bFullScrnWin = TRUE;
+			// OK to use DirectDraw fullscreen mode ?
+			if (glb.bPrimary && !glb.bFullscreenBlit && !lpCtx->EmulateSingle && !glb.bDirectDrawPersistant) {
+				lpCtx->bFullscreen = TRUE;
+				ddlogMessage(DDLOG_INFO, "Primary upgraded to page flipping.\n");
+			}
+		}
+		// Cache the display mode dimensions
+		lpCtx->dwModeWidth = ddsd2DisplayMode.dwWidth;
+		lpCtx->dwModeHeight = ddsd2DisplayMode.dwHeight;
+	}
+
+	// Clamp the effective window dimensions to primary surface.
+	// We need to do this for D3D viewport dimensions even if wide
+	// surfaces are supported. This also is a good idea for handling
+	// whacked-out window dimensions passed for non-drawable windows
+	// like Solid Edge. (DaveM)
+	if (lpCtx->dwWidth > ddsd2DisplayMode.dwWidth)
+		lpCtx->dwWidth = ddsd2DisplayMode.dwWidth;
+	if (lpCtx->dwHeight > ddsd2DisplayMode.dwHeight)
+		lpCtx->dwHeight = ddsd2DisplayMode.dwHeight;
+
+	// Check for non-RGB desktop resolution
+	if (!lpCtx->bFullscreen && ddsd2DisplayMode.ddpfPixelFormat.dwRGBBitCount <= 8) {
+		ddlogPrintf(DDLOG_CRITICAL_OR_WARN, "Desktop color depth %d bpp not supported",
+			ddsd2DisplayMode.ddpfPixelFormat.dwRGBBitCount);
+        nContextError = GLDERR_BPP;
+		goto return_with_error;
+	}
+#endif // _USE_GLD3_WGL
+
+	ddlogPrintf(DDLOG_INFO, "Window: w=%i, h=%i (%s)",
+							lpCtx->dwWidth,
+							lpCtx->dwHeight,
+							lpCtx->bFullscreen ? "fullscreen" : "windowed");
+
+#ifndef _USE_GLD3_WGL
+	// Obtain ddraw caps
+    ZeroMemory(&lpCtx->ddCaps, sizeof(DDCAPS));
+	lpCtx->ddCaps.dwSize = sizeof(DDCAPS);
+	if (glb.bHardware) {
+		// Get HAL caps
+		IDirectDraw4_GetCaps(lpCtx->lpDD4, &lpCtx->ddCaps, NULL);
+	} else {
+		// Get HEL caps
+		IDirectDraw4_GetCaps(lpCtx->lpDD4, NULL, &lpCtx->ddCaps);
+	}
+
+	// If this flag is present then we can't default to Mesa
+	// SW rendering between BeginScene() and EndScene().
+	if (lpCtx->ddCaps.dwCaps2 & DDCAPS2_NO2DDURING3DSCENE) {
+		ddlogMessage(DDLOG_INFO,
+			"Warning          : No 2D allowed during 3D scene.\n");
+	}
+
+	// Query for DX6 Direct3D3 interface
+	hResult = IDirectDraw4_QueryInterface(lpCtx->lpDD4,
+										  &IID_IDirect3D3,
+										  (void**)&lpCtx->lpD3D3);
+	if (FAILED(hResult)) {
+		MessageBox(NULL, "Unable to initialize Direct3D", "GLDirect", MB_OK);
+		ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to create Direct3D interface", hResult);
+        nContextError = GLDERR_D3D;
+		goto return_with_error;
+	}
+
+	// Context creation
+	if (lpCtx->bFullscreen) {
+		// FULLSCREEN
+
+        // Disable warning popups when in fullscreen mode
+        ddlogWarnOption(FALSE);
+
+		// Have to release persistant primary surface if fullscreen mode
+		if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary) {
+			RELEASE(glb.lpPrimary4);
+			glb.bDirectDrawPrimary = FALSE;
+		}
+
+		dwFlags = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT;
+		if (glb.bFastFPU)
+			dwFlags |= DDSCL_FPUSETUP;	// fast FPU setup optional (DaveM)
+		hResult = IDirectDraw4_SetCooperativeLevel(lpCtx->lpDD4, lpCtx->hWnd, dwFlags);
+		if (FAILED(hResult)) {
+			ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to set Exclusive Fullscreen mode", hResult);
+			goto return_with_error;
+		}
+
+		hResult = IDirectDraw4_SetDisplayMode(lpCtx->lpDD4,
+											  lpCtx->dwModeWidth,
+											  lpCtx->dwModeHeight,
+											  lpPFD->cColorBits,
+											  0,
+											  0);
+		if (FAILED(hResult)) {
+			ddlogError(DDLOG_CRITICAL_OR_WARN, "SetDisplayMode failed", hResult);
+			goto return_with_error;
+		}
+
+		// ** The display mode has changed, so dont use MessageBox! **
+
+		ZeroMemory(&ddsd2, sizeof(ddsd2));
+		ddsd2.dwSize = sizeof(ddsd2);
+
+		if (bDoubleBuffer) {
+			// Double buffered
+			// Primary surface
+			ddsd2.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
+			ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
+								   DDSCAPS_FLIP |
+								   DDSCAPS_COMPLEX |
+								   DDSCAPS_3DDEVICE |
+								   dwMemoryType;
+			ddsd2.dwBackBufferCount = 1;
+
+			hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpFront4, NULL);
+			if (FAILED(hResult)) {
+				ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateSurface (primary) failed", hResult);
+                nContextError = GLDERR_MEM;
+				goto return_with_error;
+			}
+
+			// Render target surface
+			ZeroMemory(&ddscaps2, sizeof(ddscaps2)); // Clear the entire struct.
+			ddscaps2.dwCaps = DDSCAPS_BACKBUFFER;
+			hResult = IDirectDrawSurface4_GetAttachedSurface(lpCtx->lpFront4, &ddscaps2, &lpCtx->lpBack4);
+			if (FAILED(hResult)) {
+				ddlogError(DDLOG_CRITICAL_OR_WARN, "GetAttachedSurface failed", hResult);
+                nContextError = GLDERR_MEM;
+				goto return_with_error;
+			}
+		} else {
+			// Single buffered
+			// Primary surface
+			ddsd2.dwFlags = DDSD_CAPS;
+			ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
+								   //DDSCAPS_3DDEVICE |
+								   dwMemoryType;
+
+			hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpFront4, NULL);
+			if (FAILED(hResult)) {
+				ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateSurface (primary) failed", hResult);
+                nContextError = GLDERR_MEM;
+				goto return_with_error;
+			}
+
+			lpCtx->lpBack4 = NULL;
+		}
+	} else {
+		// WINDOWED
+
+        // OK to enable warning popups in windowed mode
+        ddlogWarnOption(glb.bMessageBoxWarnings);
+
+		dwFlags = DDSCL_NORMAL;
+		if (glb.bMultiThreaded)
+			dwFlags |= DDSCL_MULTITHREADED;
+		if (glb.bFastFPU)
+			dwFlags |= DDSCL_FPUSETUP;	// fast FPU setup optional (DaveM)
+		hResult = IDirectDraw4_SetCooperativeLevel(lpCtx->lpDD4,
+												  lpCtx->hWnd,
+												  dwFlags);
+		if (FAILED(hResult)) {
+			ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to set Normal coop level", hResult);
+			goto return_with_error;
+		}
+		// Has Primary surface already been created for original GLRC ?
+		// Note this can only be applicable for windowed modes
+		if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary) {
+			lpCtx->lpFront4 = glb.lpPrimary4;
+			IDirectDrawSurface4_AddRef(lpCtx->lpFront4);
+			// Update the window on the default clipper
+			IDirectDrawSurface4_GetClipper(lpCtx->lpFront4, &lpddClipper);
+			IDirectDrawClipper_SetHWnd(lpddClipper, 0, lpCtx->hWnd);
+			IDirectDrawClipper_Release(lpddClipper);
+			goto SkipPrimaryCreate;
+		}
+
+		// Primary surface
+		ZeroMemory(&ddsd2, sizeof(ddsd2));
+		ddsd2.dwSize = sizeof(ddsd2);
+		ddsd2.dwFlags = DDSD_CAPS;
+		ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+		hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpFront4, NULL);
+		if (FAILED(hResult)) {
+			ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateSurface (primary) failed", hResult);
+            nContextError = GLDERR_MEM;
+			goto return_with_error;
+		}
+
+		// Cache Primary surface for subsequent GLRCs
+		// Note this can only be applicable to subsequent windowed modes
+		if (glb.bDirectDrawPersistant && !glb.bDirectDrawPrimary) {
+			glb.lpPrimary4 = lpCtx->lpFront4;
+			IDirectDrawSurface4_AddRef(glb.lpPrimary4);
+			glb.bDirectDrawPrimary = TRUE;
+		}
+
+		// Clipper object
+		hResult = DirectDrawCreateClipper(0, &lpddClipper, NULL);
+		if (FAILED(hResult)) {
+			ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateClipper failed", hResult);
+			goto return_with_error;
+		}
+		hResult = IDirectDrawClipper_SetHWnd(lpddClipper, 0, lpCtx->hWnd);
+		if (FAILED(hResult)) {
+			RELEASE(lpddClipper);
+			ddlogError(DDLOG_CRITICAL_OR_WARN, "SetHWnd failed", hResult);
+			goto return_with_error;
+		}
+		hResult = IDirectDrawSurface4_SetClipper(lpCtx->lpFront4, lpddClipper);
+		RELEASE(lpddClipper); // We have finished with it.
+		if (FAILED(hResult)) {
+			ddlogError(DDLOG_CRITICAL_OR_WARN, "SetClipper failed", hResult);
+			goto return_with_error;
+		}
+SkipPrimaryCreate:
+
+		if (bDoubleBuffer) {
+			// Render target surface
+			ZeroMemory(&ddsd2, sizeof(ddsd2));
+			ddsd2.dwSize = sizeof(ddsd2);
+			ddsd2.dwFlags        = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
+			ddsd2.dwWidth        = lpCtx->dwWidth;
+			ddsd2.dwHeight       = lpCtx->dwHeight;
+			ddsd2.ddsCaps.dwCaps = DDSCAPS_3DDEVICE |
+								   DDSCAPS_OFFSCREENPLAIN |
+								   dwMemoryType;
+
+			// Reserve the entire desktop size for persistant buffers option
+			if (glb.bDirectDrawPersistant && glb.bPersistantBuffers) {
+				ddsd2.dwWidth = ddsd2DisplayMode.dwWidth;
+				ddsd2.dwHeight = ddsd2DisplayMode.dwHeight;
+			}
+			// Re-use original back buffer if persistant buffers exist
+			if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && glb.lpBack4)
+				hResult = IDirectDrawSurface4_AddRef(lpCtx->lpBack4 = glb.lpBack4);
+			else
+				hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpBack4, NULL);
+			if (FAILED(hResult)) {
+				ddlogError(DDLOG_CRITICAL_OR_WARN, "Create Backbuffer failed", hResult);
+                nContextError = GLDERR_MEM;
+				goto return_with_error;
+			}
+			if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && !glb.lpBack4)
+				IDirectDrawSurface4_AddRef(glb.lpBack4 = lpCtx->lpBack4);
+		} else {
+			lpCtx->lpBack4 = NULL;
+		}
+	}
+
+	//
+	// Now create the Z-buffer
+	//
+	lpCtx->bStencil = FALSE; // Default to no stencil buffer
+	if (bDepthBuffer && (lpCtx->lpPF->iZBufferPF != -1)) {
+		// Get z-buffer dimensions from the render target
+		// Setup the surface desc for the z-buffer.
+		ZeroMemory(&ddsd2, sizeof(ddsd2));
+		ddsd2.dwSize = sizeof(ddsd2);
+		ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
+		ddsd2.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | dwMemoryType;
+		ddsd2.dwWidth = lpCtx->dwWidth;
+		ddsd2.dwHeight = lpCtx->dwHeight;
+		memcpy(&ddsd2.ddpfPixelFormat,
+			&glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF],
+			sizeof(DDPIXELFORMAT) );
+
+		// Reserve the entire desktop size for persistant buffers option
+		if (glb.bDirectDrawPersistant && glb.bPersistantBuffers) {
+			ddsd2.dwWidth = ddsd2DisplayMode.dwWidth;
+			ddsd2.dwHeight = ddsd2DisplayMode.dwHeight;
+		}
+
+		// Create a z-buffer
+		if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && glb.lpDepth4)
+			hResult = IDirectDrawSurface4_AddRef(lpCtx->lpDepth4 = glb.lpDepth4);
+		else
+			hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpDepth4, NULL);
+		if (FAILED(hResult)) {
+			ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateSurface (ZBuffer) failed", hResult);
+            nContextError = GLDERR_MEM;
+			goto return_with_error;
+		}
+		if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && !glb.lpDepth4)
+			IDirectDrawSurface4_AddRef(glb.lpDepth4 = lpCtx->lpDepth4);
+		else if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && glb.lpDepth4 && glb.lpBack4)
+			IDirectDrawSurface4_DeleteAttachedSurface(glb.lpBack4, 0, glb.lpDepth4);
+
+		// Attach Zbuffer to render target
+		TRY(IDirectDrawSurface4_AddAttachedSurface(
+			bDoubleBuffer ? lpCtx->lpBack4 : lpCtx->lpFront4,
+			lpCtx->lpDepth4),
+			"dglCreateContext: Attach Zbuffer");
+		if (glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF].dwFlags & DDPF_STENCILBUFFER) {
+			lpCtx->bStencil = TRUE;
+			ddlogMessage(DDLOG_INFO, "Depth buffer has stencil\n");
+		}
+	}
+
+	// Clear all back buffers and Z-buffers in case of memory recycling.
+	ZeroMemory(&ddbltfx, sizeof(ddbltfx));
+	ddbltfx.dwSize = sizeof(ddbltfx);
+	IDirectDrawSurface4_Blt(lpCtx->lpBack4, NULL, NULL, NULL,
+		DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
+	if (lpCtx->lpDepth4)
+		IDirectDrawSurface4_Blt(lpCtx->lpDepth4, NULL, NULL, NULL,
+			DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
+
+	// Now that we have a Z-buffer we can create the 3D device
+	hResult = IDirect3D3_CreateDevice(lpCtx->lpD3D3,
+									  &glb.d3dGuid,
+									  bDoubleBuffer ? lpCtx->lpBack4 : lpCtx->lpFront4,
+									  &lpCtx->lpDev3,
+									  NULL);
+	if (FAILED(hResult)) {
+		ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to create Direct3D device", hResult);
+        nContextError = GLDERR_D3D;
+		goto return_with_error;
+	}
+
+	// We must do this as soon as the device is created
+	dglInitStateCaches(lpCtx);
+
+	// Obtain the D3D Device Description
+	D3DHWDevDesc.dwSize = D3DHELDevDesc.dwSize = sizeof(D3DDEVICEDESC);
+	TRY(IDirect3DDevice3_GetCaps(lpCtx->lpDev3,
+								 &D3DHWDevDesc,
+								 &D3DHELDevDesc),
+								 "dglCreateContext: GetCaps failed");
+
+	// Choose the relevant description and cache it in the context.
+	// We will use this description later for caps checking
+	memcpy(	&lpCtx->D3DDevDesc,
+			glb.bHardware ? &D3DHWDevDesc : &D3DHELDevDesc,
+			sizeof(D3DDEVICEDESC));
+
+	// Now we can examine the texture formats
+	if (!dglBuildTextureFormatList(lpCtx->lpDev3)) {
+		ddlogMessage(DDLOG_CRITICAL_OR_WARN, "dglBuildTextureFormatList failed\n");
+		goto return_with_error;
+	}
+
+	// Get the pixel format of the back buffer
+	lpCtx->ddpfRender.dwSize = sizeof(lpCtx->ddpfRender);
+	if (bDoubleBuffer)
+		hResult = IDirectDrawSurface4_GetPixelFormat(
+					lpCtx->lpBack4,
+					&lpCtx->ddpfRender);
+	else
+		hResult = IDirectDrawSurface4_GetPixelFormat(
+					lpCtx->lpFront4,
+					&lpCtx->ddpfRender);
+
+	if (FAILED(hResult)) {
+		ddlogError(DDLOG_CRITICAL_OR_WARN, "GetPixelFormat failed", hResult);
+		goto return_with_error;
+	}
+	// Find a pixel packing function suitable for this surface
+	pxClassifyPixelFormat(&lpCtx->ddpfRender,
+						  &lpCtx->fnPackFunc,
+						  &lpCtx->fnUnpackFunc,
+						  &lpCtx->fnPackSpanFunc);
+
+	// Viewport
+	hResult = IDirect3D3_CreateViewport(lpCtx->lpD3D3, &lpCtx->lpViewport3, NULL);
+	if (FAILED(hResult)) {
+		ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateViewport failed", hResult);
+		goto return_with_error;
+	}
+
+	hResult = IDirect3DDevice3_AddViewport(lpCtx->lpDev3, lpCtx->lpViewport3);
+	if (FAILED(hResult)) {
+		ddlogError(DDLOG_CRITICAL_OR_WARN, "AddViewport failed", hResult);
+		goto return_with_error;
+	}
+
+	// Initialise the viewport
+	// Note screen coordinates are used for viewport clipping since D3D
+	// transform operations are not used in the GLD CAD driver. (DaveM)
+	inv_aspect = (float)lpCtx->dwHeight/(float)lpCtx->dwWidth;
+
+	lpCtx->d3dViewport.dwSize = sizeof(lpCtx->d3dViewport);
+	lpCtx->d3dViewport.dwX = 0;
+	lpCtx->d3dViewport.dwY = 0;
+	lpCtx->d3dViewport.dwWidth = lpCtx->dwWidth;
+	lpCtx->d3dViewport.dwHeight = lpCtx->dwHeight;
+	lpCtx->d3dViewport.dvClipX = 0; // -1.0f;
+	lpCtx->d3dViewport.dvClipY = 0; // inv_aspect;
+	lpCtx->d3dViewport.dvClipWidth = lpCtx->dwWidth; // 2.0f;
+	lpCtx->d3dViewport.dvClipHeight = lpCtx->dwHeight; // 2.0f * inv_aspect;
+	lpCtx->d3dViewport.dvMinZ = 0.0f;
+	lpCtx->d3dViewport.dvMaxZ = 1.0f;
+	TRY(IDirect3DViewport3_SetViewport2(lpCtx->lpViewport3, &lpCtx->d3dViewport), "dglCreateContext: SetViewport2");
+
+	hResult = IDirect3DDevice3_SetCurrentViewport(lpCtx->lpDev3, lpCtx->lpViewport3);
+	if (FAILED(hResult)) {
+		ddlogError(DDLOG_CRITICAL_OR_WARN, "SetCurrentViewport failed", hResult);
+		goto return_with_error;
+	}
+
+	lpCtx->dwBPP = lpPFD->cColorBits;
+	lpCtx->iZBufferPF = lpCtx->lpPF->iZBufferPF;
+
+	// Set last texture to NULL
+	for (i=0; i<MAX_TEXTURE_UNITS; i++) {
+		lpCtx->ColorOp[i] = D3DTOP_DISABLE;
+		lpCtx->AlphaOp[i] = D3DTOP_DISABLE;
+		lpCtx->tObj[i] = NULL;
+	}
+
+	// Default to perspective correct texture mapping
+	dglSetRenderState(lpCtx, D3DRENDERSTATE_TEXTUREPERSPECTIVE, TRUE, "TexturePersp");
+
+	// Set the default culling mode
+	lpCtx->cullmode = D3DCULL_NONE;
+	dglSetRenderState(lpCtx, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE, "CullMode");
+
+	// Disable specular
+	dglSetRenderState(lpCtx, D3DRENDERSTATE_SPECULARENABLE, FALSE, "SpecularEnable");
+	// Disable subpixel correction
+//	dglSetRenderState(lpCtx, D3DRENDERSTATE_SUBPIXEL, FALSE, "SubpixelEnable");
+	// Disable dithering
+	dglSetRenderState(lpCtx, D3DRENDERSTATE_DITHERENABLE, FALSE, "DitherEnable");
+
+	// Initialise the primitive caches
+//	lpCtx->dwNextLineVert	= 0;
+//	lpCtx->dwNextTriVert	= 0;
+
+	// Init the global texture palette
+	lpCtx->lpGlobalPalette = NULL;
+
+	// Init the HW/SW usage counters
+//	lpCtx->dwHWUsageCount = lpCtx->dwSWUsageCount = 0L;
+
+	//
+	// Create two D3D vertex buffers.
+	// One will hold the pre-transformed data with the other one
+	// being used to hold the post-transformed & clipped verts.
+	//
+#if 0  // never used (DaveM)
+	vbufdesc.dwSize = sizeof(D3DVERTEXBUFFERDESC);
+	vbufdesc.dwCaps = D3DVBCAPS_WRITEONLY;
+	if (glb.bHardware == FALSE)
+		vbufdesc.dwCaps = D3DVBCAPS_SYSTEMMEMORY;
+	vbufdesc.dwNumVertices = 32768; // For the time being
+
+	// Source vertex buffer
+	vbufdesc.dwFVF = DGL_LVERTEX;
+	hResult = IDirect3D3_CreateVertexBuffer(lpCtx->lpD3D3, &vbufdesc, &lpCtx->m_vbuf, 0, NULL);
+	if (FAILED(hResult)) {
+		ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateVertexBuffer(src) failed", hResult);
+		goto return_with_error;
+	}
+
+	// Destination vertex buffer
+	vbufdesc.dwFVF = (glb.bMultitexture == FALSE) ? D3DFVF_TLVERTEX : (D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX2);
+	hResult = IDirect3D3_CreateVertexBuffer(lpCtx->lpD3D3, &vbufdesc, &lpCtx->m_pvbuf, 0, NULL);
+	if(FAILED(hResult)) {
+		ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateVertexBuffer(dst) failed", hResult);
+		goto return_with_error;
+	}
+#endif
+
+#endif _USE_GLD3_WGL
+
+	//
+	//	Now create the Mesa context
+	//
+
+	// Create the Mesa visual
+	if (lpPFD->cDepthBits)
+		dwDepthBits = 16;
+	if (lpPFD->cStencilBits)
+		dwStencilBits = 8;
+	if (lpPFD->cAlphaBits) {
+		dwAlphaBits = 8;
+		bAlphaSW = GL_TRUE;
+	}
+	if (lpPFD->dwFlags & PFD_DOUBLEBUFFER)
+		bDouble = GL_TRUE;
+//	lpCtx->EmulateSingle =
+//		(lpPFD->dwFlags & PFD_DOUBLEBUFFER) ? FALSE : TRUE;
+
+#ifdef _USE_GLD3_WGL
+	lpCtx->glVis = _mesa_create_visual(
+		bDouble,    /* double buffer */
+		GL_FALSE,			// stereo
+		lpPFD->cRedBits,
+		lpPFD->cGreenBits,
+		lpPFD->cBlueBits,
+		dwAlphaBits,
+		dwDepthBits,
+		dwStencilBits,
+		lpPFD->cAccumRedBits,	// accum bits
+		lpPFD->cAccumGreenBits,	// accum bits
+		lpPFD->cAccumBlueBits,	// accum bits
+		lpPFD->cAccumAlphaBits,	// accum alpha bits
+		1				// num samples
+		);
+#else // _USE_GLD3_WGL
+	lpCtx->glVis = (*mesaFuncs.gl_create_visual)(
+		GL_TRUE,			// RGB mode
+		bAlphaSW,			// Is an alpha buffer required?
+		bDouble,			// Is an double-buffering required?
+		GL_FALSE,			// stereo
+		dwDepthBits,		// depth_size
+		dwStencilBits,		// stencil_size
+		lpPFD->cAccumBits,	// accum_size
+		0,					// colour-index bits
+		lpPFD->cRedBits,	// Red bit count
+		lpPFD->cGreenBits,	// Green bit count
+		lpPFD->cBlueBits,	// Blue bit count
+		dwAlphaBits			// Alpha bit count
+		);
+#endif // _USE_GLD3_WGL
+
+	if (lpCtx->glVis == NULL) {
+		ddlogMessage(DDLOG_CRITICAL_OR_WARN, "gl_create_visual failed\n");
+		goto return_with_error;
+	}
+
+#ifdef _USE_GLD3_WGL
+	lpCtx->glCtx = _mesa_create_context(API_OPENGL, lpCtx->glVis, NULL, (void *)lpCtx, GL_TRUE);
+#else
+	// Create the Mesa context
+	lpCtx->glCtx = (*mesaFuncs.gl_create_context)(
+					lpCtx->glVis,	// Mesa visual
+					NULL,			// share list context
+					(void *)lpCtx,	// Pointer to our driver context
+					GL_TRUE			// Direct context flag
+				   );
+#endif // _USE_GLD3_WGL
+
+	if (lpCtx->glCtx == NULL) {
+		ddlogMessage(DDLOG_CRITICAL_OR_WARN, "gl_create_context failed\n");
+		goto return_with_error;
+	}
+
+	// Create the Mesa framebuffer
+#ifdef _USE_GLD3_WGL
+	lpCtx->glBuffer = _mesa_create_framebuffer(
+		lpCtx->glVis,
+		lpCtx->glVis->depthBits > 0,
+		lpCtx->glVis->stencilBits > 0,
+		lpCtx->glVis->accumRedBits > 0,
+		GL_FALSE //swalpha
+		);
+#else
+	lpCtx->glBuffer = (*mesaFuncs.gl_create_framebuffer)(lpCtx->glVis);
+#endif // _USE_GLD3_WGL
+
+	if (lpCtx->glBuffer == NULL) {
+		ddlogMessage(DDLOG_CRITICAL_OR_WARN, "gl_create_framebuffer failed\n");
+		goto return_with_error;
+	}
+
+#ifdef _USE_GLD3_WGL
+	// Init Mesa internals
+	_swrast_CreateContext( lpCtx->glCtx );
+	_vbo_CreateContext( lpCtx->glCtx );
+	_tnl_CreateContext( lpCtx->glCtx );
+	_swsetup_CreateContext( lpCtx->glCtx );
+
+	_gldDriver.InitialiseMesa(lpCtx);
+	
+	lpCtx->glCtx->imports.warning	= _gld_mesa_warning;
+	lpCtx->glCtx->imports.fatal		= _gld_mesa_fatal;
+
+#else
+	// Tell Mesa how many texture stages we have
+	glb.wMaxSimultaneousTextures = lpCtx->D3DDevDesc.wMaxSimultaneousTextures;
+	// Only use as many Units as the spec requires
+	if (glb.wMaxSimultaneousTextures > MAX_TEXTURE_UNITS)
+		glb.wMaxSimultaneousTextures = MAX_TEXTURE_UNITS;
+	lpCtx->glCtx->Const.MaxTextureUnits = glb.wMaxSimultaneousTextures;
+	ddlogPrintf(DDLOG_INFO, "Texture stages   : %d", glb.wMaxSimultaneousTextures);
+
+	// Set the max texture size.
+	// NOTE: clamped to a max of 1024 for extra performance!
+	lpCtx->dwMaxTextureSize = (lpCtx->D3DDevDesc.dwMaxTextureWidth <= 1024) ? lpCtx->D3DDevDesc.dwMaxTextureWidth : 1024;
+
+// Texture resize takes place elsewhere. KH
+// NOTE: This was added to workaround an issue with the Intel app.
+#if 0
+	lpCtx->glCtx->Const.MaxTextureSize = lpCtx->dwMaxTextureSize;
+#else
+	lpCtx->glCtx->Const.MaxTextureSize = 1024;
+#endif
+	lpCtx->glCtx->Const.MaxDrawBuffers = 1;
+
+	// Setup the Display Driver pointers
+	dglSetupDDPointers(lpCtx->glCtx);
+
+	// Initialise all the Direct3D renderstates
+	dglInitStateD3D(lpCtx->glCtx);
+
+#if 0
+	// Signal a reload of texture state on next glBegin
+	lpCtx->m_texHandleValid = FALSE;
+	lpCtx->m_mtex = FALSE;
+	lpCtx->m_texturing = FALSE;
+#else
+	// Set default texture unit state
+//	dglSetTexture(lpCtx, 0, NULL);
+//	dglSetTexture(lpCtx, 1, NULL);
+#endif
+
+	//
+	// Set the global texture palette to default values.
+	//
+
+	// Clear the entire palette
+	ZeroMemory(ppe, sizeof(PALETTEENTRY) * 256);
+
+	// Fill the palette with a default colour.
+	// A garish colour is used to catch bugs. Here Magenta is used.
+	for (i=0; i < 256; i++) {
+		ppe[i].peRed	= 255;
+		ppe[i].peGreen	= 0;
+		ppe[i].peBlue	= 255;
+	}
+
+	RELEASE(lpCtx->lpGlobalPalette);
+
+	if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && glb.lpGlobalPalette)
+		hResult = IDirectDrawPalette_AddRef(lpCtx->lpGlobalPalette = glb.lpGlobalPalette);
+	else
+		hResult = IDirectDraw4_CreatePalette(
+				lpCtx->lpDD4,
+				DDPCAPS_INITIALIZE | DDPCAPS_8BIT | DDPCAPS_ALLOW256,
+				ppe,
+				&(lpCtx->lpGlobalPalette),
+				NULL);
+	if (FAILED(hResult)) {
+		ddlogError(DDLOG_ERROR, "Default CreatePalette failed\n", hResult);
+		lpCtx->lpGlobalPalette = NULL;
+		goto return_with_error;
+	}
+	if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && !glb.lpGlobalPalette)
+		IDirectDrawPalette_AddRef(glb.lpGlobalPalette = lpCtx->lpGlobalPalette);
+
+#endif // _USE_GLD3_WGL
+
+	// ** If we have made it to here then we can enable rendering **
+	lpCtx->bCanRender = TRUE;
+
+//	ddlogMessage(DDLOG_SYSTEM, "dglCreateContextBuffers succeded\n");
+
+#ifdef GLD_THREADS
+	// Release serialized access
+	if (glb.bMultiThreaded)
+		LeaveCriticalSection(&CriticalSection);
+#endif
+
+	return TRUE;
+
+return_with_error:
+	// Clean up before returning.
+	// This is critical for secondary devices.
+
+	lpCtx->bCanRender = FALSE;
+
+#ifdef _USE_GLD3_WGL
+	// Destroy the Mesa context
+	if (lpCtx->glBuffer)
+		_mesa_destroy_framebuffer(lpCtx->glBuffer);
+	if (lpCtx->glCtx)
+		_mesa_destroy_context(lpCtx->glCtx);
+	if (lpCtx->glVis)
+		_mesa_destroy_visual(lpCtx->glVis);
+
+	// Destroy driver data
+	_gldDriver.DestroyDrawable(lpCtx);
+#else
+	// Destroy the Mesa context
+	if (lpCtx->glBuffer)
+		(*mesaFuncs.gl_destroy_framebuffer)(lpCtx->glBuffer);
+	if (lpCtx->glCtx)
+		(*mesaFuncs.gl_destroy_context)(lpCtx->glCtx);
+	if (lpCtx->glVis)
+		(*mesaFuncs.gl_destroy_visual)(lpCtx->glVis);
+
+	RELEASE(lpCtx->m_pvbuf); // Release D3D vertex buffer
+	RELEASE(lpCtx->m_vbuf); // Release D3D vertex buffer
+
+	if (lpCtx->lpViewport3) {
+		if (lpCtx->lpDev3) IDirect3DDevice3_DeleteViewport(lpCtx->lpDev3, lpCtx->lpViewport3);
+		RELEASE(lpCtx->lpViewport3);
+		lpCtx->lpViewport3 = NULL;
+	}
+
+	RELEASE(lpCtx->lpDev3);
+	if (lpCtx->lpDepth4) {
+		if (lpCtx->lpBack4)
+			IDirectDrawSurface4_DeleteAttachedSurface(lpCtx->lpBack4, 0L, lpCtx->lpDepth4);
+		else
+			IDirectDrawSurface4_DeleteAttachedSurface(lpCtx->lpFront4, 0L, lpCtx->lpDepth4);
+		RELEASE(lpCtx->lpDepth4);
+		lpCtx->lpDepth4 = NULL;
+	}
+	RELEASE(lpCtx->lpBack4);
+	RELEASE(lpCtx->lpFront4);
+	else
+	if (lpCtx->bFullscreen) {
+		IDirectDraw4_RestoreDisplayMode(lpCtx->lpDD4);
+		IDirectDraw4_SetCooperativeLevel(lpCtx->lpDD4, NULL, DDSCL_NORMAL);
+	}
+	RELEASE(lpCtx->lpD3D3);
+	RELEASE(lpCtx->lpDD4);
+	RELEASE(lpCtx->lpDD1);
+#endif // _USE_GLD3_WGL
+
+	lpCtx->bAllocated = FALSE;
+
+#ifdef GLD_THREADS
+	// Release serialized access
+	if (glb.bMultiThreaded)
+		LeaveCriticalSection(&CriticalSection);
+#endif
+
+	return FALSE;
+
+#undef DDLOG_CRITICAL_OR_WARN
+}
+
+// ***********************************************************************
+
+HGLRC dglCreateContext(
+	HDC a,
+	const DGL_pixelFormat *lpPF)
+{
+	int i;
+	HGLRC				hGLRC;
+	DGL_ctx*			lpCtx;
+	static BOOL			bWarnOnce = TRUE;
+	DWORD				dwThreadId = GetCurrentThreadId();
+    char                szMsg[256];
+    HWND                hWnd;
+    LONG                lpfnWndProc;
+
+	// Validate license
+	if (!dglValidate())
+		return NULL;
+
+	// Is context state ready ?
+	if (!bContextReady)
+		return NULL;
+
+	ddlogPrintf(DDLOG_SYSTEM, "dglCreateContext for HDC=%X, ThreadId=%X", a, dwThreadId);
+
+	// Find next free context.
+	// Also ensure that only one Fullscreen context is created at any one time.
+	hGLRC = 0; // Default to Not Found
+	for (i=0; i<DGL_MAX_CONTEXTS; i++) {
+		if (ctxlist[i].bAllocated) {
+			if (/*glb.bFullscreen && */ctxlist[i].bFullscreen)
+				break;
+		} else {
+			hGLRC = (HGLRC)(i+1);
+			break;
+		}
+	}
+
+	// Bail if no GLRC was found
+	if (!hGLRC)
+		return NULL;
+
+	// Set the context pointer
+	lpCtx = dglGetContextAddress(hGLRC);
+	// Make sure that context is zeroed before we do anything.
+	// MFC and C++ apps call wglCreateContext() and wglDeleteContext() multiple times,
+	// even though only one context is ever used by the app, so keep it clean. (DaveM)
+	ZeroMemory(lpCtx, sizeof(DGL_ctx));
+	lpCtx->bAllocated = TRUE;
+	// Flag that buffers need creating on next wglMakeCurrent call.
+	lpCtx->bHasBeenCurrent = FALSE;
+	lpCtx->lpPF = (DGL_pixelFormat *)lpPF;	// cache pixel format
+	lpCtx->bCanRender = FALSE;
+
+	// Create all the internal resources here, not in dglMakeCurrent().
+	// We do a re-size check in dglMakeCurrent in case of re-allocations. (DaveM)
+	// We now try context allocations twice, first with video memory,
+	// then again with system memory. This is similar to technique
+	// used for dglWglResizeBuffers(). (DaveM)
+	if (lpCtx->bHasBeenCurrent == FALSE) {
+		if (!dglCreateContextBuffers(a, lpCtx, FALSE)) {
+			if (glb.bMessageBoxWarnings && bWarnOnce && dwLogging) {
+				bWarnOnce = FALSE;
+                switch (nContextError) {
+                   case GLDERR_DDRAW: strcpy(szMsg, szDDrawWarning); break;
+                   case GLDERR_D3D: strcpy(szMsg, szD3DWarning); break;
+                   case GLDERR_MEM: strcpy(szMsg, szResourceWarning); break;
+                   case GLDERR_BPP: strcpy(szMsg, szBPPWarning); break;
+                   default: strcpy(szMsg, "");
+                }
+                if (strlen(szMsg))
+                    MessageBox(NULL, szMsg, "GLDirect", MB_OK | MB_ICONWARNING);
+			}
+            // Only need to try again if memory error
+            if (nContextError == GLDERR_MEM) {
+			    ddlogPrintf(DDLOG_WARN, "dglCreateContext failed 1st time with video memory");
+            }
+            else {
+			    ddlogPrintf(DDLOG_ERROR, "dglCreateContext failed");
+                return NULL;
+            }
+		}
+	}
+
+	// Now that we have a hWnd, we can intercept the WindowProc.
+    hWnd = lpCtx->hWnd;
+    if (hWnd) {
+		// Only hook individual window handler once if not hooked before.
+		lpfnWndProc = GetWindowLong(hWnd, GWL_WNDPROC);
+		if (lpfnWndProc != (LONG)dglWndProc) {
+			lpCtx->lpfnWndProc = lpfnWndProc;
+			SetWindowLong(hWnd, GWL_WNDPROC, (LONG)dglWndProc);
+			}
+        // Find the parent window of the app too.
+        if (glb.hWndActive == NULL) {
+            while (hWnd != NULL) {
+                glb.hWndActive = hWnd;
+                hWnd = GetParent(hWnd);
+            }
+            // Hook the parent window too.
+            lpfnWndProc = GetWindowLong(glb.hWndActive, GWL_WNDPROC);
+            if (glb.hWndActive == lpCtx->hWnd)
+                glb.lpfnWndProc = lpCtx->lpfnWndProc;
+            else if (lpfnWndProc != (LONG)dglWndProc)
+                glb.lpfnWndProc = lpfnWndProc;
+            if (glb.lpfnWndProc)
+                SetWindowLong(glb.hWndActive, GWL_WNDPROC, (LONG)dglWndProc);
+        }
+    }
+
+	ddlogPrintf(DDLOG_SYSTEM, "dglCreateContext succeeded for HGLRC=%d", (int)hGLRC);
+
+	return hGLRC;
+}
+
+// ***********************************************************************
+// Make a DirectGL context current
+// Used by wgl functions and dgl functions
+BOOL dglMakeCurrent(
+	HDC a,
+	HGLRC b)
+{
+	int context;
+	DGL_ctx* lpCtx;
+	HWND hWnd;
+	BOOL bNeedResize = FALSE;
+	BOOL bWindowChanged, bContextChanged;
+	LPDIRECTDRAWCLIPPER	lpddClipper;
+	DWORD dwThreadId = GetCurrentThreadId();
+	LONG lpfnWndProc;
+
+	// Validate license
+	if (!dglValidate())
+		return FALSE;
+
+	// Is context state ready ?
+	if (!bContextReady)
+		return FALSE;
+
+	context = (int)b; // This is as a result of STRICT!
+	ddlogPrintf(DDLOG_SYSTEM, "dglMakeCurrent: HDC=%X, HGLRC=%d, ThreadId=%X", a, context, dwThreadId);
+
+	// If the HGLRC is NULL then make no context current;
+	// Ditto if the HDC is NULL either. (DaveM)
+	if (context == 0 || a == 0) {
+		// Corresponding Mesa operation
+#ifdef _USE_GLD3_WGL
+		_mesa_make_current(NULL, NULL);
+#else
+		(*mesaFuncs.gl_make_current)(NULL, NULL);
+#endif
+		dglSetCurrentContext(0);
+		return TRUE;
+	}
+
+	// Make sure the HGLRC is in range
+	if ((context > DGL_MAX_CONTEXTS) || (context < 0)) {
+		ddlogMessage(DDLOG_ERROR, "dglMakeCurrent: HGLRC out of range\n");
+		return FALSE;
+	}
+
+	// Find address of context and make sure that it has been allocated
+	lpCtx = dglGetContextAddress(b);
+	if (!lpCtx->bAllocated) {
+		ddlogMessage(DDLOG_ERROR, "dglMakeCurrent: Context not allocated\n");
+//		return FALSE;
+		return TRUE; // HACK: Shuts up "WebLab Viewer Pro". KeithH
+	}
+
+#ifdef GLD_THREADS
+	// Serialize access to DirectDraw or DDS operations
+	if (glb.bMultiThreaded)
+		EnterCriticalSection(&CriticalSection);
+#endif
+
+	// Check if window has changed
+	hWnd = (a != lpCtx->hDC) ? WindowFromDC(a) : lpCtx->hWnd;
+	bWindowChanged = (hWnd != lpCtx->hWnd) ? TRUE : FALSE;
+	bContextChanged = (b != dglGetCurrentContext()) ? TRUE : FALSE;
+
+	// If the window has changed, make sure the clipper is updated. (DaveM)
+	if (glb.bDirectDrawPersistant && !lpCtx->bFullscreen && (bWindowChanged || bContextChanged)) {
+		lpCtx->hWnd = hWnd;
+#ifndef _USE_GLD3_WGL
+		IDirectDrawSurface4_GetClipper(lpCtx->lpFront4, &lpddClipper);
+		IDirectDrawClipper_SetHWnd(lpddClipper, 0, lpCtx->hWnd);
+		IDirectDrawClipper_Release(lpddClipper);
+#endif // _USE_GLD3_WGL
+	}
+
+	// Make sure hDC and hWnd is current. (DaveM)
+	// Obtain the dimensions of the rendering window
+	lpCtx->hDC = a; // Cache DC
+	lpCtx->hWnd = hWnd;
+	hWndLastActive = hWnd;
+
+	// Check for non-window DC = memory DC ?
+	if (hWnd == NULL) {
+		if (GetClipBox(a, &lpCtx->rcScreenRect) == ERROR) {
+			ddlogMessage(DDLOG_WARN, "GetClipBox failed in dglMakeCurrent\n");
+			SetRect(&lpCtx->rcScreenRect, 0, 0, 0, 0);
+		}
+	}
+	else if (!GetClientRect(lpCtx->hWnd, &lpCtx->rcScreenRect)) {
+		ddlogMessage(DDLOG_WARN, "GetClientRect failed in dglMakeCurrent\n");
+		SetRect(&lpCtx->rcScreenRect, 0, 0, 0, 0);
+	}
+	// Check if buffers need to be re-sized;
+	// If so, wait until Mesa GL stuff is setup before re-sizing;
+	if (lpCtx->dwWidth != lpCtx->rcScreenRect.right - lpCtx->rcScreenRect.left ||
+		lpCtx->dwHeight != lpCtx->rcScreenRect.bottom - lpCtx->rcScreenRect.top)
+		bNeedResize = TRUE;
+
+	// Now we can update our globals
+	dglSetCurrentContext(b);
+
+	// Corresponding Mesa operation
+#ifdef _USE_GLD3_WGL
+	_mesa_make_current(lpCtx->glCtx, lpCtx->glBuffer);
+	lpCtx->glCtx->Driver.UpdateState(lpCtx->glCtx, _NEW_ALL);
+	if (bNeedResize) {
+		// Resize buffers (Note Mesa GL needs to be setup beforehand);
+		// Resize Mesa internal buffer too via glViewport() command,
+		// which subsequently calls dglWglResizeBuffers() too.
+		lpCtx->glCtx->Driver.Viewport(lpCtx->glCtx, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
+		lpCtx->bHasBeenCurrent = TRUE;
+	}
+#else
+	(*mesaFuncs.gl_make_current)(lpCtx->glCtx, lpCtx->glBuffer);
+
+	dglSetupDDPointers(lpCtx->glCtx);
+
+	// Insure DirectDraw surfaces fit current window DC
+	if (bNeedResize) {
+		// Resize buffers (Note Mesa GL needs to be setup beforehand);
+		// Resize Mesa internal buffer too via glViewport() command,
+		// which subsequently calls dglWglResizeBuffers() too.
+		(*mesaFuncs.gl_Viewport)(lpCtx->glCtx, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
+		lpCtx->bHasBeenCurrent = TRUE;
+	}
+#endif // _USE_GLD3_WGL
+	ddlogPrintf(DDLOG_SYSTEM, "dglMakeCurrent: width = %d, height = %d", lpCtx->dwWidth, lpCtx->dwHeight);
+
+	// We have to clear D3D back buffer and render state if emulated front buffering
+	// for different window (but not context) like in Solid Edge.
+	if (glb.bDirectDrawPersistant && glb.bPersistantBuffers
+		&& (bWindowChanged /* || bContextChanged */) && lpCtx->EmulateSingle) {
+#ifdef _USE_GLD3_WGL
+//		IDirect3DDevice8_EndScene(lpCtx->pDev);
+//		lpCtx->bSceneStarted = FALSE;
+		lpCtx->glCtx->Driver.Clear(lpCtx->glCtx, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
+			GL_TRUE, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
+#else
+		IDirect3DDevice3_EndScene(lpCtx->lpDev3);
+		lpCtx->bSceneStarted = FALSE;
+		dglClearD3D(lpCtx->glCtx, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
+			GL_TRUE, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
+#endif // _USE_GLD3_WGL
+	}
+
+	// The first time we call MakeCurrent we set the initial viewport size
+	if (lpCtx->bHasBeenCurrent == FALSE)
+#ifdef _USE_GLD3_WGL
+		lpCtx->glCtx->Driver.Viewport(lpCtx->glCtx, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
+#else
+		(*mesaFuncs.gl_Viewport)(lpCtx->glCtx, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
+#endif // _USE_GLD3_WGL
+	lpCtx->bHasBeenCurrent = TRUE;
+
+#ifdef GLD_THREADS
+	// Release serialized access
+	if (glb.bMultiThreaded)
+		LeaveCriticalSection(&CriticalSection);
+#endif
+
+	return TRUE;
+}
+
+// ***********************************************************************
+
+BOOL dglDeleteContext(
+	HGLRC a)
+{
+	DGL_ctx* lpCtx;
+	DWORD dwThreadId = GetCurrentThreadId();
+    char argstr[256];
+
+#if 0	// We have enough trouble throwing exceptions as it is... (DaveM)
+	// Validate license
+	if (!dglValidate())
+		return FALSE;
+#endif
+
+	// Is context state ready ?
+	if (!bContextReady)
+		return FALSE;
+
+	ddlogPrintf(DDLOG_SYSTEM, "dglDeleteContext: Deleting context HGLRC=%d, ThreadId=%X", (int)a, dwThreadId);
+
+	// Make sure the HGLRC is in range
+	if (((int) a> DGL_MAX_CONTEXTS) || ((int)a < 0)) {
+		ddlogMessage(DDLOG_ERROR, "dglDeleteCurrent: HGLRC out of range\n");
+		return FALSE;
+	}
+
+	// Make sure context is valid
+	lpCtx = dglGetContextAddress(a);
+	if (!lpCtx->bAllocated) {
+		ddlogPrintf(DDLOG_WARN, "Tried to delete unallocated context HGLRC=%d", (int)a);
+//		return FALSE;
+		return TRUE; // HACK: Shuts up "WebLab Viewer Pro". KeithH
+	}
+
+	// Make sure context is de-activated
+	if (a == dglGetCurrentContext()) {
+		ddlogPrintf(DDLOG_WARN, "dglDeleteContext: context HGLRC=%d still active", (int)a);
+		dglMakeCurrent(NULL, NULL);
+	}
+
+#ifdef GLD_THREADS
+	// Serialize access to DirectDraw or DDS operations
+	if (glb.bMultiThreaded)
+		EnterCriticalSection(&CriticalSection);
+#endif
+
+	// We are about to destroy all Direct3D objects.
+	// Therefore we must disable rendering
+	lpCtx->bCanRender = FALSE;
+
+	// This exception handler was installed to catch some
+	// particularly nasty apps. Console apps that call exit()
+	// fall into this catagory (i.e. Win32 Glut).
+
+    // VC cannot successfully implement multiple exception handlers
+    // if more than one exception occurs. Therefore reverting back to
+    // single exception handler as Keith originally had it. (DaveM)
+
+#define WARN_MESSAGE(p) strcpy(argstr, (#p));
+#define SAFE_RELEASE(p) WARN_MESSAGE(p); RELEASE(p);
+
+__try {
+#ifdef _USE_GLD3_WGL
+    WARN_MESSAGE(gl_destroy_framebuffer);
+	if (lpCtx->glBuffer)
+		_mesa_destroy_framebuffer(lpCtx->glBuffer);
+    WARN_MESSAGE(gl_destroy_context);
+	if (lpCtx->glCtx)
+		_mesa_destroy_context(lpCtx->glCtx);
+    WARN_MESSAGE(gl_destroy_visual);
+	if (lpCtx->glVis)
+		_mesa_destroy_visual(lpCtx->glVis);
+
+	_gldDriver.DestroyDrawable(lpCtx);
+#else
+	// Destroy the Mesa context
+    WARN_MESSAGE(gl_destroy_framebuffer);
+	if (lpCtx->glBuffer)
+		(*mesaFuncs.gl_destroy_framebuffer)(lpCtx->glBuffer);
+    WARN_MESSAGE(gl_destroy_context);
+	if (lpCtx->glCtx)
+		(*mesaFuncs.gl_destroy_context)(lpCtx->glCtx);
+    WARN_MESSAGE(gl_destroy_visual);
+	if (lpCtx->glVis)
+		(*mesaFuncs.gl_destroy_visual)(lpCtx->glVis);
+
+	SAFE_RELEASE(lpCtx->m_pvbuf); // release D3D vertex buffer
+	SAFE_RELEASE(lpCtx->m_vbuf); // release D3D vertex buffer
+
+	// Delete the global palette
+	SAFE_RELEASE(lpCtx->lpGlobalPalette);
+
+	// Clean up.
+	if (lpCtx->lpViewport3) {
+		if (lpCtx->lpDev3) IDirect3DDevice3_DeleteViewport(lpCtx->lpDev3, lpCtx->lpViewport3);
+		SAFE_RELEASE(lpCtx->lpViewport3);
+		lpCtx->lpViewport3 = NULL;
+	}
+
+	SAFE_RELEASE(lpCtx->lpDev3);
+	if (lpCtx->lpDepth4) {
+		if (lpCtx->lpBack4)
+			IDirectDrawSurface4_DeleteAttachedSurface(lpCtx->lpBack4, 0L, lpCtx->lpDepth4);
+		else
+			IDirectDrawSurface4_DeleteAttachedSurface(lpCtx->lpFront4, 0L, lpCtx->lpDepth4);
+		SAFE_RELEASE(lpCtx->lpDepth4);
+		lpCtx->lpDepth4 = NULL;
+	}
+	SAFE_RELEASE(lpCtx->lpBack4);
+	SAFE_RELEASE(lpCtx->lpFront4);
+	if (lpCtx->bFullscreen) {
+		IDirectDraw4_RestoreDisplayMode(lpCtx->lpDD4);
+		IDirectDraw4_SetCooperativeLevel(lpCtx->lpDD4, NULL, DDSCL_NORMAL);
+	}
+	SAFE_RELEASE(lpCtx->lpD3D3);
+	SAFE_RELEASE(lpCtx->lpDD4);
+	SAFE_RELEASE(lpCtx->lpDD1);
+#endif // _ULSE_GLD3_WGL
+
+}
+__except(EXCEPTION_EXECUTE_HANDLER) {
+    ddlogPrintf(DDLOG_WARN, "Exception raised in dglDeleteContext: %s", argstr);
+}
+
+	// Restore the window message handler because this context may be used
+	// again by another window with a *different* message handler. (DaveM)
+	if (lpCtx->lpfnWndProc) {
+		SetWindowLong(lpCtx->hWnd, GWL_WNDPROC, (LONG)lpCtx->lpfnWndProc);
+		lpCtx->lpfnWndProc = (LONG)NULL;
+		}
+
+	lpCtx->bAllocated = FALSE; // This context is now free for use
+
+#ifdef GLD_THREADS
+	// Release serialized access
+	if (glb.bMultiThreaded)
+		LeaveCriticalSection(&CriticalSection);
+#endif
+
+	return TRUE;
+}
+
+// ***********************************************************************
+
+BOOL dglSwapBuffers(
+	HDC hDC)
+{
+	RECT		rSrcRect;	// Source rectangle
+	RECT		rDstRect;	// Destination rectangle
+	POINT		pt;
+	HRESULT		hResult;
+
+	DDBLTFX		bltFX;
+	DWORD		dwBlitFlags;
+	DDBLTFX		*lpBltFX;
+
+//	DWORD		dwThreadId = GetCurrentThreadId();
+	HGLRC		hGLRC = dglGetCurrentContext();
+	DGL_ctx		*lpCtx = dglGetContextAddress(hGLRC);
+	HWND		hWnd;
+
+	HDC 		hDCAux;		// for memory DC
+	int 		x,y,w,h;	// for memory DC BitBlt
+
+#if 0	// Perhaps not a good idea. Called too often. KH
+	// Validate license
+	if (!dglValidate())
+		return FALSE;
+#endif
+
+	if (!lpCtx) {
+		return TRUE; //FALSE; // No current context
+	}
+
+	if (!lpCtx->bCanRender) {
+		// Don't return false else some apps will bail.
+		return TRUE;
+	}
+
+	hWnd = lpCtx->hWnd;
+	if (hDC != lpCtx->hDC) {
+		ddlogPrintf(DDLOG_WARN, "dglSwapBuffers: HDC=%X does not match HDC=%X for HGLRC=%d", hDC, lpCtx->hDC, hGLRC);
+		hWnd = WindowFromDC(hDC);
+	}
+
+#ifndef _USE_GLD3_WGL
+	// Ensure that the surfaces exist before we tell
+	// the device to render to them.
+	IDirectDraw4_RestoreAllSurfaces(lpCtx->lpDD4);
+
+	// Make sure that the vertex caches have been emptied
+//	dglStateChange(lpCtx);
+
+	// Some OpenGL programs don't issue a glFinish - check for it here.
+	if (lpCtx->bSceneStarted) {
+		IDirect3DDevice3_EndScene(lpCtx->lpDev3);
+		lpCtx->bSceneStarted = FALSE;
+	}
+#endif
+
+#if 0
+	// If the calling app is not active then we don't need to Blit/Flip.
+	// We can therefore simply return TRUE.
+	if (!glb.bAppActive)
+		return TRUE;
+	// Addendum: This is WRONG! We should bail if the app is *minimized*,
+	//           not merely if the app is just plain 'not active'.
+	//           KeithH, 27/May/2000.
+#endif
+
+	// Check for non-window DC = memory DC ?
+	if (hWnd == NULL) {
+		if (GetClipBox(hDC, &rSrcRect) == ERROR)
+			return TRUE;
+		// Use GDI BitBlt instead from compatible DirectDraw DC
+		x = rSrcRect.left;
+		y = rSrcRect.top;
+		w = rSrcRect.right - rSrcRect.left;
+		h = rSrcRect.bottom - rSrcRect.top;
+
+		// Ack. DX8 does not have a GetDC() function...
+                // TODO: Defer to DX7 or DX9 drivers... (DaveM)
+		return TRUE;
+	}
+
+	// Bail if window client region is not drawable, like in Solid Edge
+	if (!IsWindow(hWnd) /* || !IsWindowVisible(hWnd) */ || !GetClientRect(hWnd, &rSrcRect))
+		return TRUE;
+
+#ifdef GLD_THREADS
+	// Serialize access to DirectDraw or DDS operations
+	if (glb.bMultiThreaded)
+		EnterCriticalSection(&CriticalSection);
+#endif
+
+#ifdef _USE_GLD3_WGL
+	// Notify Mesa of impending swap, so Mesa can flush internal buffers.
+	_mesa_notifySwapBuffers(lpCtx->glCtx);
+	// Now perform driver buffer swap
+	_gldDriver.SwapBuffers(lpCtx, hDC, hWnd);
+#else
+	if (lpCtx->bFullscreen) {
+		// Sync with retrace if required
+		if (glb.bWaitForRetrace) {
+			IDirectDraw4_WaitForVerticalBlank(
+				lpCtx->lpDD4,
+				DDWAITVB_BLOCKBEGIN,
+				0);
+		}
+
+		// Perform the fullscreen flip
+		TRY(IDirectDrawSurface4_Flip(
+			lpCtx->lpFront4,
+			NULL,
+			DDFLIP_WAIT),
+			"dglSwapBuffers: Flip");
+	} else {
+		// Calculate current window position and size
+		pt.x = pt.y = 0;
+		ClientToScreen(hWnd, &pt);
+		GetClientRect(hWnd, &rDstRect);
+		if (rDstRect.right > lpCtx->dwModeWidth)
+			rDstRect.right = lpCtx->dwModeWidth;
+		if (rDstRect.bottom > lpCtx->dwModeHeight)
+			rDstRect.bottom = lpCtx->dwModeHeight;
+		OffsetRect(&rDstRect, pt.x, pt.y);
+		rSrcRect.left = rSrcRect.top = 0;
+		rSrcRect.right = lpCtx->dwWidth;
+		rSrcRect.bottom = lpCtx->dwHeight;
+		if (rSrcRect.right > lpCtx->dwModeWidth)
+			rSrcRect.right = lpCtx->dwModeWidth;
+		if (rSrcRect.bottom > lpCtx->dwModeHeight)
+			rSrcRect.bottom = lpCtx->dwModeHeight;
+
+		if (glb.bWaitForRetrace) {
+			// Sync the blit to the vertical retrace
+			ZeroMemory(&bltFX, sizeof(bltFX));
+			bltFX.dwSize = sizeof(bltFX);
+			bltFX.dwDDFX = DDBLTFX_NOTEARING;
+			dwBlitFlags = DDBLT_WAIT | DDBLT_DDFX;
+			lpBltFX = &bltFX;
+		} else {
+			dwBlitFlags = DDBLT_WAIT;
+			lpBltFX = NULL;
+		}
+
+		// Perform the actual blit
+		TRY(IDirectDrawSurface4_Blt(
+			lpCtx->lpFront4,
+			&rDstRect,
+			lpCtx->lpBack4, // Blit source
+			&rSrcRect,
+			dwBlitFlags,
+			lpBltFX),
+			"dglSwapBuffers: Blt");
+	}
+#endif // _USE_GLD3_WGL
+
+#ifdef GLD_THREADS
+	// Release serialized access
+	if (glb.bMultiThreaded)
+		LeaveCriticalSection(&CriticalSection);
+#endif
+
+    // TODO: Re-instate rendering bitmap snapshot feature??? (DaveM)
+
+	// Render frame is completed
+	ValidateRect(hWnd, NULL);
+	lpCtx->bFrameStarted = FALSE;
+
+	return TRUE;
+}
+
+// ***********************************************************************
diff --git a/mesalib/src/mesa/main/blend.c b/mesalib/src/mesa/main/blend.c
index 30466cca3..c74a16803 100644
--- a/mesalib/src/mesa/main/blend.c
+++ b/mesalib/src/mesa/main/blend.c
@@ -1,814 +1,822 @@
-/**
- * \file blend.c
- * Blending operations.
- */
-
-/*
- * Mesa 3-D graphics library
- * Version:  6.5.1
- *
- * Copyright (C) 1999-2006  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"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-
-#include "glheader.h"
-#include "blend.h"
-#include "context.h"
-#include "enums.h"
-#include "macros.h"
-#include "mtypes.h"
-
-
-
-/**
- * Check if given blend source factor is legal.
- * \return GL_TRUE if legal, GL_FALSE otherwise.
- */
-static GLboolean
-legal_src_factor(const struct gl_context *ctx, GLenum factor)
-{
-   switch (factor) {
-   case GL_SRC_COLOR:
-   case GL_ONE_MINUS_SRC_COLOR:
-      return ctx->Extensions.NV_blend_square;
-   case GL_ZERO:
-   case GL_ONE:
-   case GL_DST_COLOR:
-   case GL_ONE_MINUS_DST_COLOR:
-   case GL_SRC_ALPHA:
-   case GL_ONE_MINUS_SRC_ALPHA:
-   case GL_DST_ALPHA:
-   case GL_ONE_MINUS_DST_ALPHA:
-   case GL_SRC_ALPHA_SATURATE:
-   case GL_CONSTANT_COLOR:
-   case GL_ONE_MINUS_CONSTANT_COLOR:
-   case GL_CONSTANT_ALPHA:
-   case GL_ONE_MINUS_CONSTANT_ALPHA:
-      return GL_TRUE;
-   default:
-      return GL_FALSE;
-   }
-}
-
-
-/**
- * Check if given blend destination factor is legal.
- * \return GL_TRUE if legal, GL_FALSE otherwise.
- */
-static GLboolean
-legal_dst_factor(const struct gl_context *ctx, GLenum factor)
-{
-   switch (factor) {
-   case GL_DST_COLOR:
-   case GL_ONE_MINUS_DST_COLOR:
-      return ctx->Extensions.NV_blend_square;
-   case GL_ZERO:
-   case GL_ONE:
-   case GL_SRC_COLOR:
-   case GL_ONE_MINUS_SRC_COLOR:
-   case GL_SRC_ALPHA:
-   case GL_ONE_MINUS_SRC_ALPHA:
-   case GL_DST_ALPHA:
-   case GL_ONE_MINUS_DST_ALPHA:
-   case GL_CONSTANT_COLOR:
-   case GL_ONE_MINUS_CONSTANT_COLOR:
-   case GL_CONSTANT_ALPHA:
-   case GL_ONE_MINUS_CONSTANT_ALPHA:
-      return GL_TRUE;
-   default:
-      return GL_FALSE;
-   }
-}
-
-
-/**
- * Check if src/dest RGB/A blend factors are legal.  If not generate
- * a GL error.
- * \return GL_TRUE if factors are legal, GL_FALSE otherwise.
- */
-static GLboolean
-validate_blend_factors(struct gl_context *ctx, const char *func,
-                       GLenum sfactorRGB, GLenum dfactorRGB,
-                       GLenum sfactorA, GLenum dfactorA)
-{
-   if (!legal_src_factor(ctx, sfactorRGB)) {
-      _mesa_error(ctx, GL_INVALID_ENUM,
-                  "%s(sfactorRGB = %s)", func,
-                  _mesa_lookup_enum_by_nr(sfactorRGB));
-      return GL_FALSE;
-   }
-
-   if (!legal_dst_factor(ctx, dfactorRGB)) {
-      _mesa_error(ctx, GL_INVALID_ENUM,
-                  "%s(dfactorRGB = %s)", func,
-                  _mesa_lookup_enum_by_nr(dfactorRGB));
-      return GL_FALSE;
-   }
-
-   if (sfactorA != sfactorRGB && !legal_src_factor(ctx, sfactorA)) {
-      _mesa_error(ctx, GL_INVALID_ENUM,
-                  "%s(sfactorA = %s)", func,
-                  _mesa_lookup_enum_by_nr(sfactorA));
-      return GL_FALSE;
-   }
-
-   if (dfactorA != dfactorRGB && !legal_dst_factor(ctx, dfactorA)) {
-      _mesa_error(ctx, GL_INVALID_ENUM,
-                  "%s(dfactorA = %s)", func,
-                  _mesa_lookup_enum_by_nr(dfactorA));
-      return GL_FALSE;
-   }
-
-   return GL_TRUE;
-}
-
-
-/**
- * Specify the blending operation.
- *
- * \param sfactor source factor operator.
- * \param dfactor destination factor operator.
- *
- * \sa glBlendFunc, glBlendFuncSeparateEXT
- */
-void GLAPIENTRY
-_mesa_BlendFunc( GLenum sfactor, GLenum dfactor )
-{
-   _mesa_BlendFuncSeparateEXT(sfactor, dfactor, sfactor, dfactor);
-}
-
-
-/**
- * Set the separate blend source/dest factors for all draw buffers.
- *
- * \param sfactorRGB RGB source factor operator.
- * \param dfactorRGB RGB destination factor operator.
- * \param sfactorA alpha source factor operator.
- * \param dfactorA alpha destination factor operator.
- */
-void GLAPIENTRY
-_mesa_BlendFuncSeparateEXT( GLenum sfactorRGB, GLenum dfactorRGB,
-                            GLenum sfactorA, GLenum dfactorA )
-{
-   GLuint buf, numBuffers;
-   GLboolean changed;
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   if (MESA_VERBOSE & VERBOSE_API)
-      _mesa_debug(ctx, "glBlendFuncSeparate %s %s %s %s\n",
-                  _mesa_lookup_enum_by_nr(sfactorRGB),
-                  _mesa_lookup_enum_by_nr(dfactorRGB),
-                  _mesa_lookup_enum_by_nr(sfactorA),
-                  _mesa_lookup_enum_by_nr(dfactorA));
-
-   if (!validate_blend_factors(ctx, "glBlendFuncSeparate",
-                               sfactorRGB, dfactorRGB,
-                               sfactorA, dfactorA)) {
-      return;
-   }
-
-   numBuffers = ctx->Extensions.ARB_draw_buffers_blend
-      ? ctx->Const.MaxDrawBuffers : 1;
-
-   changed = GL_FALSE;
-   for (buf = 0; buf < numBuffers; buf++) {
-      if (ctx->Color.Blend[buf].SrcRGB != sfactorRGB ||
-          ctx->Color.Blend[buf].DstRGB != dfactorRGB ||
-          ctx->Color.Blend[buf].SrcA != sfactorA ||
-          ctx->Color.Blend[buf].DstA != dfactorA) {
-         changed = GL_TRUE;
-         break;
-      }
-   }
-   if (!changed)
-      return;
-
-   FLUSH_VERTICES(ctx, _NEW_COLOR);
-
-   for (buf = 0; buf < numBuffers; buf++) {
-      ctx->Color.Blend[buf].SrcRGB = sfactorRGB;
-      ctx->Color.Blend[buf].DstRGB = dfactorRGB;
-      ctx->Color.Blend[buf].SrcA = sfactorA;
-      ctx->Color.Blend[buf].DstA = dfactorA;
-   }
-   ctx->Color._BlendFuncPerBuffer = GL_FALSE;
-
-   if (ctx->Driver.BlendFuncSeparate) {
-      ctx->Driver.BlendFuncSeparate(ctx, sfactorRGB, dfactorRGB,
-                                    sfactorA, dfactorA);
-   }
-}
-
-
-#if _HAVE_FULL_GL
-
-
-/**
- * Set blend source/dest factors for one color buffer/target.
- */
-void GLAPIENTRY
-_mesa_BlendFunci(GLuint buf, GLenum sfactor, GLenum dfactor)
-{
-   _mesa_BlendFuncSeparatei(buf, sfactor, dfactor, sfactor, dfactor);
-}
-
-
-/**
- * Set separate blend source/dest factors for one color buffer/target.
- */
-void GLAPIENTRY
-_mesa_BlendFuncSeparatei(GLuint buf, GLenum sfactorRGB, GLenum dfactorRGB,
-                         GLenum sfactorA, GLenum dfactorA)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   if (!ctx->Extensions.ARB_draw_buffers_blend) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "glBlendFunc[Separate]i()");
-      return;
-   }
-
-   if (buf >= ctx->Const.MaxDrawBuffers) {
-      _mesa_error(ctx, GL_INVALID_VALUE, "glBlendFuncSeparatei(buffer=%u)",
-                  buf);
-      return;
-   }
-
-   if (!validate_blend_factors(ctx, "glBlendFuncSeparatei",
-                               sfactorRGB, dfactorRGB,
-                               sfactorA, dfactorA)) {
-      return;
-   }
-
-   if (ctx->Color.Blend[buf].SrcRGB == sfactorRGB &&
-       ctx->Color.Blend[buf].DstRGB == dfactorRGB &&
-       ctx->Color.Blend[buf].SrcA == sfactorA &&
-       ctx->Color.Blend[buf].DstA == dfactorA)
-      return; /* no change */
-
-   FLUSH_VERTICES(ctx, _NEW_COLOR);
-
-   ctx->Color.Blend[buf].SrcRGB = sfactorRGB;
-   ctx->Color.Blend[buf].DstRGB = dfactorRGB;
-   ctx->Color.Blend[buf].SrcA = sfactorA;
-   ctx->Color.Blend[buf].DstA = dfactorA;
-   ctx->Color._BlendFuncPerBuffer = GL_TRUE;
-
-   if (ctx->Driver.BlendFuncSeparatei) {
-      ctx->Driver.BlendFuncSeparatei(ctx, buf, sfactorRGB, dfactorRGB,
-                                     sfactorA, dfactorA);
-   }
-}
-
-
-/**
- * Check if given blend equation is legal.
- * \return GL_TRUE if legal, GL_FALSE otherwise.
- */
-static GLboolean
-legal_blend_equation(const struct gl_context *ctx,
-                     GLenum mode, GLboolean is_separate)
-{
-   switch (mode) {
-   case GL_FUNC_ADD:
-      return GL_TRUE;
-   case GL_MIN:
-   case GL_MAX:
-      return ctx->Extensions.EXT_blend_minmax;
-   case GL_LOGIC_OP:
-      /* glBlendEquationSeparate cannot take GL_LOGIC_OP as a parameter.
-       */
-      return ctx->Extensions.EXT_blend_logic_op && !is_separate;
-   case GL_FUNC_SUBTRACT:
-   case GL_FUNC_REVERSE_SUBTRACT:
-      return ctx->Extensions.EXT_blend_subtract;
-   default:
-      return GL_FALSE;
-   }
-}
-
-
-/* This is really an extension function! */
-void GLAPIENTRY
-_mesa_BlendEquation( GLenum mode )
-{
-   GLuint buf, numBuffers;
-   GLboolean changed;
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   if (MESA_VERBOSE & VERBOSE_API)
-      _mesa_debug(ctx, "glBlendEquation %s\n",
-                  _mesa_lookup_enum_by_nr(mode));
-
-   if (!legal_blend_equation(ctx, mode, GL_FALSE)) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquation");
-      return;
-   }
-
-   numBuffers = ctx->Extensions.ARB_draw_buffers_blend
-      ? ctx->Const.MaxDrawBuffers : 1;
-
-   changed = GL_FALSE;
-   for (buf = 0; buf < numBuffers; buf++) {
-      if (ctx->Color.Blend[buf].EquationRGB != mode ||
-          ctx->Color.Blend[buf].EquationA != mode) {
-         changed = GL_TRUE;
-         break;
-      }
-   }
-   if (!changed)
-      return;
-
-   FLUSH_VERTICES(ctx, _NEW_COLOR);
-   for (buf = 0; buf < numBuffers; buf++) {
-      ctx->Color.Blend[buf].EquationRGB = mode;
-      ctx->Color.Blend[buf].EquationA = mode;
-   }
-   ctx->Color._BlendEquationPerBuffer = GL_FALSE;
-
-   if (ctx->Driver.BlendEquationSeparate)
-      (*ctx->Driver.BlendEquationSeparate)( ctx, mode, mode );
-}
-
-
-/**
- * Set blend equation for one color buffer/target.
- */
-void GLAPIENTRY
-_mesa_BlendEquationi(GLuint buf, GLenum mode)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   if (MESA_VERBOSE & VERBOSE_API)
-      _mesa_debug(ctx, "glBlendEquationi(%u, %s)\n",
-                  buf, _mesa_lookup_enum_by_nr(mode));
-
-   if (buf >= ctx->Const.MaxDrawBuffers) {
-      _mesa_error(ctx, GL_INVALID_VALUE, "glBlendFuncSeparatei(buffer=%u)",
-                  buf);
-      return;
-   }
-
-   if (!legal_blend_equation(ctx, mode, GL_FALSE)) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationi");
-      return;
-   }
-
-   if (ctx->Color.Blend[buf].EquationRGB == mode &&
-       ctx->Color.Blend[buf].EquationA == mode)
-      return;  /* no change */
-
-   FLUSH_VERTICES(ctx, _NEW_COLOR);
-   ctx->Color.Blend[buf].EquationRGB = mode;
-   ctx->Color.Blend[buf].EquationA = mode;
-   ctx->Color._BlendEquationPerBuffer = GL_TRUE;
-
-   if (ctx->Driver.BlendEquationSeparatei)
-      ctx->Driver.BlendEquationSeparatei(ctx, buf, mode, mode);
-}
-
-
-void GLAPIENTRY
-_mesa_BlendEquationSeparateEXT( GLenum modeRGB, GLenum modeA )
-{
-   GLuint buf, numBuffers;
-   GLboolean changed;
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   if (MESA_VERBOSE & VERBOSE_API)
-      _mesa_debug(ctx, "glBlendEquationSeparateEXT %s %s\n",
-                  _mesa_lookup_enum_by_nr(modeRGB),
-                  _mesa_lookup_enum_by_nr(modeA));
-
-   if ( (modeRGB != modeA) && !ctx->Extensions.EXT_blend_equation_separate ) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-		  "glBlendEquationSeparateEXT not supported by driver");
-      return;
-   }
-
-   if (!legal_blend_equation(ctx, modeRGB, GL_TRUE)) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparateEXT(modeRGB)");
-      return;
-   }
-
-   if (!legal_blend_equation(ctx, modeA, GL_TRUE)) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparateEXT(modeA)");
-      return;
-   }
-
-   numBuffers = ctx->Extensions.ARB_draw_buffers_blend
-      ? ctx->Const.MaxDrawBuffers : 1;
-
-   changed = GL_FALSE;
-   for (buf = 0; buf < numBuffers; buf++) {
-      if (ctx->Color.Blend[buf].EquationRGB != modeRGB ||
-          ctx->Color.Blend[buf].EquationA != modeA) {
-         changed = GL_TRUE;
-         break;
-      }
-   }
-   if (!changed)
-      return;
-
-   FLUSH_VERTICES(ctx, _NEW_COLOR);
-   for (buf = 0; buf < numBuffers; buf++) {
-      ctx->Color.Blend[buf].EquationRGB = modeRGB;
-      ctx->Color.Blend[buf].EquationA = modeA;
-   }
-   ctx->Color._BlendEquationPerBuffer = GL_FALSE;
-
-   if (ctx->Driver.BlendEquationSeparate)
-      ctx->Driver.BlendEquationSeparate(ctx, modeRGB, modeA);
-}
-
-
-/**
- * Set separate blend equations for one color buffer/target.
- */
-void
-_mesa_BlendEquationSeparatei(GLuint buf, GLenum modeRGB, GLenum modeA)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   if (MESA_VERBOSE & VERBOSE_API)
-      _mesa_debug(ctx, "glBlendEquationSeparatei %u, %s %s\n", buf,
-                  _mesa_lookup_enum_by_nr(modeRGB),
-                  _mesa_lookup_enum_by_nr(modeA));
-
-   if (buf >= ctx->Const.MaxDrawBuffers) {
-      _mesa_error(ctx, GL_INVALID_VALUE, "glBlendEquationSeparatei(buffer=%u)",
-                  buf);
-      return;
-   }
-
-   if (!legal_blend_equation(ctx, modeRGB, GL_TRUE)) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparatei(modeRGB)");
-      return;
-   }
-
-   if (!legal_blend_equation(ctx, modeA, GL_TRUE)) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparatei(modeA)");
-      return;
-   }
-
-   if (ctx->Color.Blend[buf].EquationRGB == modeRGB &&
-       ctx->Color.Blend[buf].EquationA == modeA)
-      return;  /* no change */
-
-   FLUSH_VERTICES(ctx, _NEW_COLOR);
-   ctx->Color.Blend[buf].EquationRGB = modeRGB;
-   ctx->Color.Blend[buf].EquationA = modeA;
-   ctx->Color._BlendEquationPerBuffer = GL_TRUE;
-
-   if (ctx->Driver.BlendEquationSeparatei)
-      ctx->Driver.BlendEquationSeparatei(ctx, buf, modeRGB, modeA);
-}
-
-
-
-#endif /* _HAVE_FULL_GL */
-
-
-/**
- * Set the blending color.
- *
- * \param red red color component.
- * \param green green color component.
- * \param blue blue color component.
- * \param alpha alpha color component.
- *
- * \sa glBlendColor().
- *
- * Clamps the parameters and updates gl_colorbuffer_attrib::BlendColor.  On a
- * change, flushes the vertices and notifies the driver via
- * dd_function_table::BlendColor callback.
- */
-void GLAPIENTRY
-_mesa_BlendColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
-{
-   GLfloat tmp[4];
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   tmp[0] = CLAMP( red,   0.0F, 1.0F );
-   tmp[1] = CLAMP( green, 0.0F, 1.0F );
-   tmp[2] = CLAMP( blue,  0.0F, 1.0F );
-   tmp[3] = CLAMP( alpha, 0.0F, 1.0F );
-
-   if (TEST_EQ_4V(tmp, ctx->Color.BlendColor))
-      return;
-
-   FLUSH_VERTICES(ctx, _NEW_COLOR);
-   COPY_4FV( ctx->Color.BlendColor, tmp );
-
-   if (ctx->Driver.BlendColor)
-      (*ctx->Driver.BlendColor)(ctx, tmp);
-}
-
-
-/**
- * Specify the alpha test function.
- *
- * \param func alpha comparison function.
- * \param ref reference value.
- *
- * Verifies the parameters and updates gl_colorbuffer_attrib. 
- * On a change, flushes the vertices and notifies the driver via
- * dd_function_table::AlphaFunc callback.
- */
-void GLAPIENTRY
-_mesa_AlphaFunc( GLenum func, GLclampf ref )
-{
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   switch (func) {
-   case GL_NEVER:
-   case GL_LESS:
-   case GL_EQUAL:
-   case GL_LEQUAL:
-   case GL_GREATER:
-   case GL_NOTEQUAL:
-   case GL_GEQUAL:
-   case GL_ALWAYS:
-      ref = CLAMP(ref, 0.0F, 1.0F);
-
-      if (ctx->Color.AlphaFunc == func && ctx->Color.AlphaRef == ref)
-         return; /* no change */
-
-      FLUSH_VERTICES(ctx, _NEW_COLOR);
-      ctx->Color.AlphaFunc = func;
-      ctx->Color.AlphaRef = ref;
-
-      if (ctx->Driver.AlphaFunc)
-         ctx->Driver.AlphaFunc(ctx, func, ref);
-      return;
-
-   default:
-      _mesa_error( ctx, GL_INVALID_ENUM, "glAlphaFunc(func)" );
-      return;
-   }
-}
-
-
-/**
- * Specify a logic pixel operation for color index rendering.
- *
- * \param opcode operation.
- *
- * Verifies that \p opcode is a valid enum and updates
-gl_colorbuffer_attrib::LogicOp.
- * On a change, flushes the vertices and notifies the driver via the
- * dd_function_table::LogicOpcode callback.
- */
-void GLAPIENTRY
-_mesa_LogicOp( GLenum opcode )
-{
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   switch (opcode) {
-      case GL_CLEAR:
-      case GL_SET:
-      case GL_COPY:
-      case GL_COPY_INVERTED:
-      case GL_NOOP:
-      case GL_INVERT:
-      case GL_AND:
-      case GL_NAND:
-      case GL_OR:
-      case GL_NOR:
-      case GL_XOR:
-      case GL_EQUIV:
-      case GL_AND_REVERSE:
-      case GL_AND_INVERTED:
-      case GL_OR_REVERSE:
-      case GL_OR_INVERTED:
-	 break;
-      default:
-         _mesa_error( ctx, GL_INVALID_ENUM, "glLogicOp" );
-	 return;
-   }
-
-   if (ctx->Color.LogicOp == opcode)
-      return;
-
-   FLUSH_VERTICES(ctx, _NEW_COLOR);
-   ctx->Color.LogicOp = opcode;
-
-   if (ctx->Driver.LogicOpcode)
-      ctx->Driver.LogicOpcode( ctx, opcode );
-}
-
-#if _HAVE_FULL_GL
-void GLAPIENTRY
-_mesa_IndexMask( GLuint mask )
-{
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   if (ctx->Color.IndexMask == mask)
-      return;
-
-   FLUSH_VERTICES(ctx, _NEW_COLOR);
-   ctx->Color.IndexMask = mask;
-}
-#endif
-
-
-/**
- * Enable or disable writing of frame buffer color components.
- *
- * \param red whether to mask writing of the red color component.
- * \param green whether to mask writing of the green color component.
- * \param blue whether to mask writing of the blue color component.
- * \param alpha whether to mask writing of the alpha color component.
- *
- * \sa glColorMask().
- *
- * Sets the appropriate value of gl_colorbuffer_attrib::ColorMask.  On a
- * change, flushes the vertices and notifies the driver via the
- * dd_function_table::ColorMask callback.
- */
-void GLAPIENTRY
-_mesa_ColorMask( GLboolean red, GLboolean green,
-                 GLboolean blue, GLboolean alpha )
-{
-   GET_CURRENT_CONTEXT(ctx);
-   GLubyte tmp[4];
-   GLuint i;
-   GLboolean flushed;
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   if (MESA_VERBOSE & VERBOSE_API)
-      _mesa_debug(ctx, "glColorMask %d %d %d %d\n", red, green, blue, alpha);
-
-   /* Shouldn't have any information about channel depth in core mesa
-    * -- should probably store these as the native booleans:
-    */
-   tmp[RCOMP] = red    ? 0xff : 0x0;
-   tmp[GCOMP] = green  ? 0xff : 0x0;
-   tmp[BCOMP] = blue   ? 0xff : 0x0;
-   tmp[ACOMP] = alpha  ? 0xff : 0x0;
-
-   flushed = GL_FALSE;
-   for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
-      if (!TEST_EQ_4V(tmp, ctx->Color.ColorMask[i])) {
-         if (!flushed) {
-            FLUSH_VERTICES(ctx, _NEW_COLOR);
-         }
-         flushed = GL_TRUE;
-         COPY_4UBV(ctx->Color.ColorMask[i], tmp);
-      }
-   }
-
-   if (ctx->Driver.ColorMask)
-      ctx->Driver.ColorMask( ctx, red, green, blue, alpha );
-}
-
-
-/**
- * For GL_EXT_draw_buffers2 and GL3
- */
-void GLAPIENTRY
-_mesa_ColorMaskIndexed( GLuint buf, GLboolean red, GLboolean green,
-                        GLboolean blue, GLboolean alpha )
-{
-   GLubyte tmp[4];
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   if (MESA_VERBOSE & VERBOSE_API)
-      _mesa_debug(ctx, "glColorMaskIndexed %u %d %d %d %d\n",
-                  buf, red, green, blue, alpha);
-
-   if (buf >= ctx->Const.MaxDrawBuffers) {
-      _mesa_error(ctx, GL_INVALID_VALUE, "glColorMaskIndexed(buf=%u)", buf);
-      return;
-   }
-
-   /* Shouldn't have any information about channel depth in core mesa
-    * -- should probably store these as the native booleans:
-    */
-   tmp[RCOMP] = red    ? 0xff : 0x0;
-   tmp[GCOMP] = green  ? 0xff : 0x0;
-   tmp[BCOMP] = blue   ? 0xff : 0x0;
-   tmp[ACOMP] = alpha  ? 0xff : 0x0;
-
-   if (TEST_EQ_4V(tmp, ctx->Color.ColorMask[buf]))
-      return;
-
-   FLUSH_VERTICES(ctx, _NEW_COLOR);
-   COPY_4UBV(ctx->Color.ColorMask[buf], tmp);
-
-   if (ctx->Driver.ColorMaskIndexed)
-      ctx->Driver.ColorMaskIndexed(ctx, buf, red, green, blue, alpha);
-}
-
-
-extern void GLAPIENTRY
-_mesa_ClampColorARB(GLenum target, GLenum clamp)
-{
-   GET_CURRENT_CONTEXT(ctx);
-
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   if (clamp != GL_TRUE && clamp != GL_FALSE && clamp != GL_FIXED_ONLY_ARB) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glClampColorARB(clamp)");
-      return;
-   }
-
-   switch (target) {
-   case GL_CLAMP_VERTEX_COLOR_ARB:
-      ctx->Light.ClampVertexColor = clamp;
-      break;
-   case GL_CLAMP_FRAGMENT_COLOR_ARB:
-      ctx->Color.ClampFragmentColor = clamp;
-      break;
-   case GL_CLAMP_READ_COLOR_ARB:
-      ctx->Color.ClampReadColor = clamp;
-      break;
-   default:
-      _mesa_error(ctx, GL_INVALID_ENUM, "glClampColorARB(target)");
-      return;
-   }
-}
-
-
-
-
-/**********************************************************************/
-/** \name Initialization */
-/*@{*/
-
-/**
- * Initialization of the context's Color attribute group.
- *
- * \param ctx GL context.
- *
- * Initializes the related fields in the context color attribute group,
- * __struct gl_contextRec::Color.
- */
-void _mesa_init_color( struct gl_context * ctx )
-{
-   GLuint i;
-
-   /* Color buffer group */
-   ctx->Color.IndexMask = ~0u;
-   memset(ctx->Color.ColorMask, 0xff, sizeof(ctx->Color.ColorMask));
-   ctx->Color.ClearIndex = 0;
-   ASSIGN_4V( ctx->Color.ClearColor, 0, 0, 0, 0 );
-   ctx->Color.AlphaEnabled = GL_FALSE;
-   ctx->Color.AlphaFunc = GL_ALWAYS;
-   ctx->Color.AlphaRef = 0;
-   ctx->Color.BlendEnabled = 0x0;
-   for (i = 0; i < Elements(ctx->Color.Blend); i++) {
-      ctx->Color.Blend[i].SrcRGB = GL_ONE;
-      ctx->Color.Blend[i].DstRGB = GL_ZERO;
-      ctx->Color.Blend[i].SrcA = GL_ONE;
-      ctx->Color.Blend[i].DstA = GL_ZERO;
-      ctx->Color.Blend[i].EquationRGB = GL_FUNC_ADD;
-      ctx->Color.Blend[i].EquationA = GL_FUNC_ADD;
-   }
-   ASSIGN_4V( ctx->Color.BlendColor, 0.0, 0.0, 0.0, 0.0 );
-   ctx->Color.IndexLogicOpEnabled = GL_FALSE;
-   ctx->Color.ColorLogicOpEnabled = GL_FALSE;
-   ctx->Color._LogicOpEnabled = GL_FALSE;
-   ctx->Color.LogicOp = GL_COPY;
-   ctx->Color.DitherFlag = GL_TRUE;
-
-   if (ctx->Visual.doubleBufferMode) {
-      ctx->Color.DrawBuffer[0] = GL_BACK;
-   }
-   else {
-      ctx->Color.DrawBuffer[0] = GL_FRONT;
-   }
-
-   ctx->Color.ClampFragmentColor = GL_FIXED_ONLY_ARB;
-   ctx->Color.ClampReadColor = GL_FIXED_ONLY_ARB;
-}
-
-/*@}*/
+/**
+ * \file blend.c
+ * Blending operations.
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5.1
+ *
+ * Copyright (C) 1999-2006  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"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+
+#include "glheader.h"
+#include "blend.h"
+#include "context.h"
+#include "enums.h"
+#include "macros.h"
+#include "mtypes.h"
+
+
+
+/**
+ * Check if given blend source factor is legal.
+ * \return GL_TRUE if legal, GL_FALSE otherwise.
+ */
+static GLboolean
+legal_src_factor(const struct gl_context *ctx, GLenum factor)
+{
+   switch (factor) {
+   case GL_SRC_COLOR:
+   case GL_ONE_MINUS_SRC_COLOR:
+      return ctx->Extensions.NV_blend_square;
+   case GL_ZERO:
+   case GL_ONE:
+   case GL_DST_COLOR:
+   case GL_ONE_MINUS_DST_COLOR:
+   case GL_SRC_ALPHA:
+   case GL_ONE_MINUS_SRC_ALPHA:
+   case GL_DST_ALPHA:
+   case GL_ONE_MINUS_DST_ALPHA:
+   case GL_SRC_ALPHA_SATURATE:
+   case GL_CONSTANT_COLOR:
+   case GL_ONE_MINUS_CONSTANT_COLOR:
+   case GL_CONSTANT_ALPHA:
+   case GL_ONE_MINUS_CONSTANT_ALPHA:
+      return GL_TRUE;
+   default:
+      return GL_FALSE;
+   }
+}
+
+
+/**
+ * Check if given blend destination factor is legal.
+ * \return GL_TRUE if legal, GL_FALSE otherwise.
+ */
+static GLboolean
+legal_dst_factor(const struct gl_context *ctx, GLenum factor)
+{
+   switch (factor) {
+   case GL_DST_COLOR:
+   case GL_ONE_MINUS_DST_COLOR:
+      return ctx->Extensions.NV_blend_square;
+   case GL_ZERO:
+   case GL_ONE:
+   case GL_SRC_COLOR:
+   case GL_ONE_MINUS_SRC_COLOR:
+   case GL_SRC_ALPHA:
+   case GL_ONE_MINUS_SRC_ALPHA:
+   case GL_DST_ALPHA:
+   case GL_ONE_MINUS_DST_ALPHA:
+   case GL_CONSTANT_COLOR:
+   case GL_ONE_MINUS_CONSTANT_COLOR:
+   case GL_CONSTANT_ALPHA:
+   case GL_ONE_MINUS_CONSTANT_ALPHA:
+      return GL_TRUE;
+   default:
+      return GL_FALSE;
+   }
+}
+
+
+/**
+ * Check if src/dest RGB/A blend factors are legal.  If not generate
+ * a GL error.
+ * \return GL_TRUE if factors are legal, GL_FALSE otherwise.
+ */
+static GLboolean
+validate_blend_factors(struct gl_context *ctx, const char *func,
+                       GLenum sfactorRGB, GLenum dfactorRGB,
+                       GLenum sfactorA, GLenum dfactorA)
+{
+   if (!legal_src_factor(ctx, sfactorRGB)) {
+      _mesa_error(ctx, GL_INVALID_ENUM,
+                  "%s(sfactorRGB = %s)", func,
+                  _mesa_lookup_enum_by_nr(sfactorRGB));
+      return GL_FALSE;
+   }
+
+   if (!legal_dst_factor(ctx, dfactorRGB)) {
+      _mesa_error(ctx, GL_INVALID_ENUM,
+                  "%s(dfactorRGB = %s)", func,
+                  _mesa_lookup_enum_by_nr(dfactorRGB));
+      return GL_FALSE;
+   }
+
+   if (sfactorA != sfactorRGB && !legal_src_factor(ctx, sfactorA)) {
+      _mesa_error(ctx, GL_INVALID_ENUM,
+                  "%s(sfactorA = %s)", func,
+                  _mesa_lookup_enum_by_nr(sfactorA));
+      return GL_FALSE;
+   }
+
+   if (dfactorA != dfactorRGB && !legal_dst_factor(ctx, dfactorA)) {
+      _mesa_error(ctx, GL_INVALID_ENUM,
+                  "%s(dfactorA = %s)", func,
+                  _mesa_lookup_enum_by_nr(dfactorA));
+      return GL_FALSE;
+   }
+
+   return GL_TRUE;
+}
+
+
+/**
+ * Specify the blending operation.
+ *
+ * \param sfactor source factor operator.
+ * \param dfactor destination factor operator.
+ *
+ * \sa glBlendFunc, glBlendFuncSeparateEXT
+ */
+void GLAPIENTRY
+_mesa_BlendFunc( GLenum sfactor, GLenum dfactor )
+{
+   _mesa_BlendFuncSeparateEXT(sfactor, dfactor, sfactor, dfactor);
+}
+
+
+/**
+ * Set the separate blend source/dest factors for all draw buffers.
+ *
+ * \param sfactorRGB RGB source factor operator.
+ * \param dfactorRGB RGB destination factor operator.
+ * \param sfactorA alpha source factor operator.
+ * \param dfactorA alpha destination factor operator.
+ */
+void GLAPIENTRY
+_mesa_BlendFuncSeparateEXT( GLenum sfactorRGB, GLenum dfactorRGB,
+                            GLenum sfactorA, GLenum dfactorA )
+{
+   GLuint buf, numBuffers;
+   GLboolean changed;
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glBlendFuncSeparate %s %s %s %s\n",
+                  _mesa_lookup_enum_by_nr(sfactorRGB),
+                  _mesa_lookup_enum_by_nr(dfactorRGB),
+                  _mesa_lookup_enum_by_nr(sfactorA),
+                  _mesa_lookup_enum_by_nr(dfactorA));
+
+   if (!validate_blend_factors(ctx, "glBlendFuncSeparate",
+                               sfactorRGB, dfactorRGB,
+                               sfactorA, dfactorA)) {
+      return;
+   }
+
+   numBuffers = ctx->Extensions.ARB_draw_buffers_blend
+      ? ctx->Const.MaxDrawBuffers : 1;
+
+   changed = GL_FALSE;
+   for (buf = 0; buf < numBuffers; buf++) {
+      if (ctx->Color.Blend[buf].SrcRGB != sfactorRGB ||
+          ctx->Color.Blend[buf].DstRGB != dfactorRGB ||
+          ctx->Color.Blend[buf].SrcA != sfactorA ||
+          ctx->Color.Blend[buf].DstA != dfactorA) {
+         changed = GL_TRUE;
+         break;
+      }
+   }
+   if (!changed)
+      return;
+
+   FLUSH_VERTICES(ctx, _NEW_COLOR);
+
+   for (buf = 0; buf < numBuffers; buf++) {
+      ctx->Color.Blend[buf].SrcRGB = sfactorRGB;
+      ctx->Color.Blend[buf].DstRGB = dfactorRGB;
+      ctx->Color.Blend[buf].SrcA = sfactorA;
+      ctx->Color.Blend[buf].DstA = dfactorA;
+   }
+   ctx->Color._BlendFuncPerBuffer = GL_FALSE;
+
+   if (ctx->Driver.BlendFuncSeparate) {
+      ctx->Driver.BlendFuncSeparate(ctx, sfactorRGB, dfactorRGB,
+                                    sfactorA, dfactorA);
+   }
+}
+
+
+#if _HAVE_FULL_GL
+
+
+/**
+ * Set blend source/dest factors for one color buffer/target.
+ */
+void GLAPIENTRY
+_mesa_BlendFunci(GLuint buf, GLenum sfactor, GLenum dfactor)
+{
+   _mesa_BlendFuncSeparatei(buf, sfactor, dfactor, sfactor, dfactor);
+}
+
+
+/**
+ * Set separate blend source/dest factors for one color buffer/target.
+ */
+void GLAPIENTRY
+_mesa_BlendFuncSeparatei(GLuint buf, GLenum sfactorRGB, GLenum dfactorRGB,
+                         GLenum sfactorA, GLenum dfactorA)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (!ctx->Extensions.ARB_draw_buffers_blend) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "glBlendFunc[Separate]i()");
+      return;
+   }
+
+   if (buf >= ctx->Const.MaxDrawBuffers) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "glBlendFuncSeparatei(buffer=%u)",
+                  buf);
+      return;
+   }
+
+   if (!validate_blend_factors(ctx, "glBlendFuncSeparatei",
+                               sfactorRGB, dfactorRGB,
+                               sfactorA, dfactorA)) {
+      return;
+   }
+
+   if (ctx->Color.Blend[buf].SrcRGB == sfactorRGB &&
+       ctx->Color.Blend[buf].DstRGB == dfactorRGB &&
+       ctx->Color.Blend[buf].SrcA == sfactorA &&
+       ctx->Color.Blend[buf].DstA == dfactorA)
+      return; /* no change */
+
+   FLUSH_VERTICES(ctx, _NEW_COLOR);
+
+   ctx->Color.Blend[buf].SrcRGB = sfactorRGB;
+   ctx->Color.Blend[buf].DstRGB = dfactorRGB;
+   ctx->Color.Blend[buf].SrcA = sfactorA;
+   ctx->Color.Blend[buf].DstA = dfactorA;
+   ctx->Color._BlendFuncPerBuffer = GL_TRUE;
+
+   if (ctx->Driver.BlendFuncSeparatei) {
+      ctx->Driver.BlendFuncSeparatei(ctx, buf, sfactorRGB, dfactorRGB,
+                                     sfactorA, dfactorA);
+   }
+}
+
+
+/**
+ * Check if given blend equation is legal.
+ * \return GL_TRUE if legal, GL_FALSE otherwise.
+ */
+static GLboolean
+legal_blend_equation(const struct gl_context *ctx,
+                     GLenum mode, GLboolean is_separate)
+{
+   switch (mode) {
+   case GL_FUNC_ADD:
+      return GL_TRUE;
+   case GL_MIN:
+   case GL_MAX:
+      return ctx->Extensions.EXT_blend_minmax;
+   case GL_LOGIC_OP:
+      /* glBlendEquationSeparate cannot take GL_LOGIC_OP as a parameter.
+       */
+      return ctx->Extensions.EXT_blend_logic_op && !is_separate;
+   case GL_FUNC_SUBTRACT:
+   case GL_FUNC_REVERSE_SUBTRACT:
+      return ctx->Extensions.EXT_blend_subtract;
+   default:
+      return GL_FALSE;
+   }
+}
+
+
+/* This is really an extension function! */
+void GLAPIENTRY
+_mesa_BlendEquation( GLenum mode )
+{
+   GLuint buf, numBuffers;
+   GLboolean changed;
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glBlendEquation(%s)\n",
+                  _mesa_lookup_enum_by_nr(mode));
+
+   if (!legal_blend_equation(ctx, mode, GL_FALSE)) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquation");
+      return;
+   }
+
+   numBuffers = ctx->Extensions.ARB_draw_buffers_blend
+      ? ctx->Const.MaxDrawBuffers : 1;
+
+   changed = GL_FALSE;
+   for (buf = 0; buf < numBuffers; buf++) {
+      if (ctx->Color.Blend[buf].EquationRGB != mode ||
+          ctx->Color.Blend[buf].EquationA != mode) {
+         changed = GL_TRUE;
+         break;
+      }
+   }
+   if (!changed)
+      return;
+
+   FLUSH_VERTICES(ctx, _NEW_COLOR);
+   for (buf = 0; buf < numBuffers; buf++) {
+      ctx->Color.Blend[buf].EquationRGB = mode;
+      ctx->Color.Blend[buf].EquationA = mode;
+   }
+   ctx->Color._BlendEquationPerBuffer = GL_FALSE;
+
+   if (ctx->Driver.BlendEquationSeparate)
+      (*ctx->Driver.BlendEquationSeparate)( ctx, mode, mode );
+}
+
+
+/**
+ * Set blend equation for one color buffer/target.
+ */
+void GLAPIENTRY
+_mesa_BlendEquationi(GLuint buf, GLenum mode)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glBlendEquationi(%u, %s)\n",
+                  buf, _mesa_lookup_enum_by_nr(mode));
+
+   if (buf >= ctx->Const.MaxDrawBuffers) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "glBlendFuncSeparatei(buffer=%u)",
+                  buf);
+      return;
+   }
+
+   if (!legal_blend_equation(ctx, mode, GL_FALSE)) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationi");
+      return;
+   }
+
+   if (ctx->Color.Blend[buf].EquationRGB == mode &&
+       ctx->Color.Blend[buf].EquationA == mode)
+      return;  /* no change */
+
+   FLUSH_VERTICES(ctx, _NEW_COLOR);
+   ctx->Color.Blend[buf].EquationRGB = mode;
+   ctx->Color.Blend[buf].EquationA = mode;
+   ctx->Color._BlendEquationPerBuffer = GL_TRUE;
+
+   if (ctx->Driver.BlendEquationSeparatei)
+      ctx->Driver.BlendEquationSeparatei(ctx, buf, mode, mode);
+}
+
+
+void GLAPIENTRY
+_mesa_BlendEquationSeparateEXT( GLenum modeRGB, GLenum modeA )
+{
+   GLuint buf, numBuffers;
+   GLboolean changed;
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glBlendEquationSeparateEXT(%s %s)\n",
+                  _mesa_lookup_enum_by_nr(modeRGB),
+                  _mesa_lookup_enum_by_nr(modeA));
+
+   if ( (modeRGB != modeA) && !ctx->Extensions.EXT_blend_equation_separate ) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+		  "glBlendEquationSeparateEXT not supported by driver");
+      return;
+   }
+
+   if (!legal_blend_equation(ctx, modeRGB, GL_TRUE)) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparateEXT(modeRGB)");
+      return;
+   }
+
+   if (!legal_blend_equation(ctx, modeA, GL_TRUE)) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparateEXT(modeA)");
+      return;
+   }
+
+   numBuffers = ctx->Extensions.ARB_draw_buffers_blend
+      ? ctx->Const.MaxDrawBuffers : 1;
+
+   changed = GL_FALSE;
+   for (buf = 0; buf < numBuffers; buf++) {
+      if (ctx->Color.Blend[buf].EquationRGB != modeRGB ||
+          ctx->Color.Blend[buf].EquationA != modeA) {
+         changed = GL_TRUE;
+         break;
+      }
+   }
+   if (!changed)
+      return;
+
+   FLUSH_VERTICES(ctx, _NEW_COLOR);
+   for (buf = 0; buf < numBuffers; buf++) {
+      ctx->Color.Blend[buf].EquationRGB = modeRGB;
+      ctx->Color.Blend[buf].EquationA = modeA;
+   }
+   ctx->Color._BlendEquationPerBuffer = GL_FALSE;
+
+   if (ctx->Driver.BlendEquationSeparate)
+      ctx->Driver.BlendEquationSeparate(ctx, modeRGB, modeA);
+}
+
+
+/**
+ * Set separate blend equations for one color buffer/target.
+ */
+void
+_mesa_BlendEquationSeparatei(GLuint buf, GLenum modeRGB, GLenum modeA)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glBlendEquationSeparatei(%u, %s %s)\n", buf,
+                  _mesa_lookup_enum_by_nr(modeRGB),
+                  _mesa_lookup_enum_by_nr(modeA));
+
+   if (buf >= ctx->Const.MaxDrawBuffers) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "glBlendEquationSeparatei(buffer=%u)",
+                  buf);
+      return;
+   }
+
+   if (!legal_blend_equation(ctx, modeRGB, GL_TRUE)) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparatei(modeRGB)");
+      return;
+   }
+
+   if (!legal_blend_equation(ctx, modeA, GL_TRUE)) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparatei(modeA)");
+      return;
+   }
+
+   if (ctx->Color.Blend[buf].EquationRGB == modeRGB &&
+       ctx->Color.Blend[buf].EquationA == modeA)
+      return;  /* no change */
+
+   FLUSH_VERTICES(ctx, _NEW_COLOR);
+   ctx->Color.Blend[buf].EquationRGB = modeRGB;
+   ctx->Color.Blend[buf].EquationA = modeA;
+   ctx->Color._BlendEquationPerBuffer = GL_TRUE;
+
+   if (ctx->Driver.BlendEquationSeparatei)
+      ctx->Driver.BlendEquationSeparatei(ctx, buf, modeRGB, modeA);
+}
+
+
+
+#endif /* _HAVE_FULL_GL */
+
+
+/**
+ * Set the blending color.
+ *
+ * \param red red color component.
+ * \param green green color component.
+ * \param blue blue color component.
+ * \param alpha alpha color component.
+ *
+ * \sa glBlendColor().
+ *
+ * Clamps the parameters and updates gl_colorbuffer_attrib::BlendColor.  On a
+ * change, flushes the vertices and notifies the driver via
+ * dd_function_table::BlendColor callback.
+ */
+void GLAPIENTRY
+_mesa_BlendColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
+{
+   GLfloat tmp[4];
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   tmp[0] = CLAMP( red,   0.0F, 1.0F );
+   tmp[1] = CLAMP( green, 0.0F, 1.0F );
+   tmp[2] = CLAMP( blue,  0.0F, 1.0F );
+   tmp[3] = CLAMP( alpha, 0.0F, 1.0F );
+
+   if (TEST_EQ_4V(tmp, ctx->Color.BlendColor))
+      return;
+
+   FLUSH_VERTICES(ctx, _NEW_COLOR);
+   COPY_4FV( ctx->Color.BlendColor, tmp );
+
+   if (ctx->Driver.BlendColor)
+      (*ctx->Driver.BlendColor)(ctx, tmp);
+}
+
+
+/**
+ * Specify the alpha test function.
+ *
+ * \param func alpha comparison function.
+ * \param ref reference value.
+ *
+ * Verifies the parameters and updates gl_colorbuffer_attrib. 
+ * On a change, flushes the vertices and notifies the driver via
+ * dd_function_table::AlphaFunc callback.
+ */
+void GLAPIENTRY
+_mesa_AlphaFunc( GLenum func, GLclampf ref )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glAlphaFunc(%s, %f)\n",
+                  _mesa_lookup_enum_by_nr(func), ref);
+
+   switch (func) {
+   case GL_NEVER:
+   case GL_LESS:
+   case GL_EQUAL:
+   case GL_LEQUAL:
+   case GL_GREATER:
+   case GL_NOTEQUAL:
+   case GL_GEQUAL:
+   case GL_ALWAYS:
+      ref = CLAMP(ref, 0.0F, 1.0F);
+
+      if (ctx->Color.AlphaFunc == func && ctx->Color.AlphaRef == ref)
+         return; /* no change */
+
+      FLUSH_VERTICES(ctx, _NEW_COLOR);
+      ctx->Color.AlphaFunc = func;
+      ctx->Color.AlphaRef = ref;
+
+      if (ctx->Driver.AlphaFunc)
+         ctx->Driver.AlphaFunc(ctx, func, ref);
+      return;
+
+   default:
+      _mesa_error( ctx, GL_INVALID_ENUM, "glAlphaFunc(func)" );
+      return;
+   }
+}
+
+
+/**
+ * Specify a logic pixel operation for color index rendering.
+ *
+ * \param opcode operation.
+ *
+ * Verifies that \p opcode is a valid enum and updates
+gl_colorbuffer_attrib::LogicOp.
+ * On a change, flushes the vertices and notifies the driver via the
+ * dd_function_table::LogicOpcode callback.
+ */
+void GLAPIENTRY
+_mesa_LogicOp( GLenum opcode )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glLogicOp(%s)\n", _mesa_lookup_enum_by_nr(opcode));
+
+   switch (opcode) {
+      case GL_CLEAR:
+      case GL_SET:
+      case GL_COPY:
+      case GL_COPY_INVERTED:
+      case GL_NOOP:
+      case GL_INVERT:
+      case GL_AND:
+      case GL_NAND:
+      case GL_OR:
+      case GL_NOR:
+      case GL_XOR:
+      case GL_EQUIV:
+      case GL_AND_REVERSE:
+      case GL_AND_INVERTED:
+      case GL_OR_REVERSE:
+      case GL_OR_INVERTED:
+	 break;
+      default:
+         _mesa_error( ctx, GL_INVALID_ENUM, "glLogicOp" );
+	 return;
+   }
+
+   if (ctx->Color.LogicOp == opcode)
+      return;
+
+   FLUSH_VERTICES(ctx, _NEW_COLOR);
+   ctx->Color.LogicOp = opcode;
+
+   if (ctx->Driver.LogicOpcode)
+      ctx->Driver.LogicOpcode( ctx, opcode );
+}
+
+#if _HAVE_FULL_GL
+void GLAPIENTRY
+_mesa_IndexMask( GLuint mask )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (ctx->Color.IndexMask == mask)
+      return;
+
+   FLUSH_VERTICES(ctx, _NEW_COLOR);
+   ctx->Color.IndexMask = mask;
+}
+#endif
+
+
+/**
+ * Enable or disable writing of frame buffer color components.
+ *
+ * \param red whether to mask writing of the red color component.
+ * \param green whether to mask writing of the green color component.
+ * \param blue whether to mask writing of the blue color component.
+ * \param alpha whether to mask writing of the alpha color component.
+ *
+ * \sa glColorMask().
+ *
+ * Sets the appropriate value of gl_colorbuffer_attrib::ColorMask.  On a
+ * change, flushes the vertices and notifies the driver via the
+ * dd_function_table::ColorMask callback.
+ */
+void GLAPIENTRY
+_mesa_ColorMask( GLboolean red, GLboolean green,
+                 GLboolean blue, GLboolean alpha )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   GLubyte tmp[4];
+   GLuint i;
+   GLboolean flushed;
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glColorMask(%d, %d, %d, %d)\n",
+                  red, green, blue, alpha);
+
+   /* Shouldn't have any information about channel depth in core mesa
+    * -- should probably store these as the native booleans:
+    */
+   tmp[RCOMP] = red    ? 0xff : 0x0;
+   tmp[GCOMP] = green  ? 0xff : 0x0;
+   tmp[BCOMP] = blue   ? 0xff : 0x0;
+   tmp[ACOMP] = alpha  ? 0xff : 0x0;
+
+   flushed = GL_FALSE;
+   for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
+      if (!TEST_EQ_4V(tmp, ctx->Color.ColorMask[i])) {
+         if (!flushed) {
+            FLUSH_VERTICES(ctx, _NEW_COLOR);
+         }
+         flushed = GL_TRUE;
+         COPY_4UBV(ctx->Color.ColorMask[i], tmp);
+      }
+   }
+
+   if (ctx->Driver.ColorMask)
+      ctx->Driver.ColorMask( ctx, red, green, blue, alpha );
+}
+
+
+/**
+ * For GL_EXT_draw_buffers2 and GL3
+ */
+void GLAPIENTRY
+_mesa_ColorMaskIndexed( GLuint buf, GLboolean red, GLboolean green,
+                        GLboolean blue, GLboolean alpha )
+{
+   GLubyte tmp[4];
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glColorMaskIndexed %u %d %d %d %d\n",
+                  buf, red, green, blue, alpha);
+
+   if (buf >= ctx->Const.MaxDrawBuffers) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "glColorMaskIndexed(buf=%u)", buf);
+      return;
+   }
+
+   /* Shouldn't have any information about channel depth in core mesa
+    * -- should probably store these as the native booleans:
+    */
+   tmp[RCOMP] = red    ? 0xff : 0x0;
+   tmp[GCOMP] = green  ? 0xff : 0x0;
+   tmp[BCOMP] = blue   ? 0xff : 0x0;
+   tmp[ACOMP] = alpha  ? 0xff : 0x0;
+
+   if (TEST_EQ_4V(tmp, ctx->Color.ColorMask[buf]))
+      return;
+
+   FLUSH_VERTICES(ctx, _NEW_COLOR);
+   COPY_4UBV(ctx->Color.ColorMask[buf], tmp);
+
+   if (ctx->Driver.ColorMaskIndexed)
+      ctx->Driver.ColorMaskIndexed(ctx, buf, red, green, blue, alpha);
+}
+
+
+extern void GLAPIENTRY
+_mesa_ClampColorARB(GLenum target, GLenum clamp)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (clamp != GL_TRUE && clamp != GL_FALSE && clamp != GL_FIXED_ONLY_ARB) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glClampColorARB(clamp)");
+      return;
+   }
+
+   switch (target) {
+   case GL_CLAMP_VERTEX_COLOR_ARB:
+      ctx->Light.ClampVertexColor = clamp;
+      break;
+   case GL_CLAMP_FRAGMENT_COLOR_ARB:
+      ctx->Color.ClampFragmentColor = clamp;
+      break;
+   case GL_CLAMP_READ_COLOR_ARB:
+      ctx->Color.ClampReadColor = clamp;
+      break;
+   default:
+      _mesa_error(ctx, GL_INVALID_ENUM, "glClampColorARB(target)");
+      return;
+   }
+}
+
+
+
+
+/**********************************************************************/
+/** \name Initialization */
+/*@{*/
+
+/**
+ * Initialization of the context's Color attribute group.
+ *
+ * \param ctx GL context.
+ *
+ * Initializes the related fields in the context color attribute group,
+ * __struct gl_contextRec::Color.
+ */
+void _mesa_init_color( struct gl_context * ctx )
+{
+   GLuint i;
+
+   /* Color buffer group */
+   ctx->Color.IndexMask = ~0u;
+   memset(ctx->Color.ColorMask, 0xff, sizeof(ctx->Color.ColorMask));
+   ctx->Color.ClearIndex = 0;
+   ASSIGN_4V( ctx->Color.ClearColor, 0, 0, 0, 0 );
+   ctx->Color.AlphaEnabled = GL_FALSE;
+   ctx->Color.AlphaFunc = GL_ALWAYS;
+   ctx->Color.AlphaRef = 0;
+   ctx->Color.BlendEnabled = 0x0;
+   for (i = 0; i < Elements(ctx->Color.Blend); i++) {
+      ctx->Color.Blend[i].SrcRGB = GL_ONE;
+      ctx->Color.Blend[i].DstRGB = GL_ZERO;
+      ctx->Color.Blend[i].SrcA = GL_ONE;
+      ctx->Color.Blend[i].DstA = GL_ZERO;
+      ctx->Color.Blend[i].EquationRGB = GL_FUNC_ADD;
+      ctx->Color.Blend[i].EquationA = GL_FUNC_ADD;
+   }
+   ASSIGN_4V( ctx->Color.BlendColor, 0.0, 0.0, 0.0, 0.0 );
+   ctx->Color.IndexLogicOpEnabled = GL_FALSE;
+   ctx->Color.ColorLogicOpEnabled = GL_FALSE;
+   ctx->Color._LogicOpEnabled = GL_FALSE;
+   ctx->Color.LogicOp = GL_COPY;
+   ctx->Color.DitherFlag = GL_TRUE;
+
+   if (ctx->Visual.doubleBufferMode) {
+      ctx->Color.DrawBuffer[0] = GL_BACK;
+   }
+   else {
+      ctx->Color.DrawBuffer[0] = GL_FRONT;
+   }
+
+   ctx->Color.ClampFragmentColor = GL_FIXED_ONLY_ARB;
+   ctx->Color.ClampReadColor = GL_FIXED_ONLY_ARB;
+}
+
+/*@}*/
diff --git a/mesalib/src/mesa/main/bufferobj.c b/mesalib/src/mesa/main/bufferobj.c
index 31475529e..75afae0ad 100644
--- a/mesalib/src/mesa/main/bufferobj.c
+++ b/mesalib/src/mesa/main/bufferobj.c
@@ -1,2145 +1,2158 @@
-/*
- * Mesa 3-D graphics library
- * Version:  7.6
- *
- * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
- * Copyright (C) 2009  VMware, Inc.  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"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-/**
- * \file bufferobj.c
- * \brief Functions for the GL_ARB_vertex/pixel_buffer_object extensions.
- * \author Brian Paul, Ian Romanick
- */
-
-
-#include "glheader.h"
-#include "enums.h"
-#include "hash.h"
-#include "imports.h"
-#include "image.h"
-#include "context.h"
-#include "bufferobj.h"
-#include "fbobject.h"
-#include "mfeatures.h"
-#include "mtypes.h"
-#include "texobj.h"
-
-
-/* Debug flags */
-/*#define VBO_DEBUG*/
-/*#define BOUNDS_CHECK*/
-
-
-#if FEATURE_OES_mapbuffer
-#define DEFAULT_ACCESS GL_MAP_WRITE_BIT
-#else
-#define DEFAULT_ACCESS (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)
-#endif
-
-
-/**
- * Used as a placeholder for buffer objects between glGenBuffers() and
- * glBindBuffer() so that glIsBuffer() can work correctly.
- */
-static struct gl_buffer_object DummyBufferObject;
-
-
-/**
- * Return pointer to address of a buffer object target.
- * \param ctx  the GL context
- * \param target  the buffer object target to be retrieved.
- * \return   pointer to pointer to the buffer object bound to \c target in the
- *           specified context or \c NULL if \c target is invalid.
- */
-static INLINE struct gl_buffer_object **
-get_buffer_target(struct gl_context *ctx, GLenum target)
-{
-   switch (target) {
-   case GL_ARRAY_BUFFER_ARB:
-      return &ctx->Array.ArrayBufferObj;
-   case GL_ELEMENT_ARRAY_BUFFER_ARB:
-      return &ctx->Array.ElementArrayBufferObj;
-   case GL_PIXEL_PACK_BUFFER_EXT:
-      return &ctx->Pack.BufferObj;
-   case GL_PIXEL_UNPACK_BUFFER_EXT:
-      return &ctx->Unpack.BufferObj;
-   case GL_COPY_READ_BUFFER:
-      return &ctx->CopyReadBuffer;
-   case GL_COPY_WRITE_BUFFER:
-      return &ctx->CopyWriteBuffer;
-#if FEATURE_EXT_transform_feedback
-   case GL_TRANSFORM_FEEDBACK_BUFFER:
-      if (ctx->Extensions.EXT_transform_feedback) {
-         return &ctx->TransformFeedback.CurrentBuffer;
-      }
-      break;
-#endif
-   default:
-      return NULL;
-   }
-   return NULL;
-}
-
-
-/**
- * Get the buffer object bound to the specified target in a GL context.
- * \param ctx  the GL context
- * \param target  the buffer object target to be retrieved.
- * \return   pointer to the buffer object bound to \c target in the
- *           specified context or \c NULL if \c target is invalid.
- */
-static INLINE struct gl_buffer_object *
-get_buffer(struct gl_context *ctx, GLenum target)
-{
-   struct gl_buffer_object **bufObj = get_buffer_target(ctx, target);
-   if (bufObj)
-      return *bufObj;
-   return NULL;
-}
-
-
-/**
- * Convert a GLbitfield describing the mapped buffer access flags
- * into one of GL_READ_WRITE, GL_READ_ONLY, or GL_WRITE_ONLY.
- */
-static GLenum
-simplified_access_mode(GLbitfield access)
-{
-   const GLbitfield rwFlags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT;
-   if ((access & rwFlags) == rwFlags)
-      return GL_READ_WRITE;
-   if ((access & GL_MAP_READ_BIT) == GL_MAP_READ_BIT)
-      return GL_READ_ONLY;
-   if ((access & GL_MAP_WRITE_BIT) == GL_MAP_WRITE_BIT)
-      return GL_WRITE_ONLY;
-   return GL_READ_WRITE; /* this should never happen, but no big deal */
-}
-
-
-/**
- * Tests the subdata range parameters and sets the GL error code for
- * \c glBufferSubDataARB and \c glGetBufferSubDataARB.
- *
- * \param ctx     GL context.
- * \param target  Buffer object target on which to operate.
- * \param offset  Offset of the first byte of the subdata range.
- * \param size    Size, in bytes, of the subdata range.
- * \param caller  Name of calling function for recording errors.
- * \return   A pointer to the buffer object bound to \c target in the
- *           specified context or \c NULL if any of the parameter or state
- *           conditions for \c glBufferSubDataARB or \c glGetBufferSubDataARB
- *           are invalid.
- *
- * \sa glBufferSubDataARB, glGetBufferSubDataARB
- */
-static struct gl_buffer_object *
-buffer_object_subdata_range_good( struct gl_context * ctx, GLenum target, 
-                                  GLintptrARB offset, GLsizeiptrARB size,
-                                  const char *caller )
-{
-   struct gl_buffer_object *bufObj;
-
-   if (size < 0) {
-      _mesa_error(ctx, GL_INVALID_VALUE, "%s(size < 0)", caller);
-      return NULL;
-   }
-
-   if (offset < 0) {
-      _mesa_error(ctx, GL_INVALID_VALUE, "%s(offset < 0)", caller);
-      return NULL;
-   }
-
-   bufObj = get_buffer(ctx, target);
-   if (!bufObj) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", caller);
-      return NULL;
-   }
-   if (!_mesa_is_bufferobj(bufObj)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller);
-      return NULL;
-   }
-   if (offset + size > bufObj->Size) {
-      _mesa_error(ctx, GL_INVALID_VALUE,
-		  "%s(size + offset > buffer size)", caller);
-      return NULL;
-   }
-   if (_mesa_bufferobj_mapped(bufObj)) {
-      /* Buffer is currently mapped */
-      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller);
-      return NULL;
-   }
-
-   return bufObj;
-}
-
-
-/**
- * Allocate and initialize a new buffer object.
- * 
- * Default callback for the \c dd_function_table::NewBufferObject() hook.
- */
-static struct gl_buffer_object *
-_mesa_new_buffer_object( struct gl_context *ctx, GLuint name, GLenum target )
-{
-   struct gl_buffer_object *obj;
-
-   (void) ctx;
-
-   obj = MALLOC_STRUCT(gl_buffer_object);
-   _mesa_initialize_buffer_object(obj, name, target);
-   return obj;
-}
-
-
-/**
- * Delete a buffer object.
- * 
- * Default callback for the \c dd_function_table::DeleteBuffer() hook.
- */
-static void
-_mesa_delete_buffer_object( struct gl_context *ctx, struct gl_buffer_object *bufObj )
-{
-   (void) ctx;
-
-   if (bufObj->Data)
-      free(bufObj->Data);
-
-   /* assign strange values here to help w/ debugging */
-   bufObj->RefCount = -1000;
-   bufObj->Name = ~0;
-
-   _glthread_DESTROY_MUTEX(bufObj->Mutex);
-   free(bufObj);
-}
-
-
-
-/**
- * Set ptr to bufObj w/ reference counting.
- */
-void
-_mesa_reference_buffer_object(struct gl_context *ctx,
-                              struct gl_buffer_object **ptr,
-                              struct gl_buffer_object *bufObj)
-{
-   if (*ptr == bufObj)
-      return;
-
-   if (*ptr) {
-      /* Unreference the old buffer */
-      GLboolean deleteFlag = GL_FALSE;
-      struct gl_buffer_object *oldObj = *ptr;
-
-      _glthread_LOCK_MUTEX(oldObj->Mutex);
-      ASSERT(oldObj->RefCount > 0);
-      oldObj->RefCount--;
-#if 0
-      printf("BufferObj %p %d DECR to %d\n",
-             (void *) oldObj, oldObj->Name, oldObj->RefCount);
-#endif
-      deleteFlag = (oldObj->RefCount == 0);
-      _glthread_UNLOCK_MUTEX(oldObj->Mutex);
-
-      if (deleteFlag) {
-
-         /* some sanity checking: don't delete a buffer still in use */
-#if 0
-         /* unfortunately, these tests are invalid during context tear-down */
-	 ASSERT(ctx->Array.ArrayBufferObj != bufObj);
-	 ASSERT(ctx->Array.ElementArrayBufferObj != bufObj);
-	 ASSERT(ctx->Array.ArrayObj->Vertex.BufferObj != bufObj);
-#endif
-
-	 ASSERT(ctx->Driver.DeleteBuffer);
-         ctx->Driver.DeleteBuffer(ctx, oldObj);
-      }
-
-      *ptr = NULL;
-   }
-   ASSERT(!*ptr);
-
-   if (bufObj) {
-      /* reference new buffer */
-      _glthread_LOCK_MUTEX(bufObj->Mutex);
-      if (bufObj->RefCount == 0) {
-         /* this buffer's being deleted (look just above) */
-         /* Not sure this can every really happen.  Warn if it does. */
-         _mesa_problem(NULL, "referencing deleted buffer object");
-         *ptr = NULL;
-      }
-      else {
-         bufObj->RefCount++;
-#if 0
-         printf("BufferObj %p %d INCR to %d\n",
-                (void *) bufObj, bufObj->Name, bufObj->RefCount);
-#endif
-         *ptr = bufObj;
-      }
-      _glthread_UNLOCK_MUTEX(bufObj->Mutex);
-   }
-}
-
-
-/**
- * Initialize a buffer object to default values.
- */
-void
-_mesa_initialize_buffer_object( struct gl_buffer_object *obj,
-				GLuint name, GLenum target )
-{
-   (void) target;
-
-   memset(obj, 0, sizeof(struct gl_buffer_object));
-   _glthread_INIT_MUTEX(obj->Mutex);
-   obj->RefCount = 1;
-   obj->Name = name;
-   obj->Usage = GL_STATIC_DRAW_ARB;
-   obj->AccessFlags = DEFAULT_ACCESS;
-}
-
-
-/**
- * Allocate space for and store data in a buffer object.  Any data that was
- * previously stored in the buffer object is lost.  If \c data is \c NULL,
- * memory will be allocated, but no copy will occur.
- *
- * This is the default callback for \c dd_function_table::BufferData()
- * Note that all GL error checking will have been done already.
- *
- * \param ctx     GL context.
- * \param target  Buffer object target on which to operate.
- * \param size    Size, in bytes, of the new data store.
- * \param data    Pointer to the data to store in the buffer object.  This
- *                pointer may be \c NULL.
- * \param usage   Hints about how the data will be used.
- * \param bufObj  Object to be used.
- *
- * \return GL_TRUE for success, GL_FALSE for failure
- * \sa glBufferDataARB, dd_function_table::BufferData.
- */
-static GLboolean
-_mesa_buffer_data( struct gl_context *ctx, GLenum target, GLsizeiptrARB size,
-		   const GLvoid * data, GLenum usage,
-		   struct gl_buffer_object * bufObj )
-{
-   void * new_data;
-
-   (void) ctx; (void) target;
-
-   new_data = _mesa_realloc( bufObj->Data, bufObj->Size, size );
-   if (new_data) {
-      bufObj->Data = (GLubyte *) new_data;
-      bufObj->Size = size;
-      bufObj->Usage = usage;
-
-      if (data) {
-	 memcpy( bufObj->Data, data, size );
-      }
-
-      return GL_TRUE;
-   }
-   else {
-      return GL_FALSE;
-   }
-}
-
-
-/**
- * Replace data in a subrange of buffer object.  If the data range
- * specified by \c size + \c offset extends beyond the end of the buffer or
- * if \c data is \c NULL, no copy is performed.
- *
- * This is the default callback for \c dd_function_table::BufferSubData()
- * Note that all GL error checking will have been done already.
- *
- * \param ctx     GL context.
- * \param target  Buffer object target on which to operate.
- * \param offset  Offset of the first byte to be modified.
- * \param size    Size, in bytes, of the data range.
- * \param data    Pointer to the data to store in the buffer object.
- * \param bufObj  Object to be used.
- *
- * \sa glBufferSubDataARB, dd_function_table::BufferSubData.
- */
-static void
-_mesa_buffer_subdata( struct gl_context *ctx, GLenum target, GLintptrARB offset,
-		      GLsizeiptrARB size, const GLvoid * data,
-		      struct gl_buffer_object * bufObj )
-{
-   (void) ctx; (void) target;
-
-   /* this should have been caught in _mesa_BufferSubData() */
-   ASSERT(size + offset <= bufObj->Size);
-
-   if (bufObj->Data) {
-      memcpy( (GLubyte *) bufObj->Data + offset, data, size );
-   }
-}
-
-
-/**
- * Retrieve data from a subrange of buffer object.  If the data range
- * specified by \c size + \c offset extends beyond the end of the buffer or
- * if \c data is \c NULL, no copy is performed.
- *
- * This is the default callback for \c dd_function_table::GetBufferSubData()
- * Note that all GL error checking will have been done already.
- *
- * \param ctx     GL context.
- * \param target  Buffer object target on which to operate.
- * \param offset  Offset of the first byte to be fetched.
- * \param size    Size, in bytes, of the data range.
- * \param data    Destination for data
- * \param bufObj  Object to be used.
- *
- * \sa glBufferGetSubDataARB, dd_function_table::GetBufferSubData.
- */
-static void
-_mesa_buffer_get_subdata( struct gl_context *ctx, GLenum target, GLintptrARB offset,
-			  GLsizeiptrARB size, GLvoid * data,
-			  struct gl_buffer_object * bufObj )
-{
-   (void) ctx; (void) target;
-
-   if (bufObj->Data && ((GLsizeiptrARB) (size + offset) <= bufObj->Size)) {
-      memcpy( data, (GLubyte *) bufObj->Data + offset, size );
-   }
-}
-
-
-/**
- * Default callback for \c dd_function_tabel::MapBuffer().
- *
- * The function parameters will have been already tested for errors.
- *
- * \param ctx     GL context.
- * \param target  Buffer object target on which to operate.
- * \param access  Information about how the buffer will be accessed.
- * \param bufObj  Object to be mapped.
- * \return  A pointer to the object's internal data store that can be accessed
- *          by the processor
- *
- * \sa glMapBufferARB, dd_function_table::MapBuffer
- */
-static void *
-_mesa_buffer_map( struct gl_context *ctx, GLenum target, GLenum access,
-		  struct gl_buffer_object *bufObj )
-{
-   (void) ctx;
-   (void) target;
-   (void) access;
-   /* Just return a direct pointer to the data */
-   if (_mesa_bufferobj_mapped(bufObj)) {
-      /* already mapped! */
-      return NULL;
-   }
-   bufObj->Pointer = bufObj->Data;
-   bufObj->Length = bufObj->Size;
-   bufObj->Offset = 0;
-   return bufObj->Pointer;
-}
-
-
-/**
- * Default fallback for \c dd_function_table::MapBufferRange().
- * Called via glMapBufferRange().
- */
-static void *
-_mesa_buffer_map_range( struct gl_context *ctx, GLenum target, GLintptr offset,
-                        GLsizeiptr length, GLbitfield access,
-                        struct gl_buffer_object *bufObj )
-{
-   (void) ctx;
-   (void) target;
-   assert(!_mesa_bufferobj_mapped(bufObj));
-   /* Just return a direct pointer to the data */
-   bufObj->Pointer = bufObj->Data + offset;
-   bufObj->Length = length;
-   bufObj->Offset = offset;
-   bufObj->AccessFlags = access;
-   return bufObj->Pointer;
-}
-
-
-/**
- * Default fallback for \c dd_function_table::FlushMappedBufferRange().
- * Called via glFlushMappedBufferRange().
- */
-static void
-_mesa_buffer_flush_mapped_range( struct gl_context *ctx, GLenum target, 
-                                 GLintptr offset, GLsizeiptr length,
-                                 struct gl_buffer_object *obj )
-{
-   (void) ctx;
-   (void) target;
-   (void) offset;
-   (void) length;
-   (void) obj;
-   /* no-op */
-}
-
-
-/**
- * Default callback for \c dd_function_table::MapBuffer().
- *
- * The input parameters will have been already tested for errors.
- *
- * \sa glUnmapBufferARB, dd_function_table::UnmapBuffer
- */
-static GLboolean
-_mesa_buffer_unmap( struct gl_context *ctx, GLenum target,
-                    struct gl_buffer_object *bufObj )
-{
-   (void) ctx;
-   (void) target;
-   /* XXX we might assert here that bufObj->Pointer is non-null */
-   bufObj->Pointer = NULL;
-   bufObj->Length = 0;
-   bufObj->Offset = 0;
-   bufObj->AccessFlags = 0x0;
-   return GL_TRUE;
-}
-
-
-/**
- * Default fallback for \c dd_function_table::CopyBufferSubData().
- * Called via glCopyBuffserSubData().
- */
-static void
-_mesa_copy_buffer_subdata(struct gl_context *ctx,
-                          struct gl_buffer_object *src,
-                          struct gl_buffer_object *dst,
-                          GLintptr readOffset, GLintptr writeOffset,
-                          GLsizeiptr size)
-{
-   GLubyte *srcPtr, *dstPtr;
-
-   /* buffer should not already be mapped */
-   assert(!_mesa_bufferobj_mapped(src));
-   assert(!_mesa_bufferobj_mapped(dst));
-
-   srcPtr = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_COPY_READ_BUFFER,
-                                              GL_READ_ONLY, src);
-   dstPtr = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_COPY_WRITE_BUFFER,
-                                              GL_WRITE_ONLY, dst);
-
-   if (srcPtr && dstPtr)
-      memcpy(dstPtr + writeOffset, srcPtr + readOffset, size);
-
-   ctx->Driver.UnmapBuffer(ctx, GL_COPY_READ_BUFFER, src);
-   ctx->Driver.UnmapBuffer(ctx, GL_COPY_WRITE_BUFFER, dst);
-}
-
-
-
-/**
- * Initialize the state associated with buffer objects
- */
-void
-_mesa_init_buffer_objects( struct gl_context *ctx )
-{
-   memset(&DummyBufferObject, 0, sizeof(DummyBufferObject));
-   DummyBufferObject.RefCount = 1000*1000*1000; /* never delete */
-
-   _mesa_reference_buffer_object(ctx, &ctx->Array.ArrayBufferObj,
-                                 ctx->Shared->NullBufferObj);
-   _mesa_reference_buffer_object(ctx, &ctx->Array.ElementArrayBufferObj,
-                                 ctx->Shared->NullBufferObj);
-
-   _mesa_reference_buffer_object(ctx, &ctx->CopyReadBuffer,
-                                 ctx->Shared->NullBufferObj);
-   _mesa_reference_buffer_object(ctx, &ctx->CopyWriteBuffer,
-                                 ctx->Shared->NullBufferObj);
-}
-
-
-void
-_mesa_free_buffer_objects( struct gl_context *ctx )
-{
-   _mesa_reference_buffer_object(ctx, &ctx->Array.ArrayBufferObj, NULL);
-   _mesa_reference_buffer_object(ctx, &ctx->Array.ElementArrayBufferObj, NULL);
-
-   _mesa_reference_buffer_object(ctx, &ctx->CopyReadBuffer, NULL);
-   _mesa_reference_buffer_object(ctx, &ctx->CopyWriteBuffer, NULL);
-}
-
-
-/**
- * Bind the specified target to buffer for the specified context.
- * Called by glBindBuffer() and other functions.
- */
-static void
-bind_buffer_object(struct gl_context *ctx, GLenum target, GLuint buffer)
-{
-   struct gl_buffer_object *oldBufObj;
-   struct gl_buffer_object *newBufObj = NULL;
-   struct gl_buffer_object **bindTarget = NULL;
-
-   bindTarget = get_buffer_target(ctx, target);
-   if (!bindTarget) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferARB(target 0x%x)", target);
-      return;
-   }
-
-   /* Get pointer to old buffer object (to be unbound) */
-   oldBufObj = *bindTarget;
-   if (oldBufObj && oldBufObj->Name == buffer)
-      return;   /* rebinding the same buffer object- no change */
-
-   /*
-    * Get pointer to new buffer object (newBufObj)
-    */
-   if (buffer == 0) {
-      /* The spec says there's not a buffer object named 0, but we use
-       * one internally because it simplifies things.
-       */
-      newBufObj = ctx->Shared->NullBufferObj;
-   }
-   else {
-      /* non-default buffer object */
-      newBufObj = _mesa_lookup_bufferobj(ctx, buffer);
-      if (!newBufObj || newBufObj == &DummyBufferObject) {
-         /* If this is a new buffer object id, or one which was generated but
-          * never used before, allocate a buffer object now.
-          */
-         ASSERT(ctx->Driver.NewBufferObject);
-         newBufObj = ctx->Driver.NewBufferObject(ctx, buffer, target);
-         if (!newBufObj) {
-            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindBufferARB");
-            return;
-         }
-         _mesa_HashInsert(ctx->Shared->BufferObjects, buffer, newBufObj);
-      }
-   }
-   
-   /* bind new buffer */
-   _mesa_reference_buffer_object(ctx, bindTarget, newBufObj);
-
-   /* Pass BindBuffer call to device driver */
-   if (ctx->Driver.BindBuffer)
-      ctx->Driver.BindBuffer( ctx, target, newBufObj );
-}
-
-
-/**
- * Update the default buffer objects in the given context to reference those
- * specified in the shared state and release those referencing the old 
- * shared state.
- */
-void
-_mesa_update_default_objects_buffer_objects(struct gl_context *ctx)
-{
-   /* Bind the NullBufferObj to remove references to those
-    * in the shared context hash table.
-    */
-   bind_buffer_object( ctx, GL_ARRAY_BUFFER_ARB, 0);
-   bind_buffer_object( ctx, GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
-   bind_buffer_object( ctx, GL_PIXEL_PACK_BUFFER_ARB, 0);
-   bind_buffer_object( ctx, GL_PIXEL_UNPACK_BUFFER_ARB, 0);
-}
-
-
-/**
- * When we're about to read pixel data out of a PBO (via glDrawPixels,
- * glTexImage, etc) or write data into a PBO (via glReadPixels,
- * glGetTexImage, etc) we call this function to check that we're not
- * going to read out of bounds.
- *
- * XXX This would also be a convenient time to check that the PBO isn't
- * currently mapped.  Whoever calls this function should check for that.
- * Remember, we can't use a PBO when it's mapped!
- *
- * If we're not using a PBO, this is a no-op.
- *
- * \param width  width of image to read/write
- * \param height  height of image to read/write
- * \param depth  depth of image to read/write
- * \param format  format of image to read/write
- * \param type  datatype of image to read/write
- * \param ptr  the user-provided pointer/offset
- * \return GL_TRUE if the PBO access is OK, GL_FALSE if the access would
- *         go out of bounds.
- */
-GLboolean
-_mesa_validate_pbo_access(GLuint dimensions,
-                          const struct gl_pixelstore_attrib *pack,
-                          GLsizei width, GLsizei height, GLsizei depth,
-                          GLenum format, GLenum type, const GLvoid *ptr)
-{
-   GLvoid *start, *end;
-   const GLubyte *sizeAddr; /* buffer size, cast to a pointer */
-
-   if (!_mesa_is_bufferobj(pack->BufferObj))
-      return GL_TRUE;  /* no PBO, OK */
-
-   if (pack->BufferObj->Size == 0)
-      /* no buffer! */
-      return GL_FALSE;
-
-   /* get address of first pixel we'll read */
-   start = _mesa_image_address(dimensions, pack, ptr, width, height,
-                               format, type, 0, 0, 0);
-
-   /* get address just past the last pixel we'll read */
-   end =  _mesa_image_address(dimensions, pack, ptr, width, height,
-                              format, type, depth-1, height-1, width);
-
-
-   sizeAddr = ((const GLubyte *) 0) + pack->BufferObj->Size;
-
-   if ((const GLubyte *) start > sizeAddr) {
-      /* This will catch negative values / wrap-around */
-      return GL_FALSE;
-   }
-   if ((const GLubyte *) end > sizeAddr) {
-      /* Image read goes beyond end of buffer */
-      return GL_FALSE;
-   }
-
-   /* OK! */
-   return GL_TRUE;
-}
-
-
-/**
- * For commands that read from a PBO (glDrawPixels, glTexImage,
- * glPolygonStipple, etc), if we're reading from a PBO, map it read-only
- * and return the pointer into the PBO.  If we're not reading from a
- * PBO, return \p src as-is.
- * If non-null return, must call _mesa_unmap_pbo_source() when done.
- *
- * \return NULL if error, else pointer to start of data
- */
-const GLvoid *
-_mesa_map_pbo_source(struct gl_context *ctx,
-                     const struct gl_pixelstore_attrib *unpack,
-                     const GLvoid *src)
-{
-   const GLubyte *buf;
-
-   if (_mesa_is_bufferobj(unpack->BufferObj)) {
-      /* unpack from PBO */
-      buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
-                                              GL_READ_ONLY_ARB,
-                                              unpack->BufferObj);
-      if (!buf)
-         return NULL;
-
-      buf = ADD_POINTERS(buf, src);
-   }
-   else {
-      /* unpack from normal memory */
-      buf = src;
-   }
-
-   return buf;
-}
-
-
-/**
- * Combine PBO-read validation and mapping.
- * If any GL errors are detected, they'll be recorded and NULL returned.
- * \sa _mesa_validate_pbo_access
- * \sa _mesa_map_pbo_source
- * A call to this function should have a matching call to
- * _mesa_unmap_pbo_source().
- */
-const GLvoid *
-_mesa_map_validate_pbo_source(struct gl_context *ctx,
-                              GLuint dimensions,
-                              const struct gl_pixelstore_attrib *unpack,
-                              GLsizei width, GLsizei height, GLsizei depth,
-                              GLenum format, GLenum type, const GLvoid *ptr,
-                              const char *where)
-{
-   ASSERT(dimensions == 1 || dimensions == 2 || dimensions == 3);
-
-   if (!_mesa_is_bufferobj(unpack->BufferObj)) {
-      /* non-PBO access: no validation to be done */
-      return ptr;
-   }
-
-   if (!_mesa_validate_pbo_access(dimensions, unpack,
-                                  width, height, depth, format, type, ptr)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "%s(out of bounds PBO access)", where);
-      return NULL;
-   }
-
-   if (_mesa_bufferobj_mapped(unpack->BufferObj)) {
-      /* buffer is already mapped - that's an error */
-      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", where);
-      return NULL;
-   }
-
-   ptr = _mesa_map_pbo_source(ctx, unpack, ptr);
-   return ptr;
-}
-
-
-/**
- * Counterpart to _mesa_map_pbo_source()
- */
-void
-_mesa_unmap_pbo_source(struct gl_context *ctx,
-                       const struct gl_pixelstore_attrib *unpack)
-{
-   ASSERT(unpack != &ctx->Pack); /* catch pack/unpack mismatch */
-   if (_mesa_is_bufferobj(unpack->BufferObj)) {
-      ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
-                              unpack->BufferObj);
-   }
-}
-
-
-/**
- * For commands that write to a PBO (glReadPixels, glGetColorTable, etc),
- * if we're writing to a PBO, map it write-only and return the pointer
- * into the PBO.  If we're not writing to a PBO, return \p dst as-is.
- * If non-null return, must call _mesa_unmap_pbo_dest() when done.
- *
- * \return NULL if error, else pointer to start of data
- */
-void *
-_mesa_map_pbo_dest(struct gl_context *ctx,
-                   const struct gl_pixelstore_attrib *pack,
-                   GLvoid *dest)
-{
-   void *buf;
-
-   if (_mesa_is_bufferobj(pack->BufferObj)) {
-      /* pack into PBO */
-      buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
-                                              GL_WRITE_ONLY_ARB,
-                                              pack->BufferObj);
-      if (!buf)
-         return NULL;
-
-      buf = ADD_POINTERS(buf, dest);
-   }
-   else {
-      /* pack to normal memory */
-      buf = dest;
-   }
-
-   return buf;
-}
-
-
-/**
- * Combine PBO-write validation and mapping.
- * If any GL errors are detected, they'll be recorded and NULL returned.
- * \sa _mesa_validate_pbo_access
- * \sa _mesa_map_pbo_dest
- * A call to this function should have a matching call to
- * _mesa_unmap_pbo_dest().
- */
-GLvoid *
-_mesa_map_validate_pbo_dest(struct gl_context *ctx,
-                            GLuint dimensions,
-                            const struct gl_pixelstore_attrib *unpack,
-                            GLsizei width, GLsizei height, GLsizei depth,
-                            GLenum format, GLenum type, GLvoid *ptr,
-                            const char *where)
-{
-   ASSERT(dimensions == 1 || dimensions == 2 || dimensions == 3);
-
-   if (!_mesa_is_bufferobj(unpack->BufferObj)) {
-      /* non-PBO access: no validation to be done */
-      return ptr;
-   }
-
-   if (!_mesa_validate_pbo_access(dimensions, unpack,
-                                  width, height, depth, format, type, ptr)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "%s(out of bounds PBO access)", where);
-      return NULL;
-   }
-
-   if (_mesa_bufferobj_mapped(unpack->BufferObj)) {
-      /* buffer is already mapped - that's an error */
-      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", where);
-      return NULL;
-   }
-
-   ptr = _mesa_map_pbo_dest(ctx, unpack, ptr);
-   return ptr;
-}
-
-
-/**
- * Counterpart to _mesa_map_pbo_dest()
- */
-void
-_mesa_unmap_pbo_dest(struct gl_context *ctx,
-                     const struct gl_pixelstore_attrib *pack)
-{
-   ASSERT(pack != &ctx->Unpack); /* catch pack/unpack mismatch */
-   if (_mesa_is_bufferobj(pack->BufferObj)) {
-      ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, pack->BufferObj);
-   }
-}
-
-
-
-/**
- * Return the gl_buffer_object for the given ID.
- * Always return NULL for ID 0.
- */
-struct gl_buffer_object *
-_mesa_lookup_bufferobj(struct gl_context *ctx, GLuint buffer)
-{
-   if (buffer == 0)
-      return NULL;
-   else
-      return (struct gl_buffer_object *)
-         _mesa_HashLookup(ctx->Shared->BufferObjects, buffer);
-}
-
-
-/**
- * If *ptr points to obj, set ptr = the Null/default buffer object.
- * This is a helper for buffer object deletion.
- * The GL spec says that deleting a buffer object causes it to get
- * unbound from all arrays in the current context.
- */
-static void
-unbind(struct gl_context *ctx,
-       struct gl_buffer_object **ptr,
-       struct gl_buffer_object *obj)
-{
-   if (*ptr == obj) {
-      _mesa_reference_buffer_object(ctx, ptr, ctx->Shared->NullBufferObj);
-   }
-}
-
-
-/**
- * Plug default/fallback buffer object functions into the device
- * driver hooks.
- */
-void
-_mesa_init_buffer_object_functions(struct dd_function_table *driver)
-{
-   /* GL_ARB_vertex/pixel_buffer_object */
-   driver->NewBufferObject = _mesa_new_buffer_object;
-   driver->DeleteBuffer = _mesa_delete_buffer_object;
-   driver->BindBuffer = NULL;
-   driver->BufferData = _mesa_buffer_data;
-   driver->BufferSubData = _mesa_buffer_subdata;
-   driver->GetBufferSubData = _mesa_buffer_get_subdata;
-   driver->MapBuffer = _mesa_buffer_map;
-   driver->UnmapBuffer = _mesa_buffer_unmap;
-
-   /* GL_ARB_map_buffer_range */
-   driver->MapBufferRange = _mesa_buffer_map_range;
-   driver->FlushMappedBufferRange = _mesa_buffer_flush_mapped_range;
-
-   /* GL_ARB_copy_buffer */
-   driver->CopyBufferSubData = _mesa_copy_buffer_subdata;
-}
-
-
-
-/**********************************************************************/
-/* API Functions                                                      */
-/**********************************************************************/
-
-void GLAPIENTRY
-_mesa_BindBufferARB(GLenum target, GLuint buffer)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   bind_buffer_object(ctx, target, buffer);
-}
-
-
-/**
- * Delete a set of buffer objects.
- * 
- * \param n      Number of buffer objects to delete.
- * \param ids    Array of \c n buffer object IDs.
- */
-void GLAPIENTRY
-_mesa_DeleteBuffersARB(GLsizei n, const GLuint *ids)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   GLsizei i;
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   if (n < 0) {
-      _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteBuffersARB(n)");
-      return;
-   }
-
-   _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
-
-   for (i = 0; i < n; i++) {
-      struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, ids[i]);
-      if (bufObj) {
-         struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
-         GLuint j;
-
-         ASSERT(bufObj->Name == ids[i] || bufObj == &DummyBufferObject);
-
-         if (_mesa_bufferobj_mapped(bufObj)) {
-            /* if mapped, unmap it now */
-            ctx->Driver.UnmapBuffer(ctx, 0, bufObj);
-            bufObj->AccessFlags = DEFAULT_ACCESS;
-            bufObj->Pointer = NULL;
-         }
-
-         /* unbind any vertex pointers bound to this buffer */
-         unbind(ctx, &arrayObj->Vertex.BufferObj, bufObj);
-         unbind(ctx, &arrayObj->Weight.BufferObj, bufObj);
-         unbind(ctx, &arrayObj->Normal.BufferObj, bufObj);
-         unbind(ctx, &arrayObj->Color.BufferObj, bufObj);
-         unbind(ctx, &arrayObj->SecondaryColor.BufferObj, bufObj);
-         unbind(ctx, &arrayObj->FogCoord.BufferObj, bufObj);
-         unbind(ctx, &arrayObj->Index.BufferObj, bufObj);
-         unbind(ctx, &arrayObj->EdgeFlag.BufferObj, bufObj);
-         for (j = 0; j < Elements(arrayObj->TexCoord); j++) {
-            unbind(ctx, &arrayObj->TexCoord[j].BufferObj, bufObj);
-         }
-         for (j = 0; j < Elements(arrayObj->VertexAttrib); j++) {
-            unbind(ctx, &arrayObj->VertexAttrib[j].BufferObj, bufObj);
-         }
-
-         if (ctx->Array.ArrayBufferObj == bufObj) {
-            _mesa_BindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
-         }
-         if (ctx->Array.ElementArrayBufferObj == bufObj) {
-            _mesa_BindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 0 );
-         }
-
-         /* unbind any pixel pack/unpack pointers bound to this buffer */
-         if (ctx->Pack.BufferObj == bufObj) {
-            _mesa_BindBufferARB( GL_PIXEL_PACK_BUFFER_EXT, 0 );
-         }
-         if (ctx->Unpack.BufferObj == bufObj) {
-            _mesa_BindBufferARB( GL_PIXEL_UNPACK_BUFFER_EXT, 0 );
-         }
-
-         /* The ID is immediately freed for re-use */
-         _mesa_HashRemove(ctx->Shared->BufferObjects, ids[i]);
-         _mesa_reference_buffer_object(ctx, &bufObj, NULL);
-      }
-   }
-
-   _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
-}
-
-
-/**
- * Generate a set of unique buffer object IDs and store them in \c buffer.
- * 
- * \param n       Number of IDs to generate.
- * \param buffer  Array of \c n locations to store the IDs.
- */
-void GLAPIENTRY
-_mesa_GenBuffersARB(GLsizei n, GLuint *buffer)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   GLuint first;
-   GLint i;
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   if (n < 0) {
-      _mesa_error(ctx, GL_INVALID_VALUE, "glGenBuffersARB");
-      return;
-   }
-
-   if (!buffer) {
-      return;
-   }
-
-   /*
-    * This must be atomic (generation and allocation of buffer object IDs)
-    */
-   _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
-
-   first = _mesa_HashFindFreeKeyBlock(ctx->Shared->BufferObjects, n);
-
-   /* Insert the ID and pointer to dummy buffer object into hash table */
-   for (i = 0; i < n; i++) {
-      _mesa_HashInsert(ctx->Shared->BufferObjects, first + i,
-                       &DummyBufferObject);
-      buffer[i] = first + i;
-   }
-
-   _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
-}
-
-
-/**
- * Determine if ID is the name of a buffer object.
- * 
- * \param id  ID of the potential buffer object.
- * \return  \c GL_TRUE if \c id is the name of a buffer object, 
- *          \c GL_FALSE otherwise.
- */
-GLboolean GLAPIENTRY
-_mesa_IsBufferARB(GLuint id)
-{
-   struct gl_buffer_object *bufObj;
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
-
-   _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
-   bufObj = _mesa_lookup_bufferobj(ctx, id);
-   _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
-
-   return bufObj && bufObj != &DummyBufferObject;
-}
-
-
-void GLAPIENTRY
-_mesa_BufferDataARB(GLenum target, GLsizeiptrARB size,
-                    const GLvoid * data, GLenum usage)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   struct gl_buffer_object *bufObj;
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   if (size < 0) {
-      _mesa_error(ctx, GL_INVALID_VALUE, "glBufferDataARB(size < 0)");
-      return;
-   }
-
-   switch (usage) {
-   case GL_STREAM_DRAW_ARB:
-   case GL_STREAM_READ_ARB:
-   case GL_STREAM_COPY_ARB:
-   case GL_STATIC_DRAW_ARB:
-   case GL_STATIC_READ_ARB:
-   case GL_STATIC_COPY_ARB:
-   case GL_DYNAMIC_DRAW_ARB:
-   case GL_DYNAMIC_READ_ARB:
-   case GL_DYNAMIC_COPY_ARB:
-      /* OK */
-      break;
-   default:
-      _mesa_error(ctx, GL_INVALID_ENUM, "glBufferDataARB(usage)");
-      return;
-   }
-
-   bufObj = get_buffer(ctx, target);
-   if (!bufObj) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glBufferDataARB(target)" );
-      return;
-   }
-   if (!_mesa_is_bufferobj(bufObj)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "glBufferDataARB(buffer 0)" );
-      return;
-   }
-   
-   if (_mesa_bufferobj_mapped(bufObj)) {
-      /* Unmap the existing buffer.  We'll replace it now.  Not an error. */
-      ctx->Driver.UnmapBuffer(ctx, target, bufObj);
-      bufObj->AccessFlags = DEFAULT_ACCESS;
-      ASSERT(bufObj->Pointer == NULL);
-   }  
-
-   FLUSH_VERTICES(ctx, _NEW_BUFFER_OBJECT);
-
-   bufObj->Written = GL_TRUE;
-
-#ifdef VBO_DEBUG
-   printf("glBufferDataARB(%u, sz %ld, from %p, usage 0x%x)\n",
-                bufObj->Name, size, data, usage);
-#endif
-
-#ifdef BOUNDS_CHECK
-   size += 100;
-#endif
-
-   ASSERT(ctx->Driver.BufferData);
-   if (!ctx->Driver.BufferData( ctx, target, size, data, usage, bufObj )) {
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBufferDataARB()");
-   }
-}
-
-
-void GLAPIENTRY
-_mesa_BufferSubDataARB(GLenum target, GLintptrARB offset,
-                       GLsizeiptrARB size, const GLvoid * data)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   struct gl_buffer_object *bufObj;
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   bufObj = buffer_object_subdata_range_good( ctx, target, offset, size,
-                                              "glBufferSubDataARB" );
-   if (!bufObj) {
-      /* error already recorded */
-      return;
-   }
-
-   if (size == 0)
-      return;
-
-   bufObj->Written = GL_TRUE;
-
-   ASSERT(ctx->Driver.BufferSubData);
-   ctx->Driver.BufferSubData( ctx, target, offset, size, data, bufObj );
-}
-
-
-void GLAPIENTRY
-_mesa_GetBufferSubDataARB(GLenum target, GLintptrARB offset,
-                          GLsizeiptrARB size, void * data)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   struct gl_buffer_object *bufObj;
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   bufObj = buffer_object_subdata_range_good( ctx, target, offset, size,
-                                              "glGetBufferSubDataARB" );
-   if (!bufObj) {
-      /* error already recorded */
-      return;
-   }
-
-   ASSERT(ctx->Driver.GetBufferSubData);
-   ctx->Driver.GetBufferSubData( ctx, target, offset, size, data, bufObj );
-}
-
-
-void * GLAPIENTRY
-_mesa_MapBufferARB(GLenum target, GLenum access)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   struct gl_buffer_object * bufObj;
-   GLbitfield accessFlags;
-   void *map;
-
-   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL);
-
-   switch (access) {
-   case GL_READ_ONLY_ARB:
-      accessFlags = GL_MAP_READ_BIT;
-      break;
-   case GL_WRITE_ONLY_ARB:
-      accessFlags = GL_MAP_WRITE_BIT;
-      break;
-   case GL_READ_WRITE_ARB:
-      accessFlags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT;
-      break;
-   default:
-      _mesa_error(ctx, GL_INVALID_ENUM, "glMapBufferARB(access)");
-      return NULL;
-   }
-
-   bufObj = get_buffer(ctx, target);
-   if (!bufObj) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glMapBufferARB(target)" );
-      return NULL;
-   }
-   if (!_mesa_is_bufferobj(bufObj)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "glMapBufferARB(buffer 0)" );
-      return NULL;
-   }
-   if (_mesa_bufferobj_mapped(bufObj)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "glMapBufferARB(already mapped)");
-      return NULL;
-   }
-
-   ASSERT(ctx->Driver.MapBuffer);
-   map = ctx->Driver.MapBuffer( ctx, target, access, bufObj );
-   if (!map) {
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMapBufferARB(map failed)");
-      return NULL;
-   }
-   else {
-      /* The driver callback should have set these fields.
-       * This is important because other modules (like VBO) might call
-       * the driver function directly.
-       */
-      ASSERT(bufObj->Pointer == map);
-      ASSERT(bufObj->Length == bufObj->Size);
-      ASSERT(bufObj->Offset == 0);
-      bufObj->AccessFlags = accessFlags;
-   }
-
-   if (access == GL_WRITE_ONLY_ARB || access == GL_READ_WRITE_ARB)
-      bufObj->Written = GL_TRUE;
-
-#ifdef VBO_DEBUG
-   printf("glMapBufferARB(%u, sz %ld, access 0x%x)\n",
-	  bufObj->Name, bufObj->Size, access);
-   if (access == GL_WRITE_ONLY_ARB) {
-      GLuint i;
-      GLubyte *b = (GLubyte *) bufObj->Pointer;
-      for (i = 0; i < bufObj->Size; i++)
-         b[i] = i & 0xff;
-   }
-#endif
-
-#ifdef BOUNDS_CHECK
-   {
-      GLubyte *buf = (GLubyte *) bufObj->Pointer;
-      GLuint i;
-      /* buffer is 100 bytes larger than requested, fill with magic value */
-      for (i = 0; i < 100; i++) {
-         buf[bufObj->Size - i - 1] = 123;
-      }
-   }
-#endif
-
-   return bufObj->Pointer;
-}
-
-
-GLboolean GLAPIENTRY
-_mesa_UnmapBufferARB(GLenum target)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   struct gl_buffer_object *bufObj;
-   GLboolean status = GL_TRUE;
-   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
-
-   bufObj = get_buffer(ctx, target);
-   if (!bufObj) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glUnmapBufferARB(target)" );
-      return GL_FALSE;
-   }
-   if (!_mesa_is_bufferobj(bufObj)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "glUnmapBufferARB" );
-      return GL_FALSE;
-   }
-   if (!_mesa_bufferobj_mapped(bufObj)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "glUnmapBufferARB");
-      return GL_FALSE;
-   }
-
-#ifdef BOUNDS_CHECK
-   if (bufObj->Access != GL_READ_ONLY_ARB) {
-      GLubyte *buf = (GLubyte *) bufObj->Pointer;
-      GLuint i;
-      /* check that last 100 bytes are still = magic value */
-      for (i = 0; i < 100; i++) {
-         GLuint pos = bufObj->Size - i - 1;
-         if (buf[pos] != 123) {
-            _mesa_warning(ctx, "Out of bounds buffer object write detected"
-                          " at position %d (value = %u)\n",
-                          pos, buf[pos]);
-         }
-      }
-   }
-#endif
-
-#ifdef VBO_DEBUG
-   if (bufObj->AccessFlags & GL_MAP_WRITE_BIT) {
-      GLuint i, unchanged = 0;
-      GLubyte *b = (GLubyte *) bufObj->Pointer;
-      GLint pos = -1;
-      /* check which bytes changed */
-      for (i = 0; i < bufObj->Size - 1; i++) {
-         if (b[i] == (i & 0xff) && b[i+1] == ((i+1) & 0xff)) {
-            unchanged++;
-            if (pos == -1)
-               pos = i;
-         }
-      }
-      if (unchanged) {
-         printf("glUnmapBufferARB(%u): %u of %ld unchanged, starting at %d\n",
-                      bufObj->Name, unchanged, bufObj->Size, pos);
-      }
-   }
-#endif
-
-   status = ctx->Driver.UnmapBuffer( ctx, target, bufObj );
-   bufObj->AccessFlags = DEFAULT_ACCESS;
-   ASSERT(bufObj->Pointer == NULL);
-   ASSERT(bufObj->Offset == 0);
-   ASSERT(bufObj->Length == 0);
-
-   return status;
-}
-
-
-void GLAPIENTRY
-_mesa_GetBufferParameterivARB(GLenum target, GLenum pname, GLint *params)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   struct gl_buffer_object *bufObj;
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   bufObj = get_buffer(ctx, target);
-   if (!bufObj) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferParameterivARB(target)" );
-      return;
-   }
-   if (!_mesa_is_bufferobj(bufObj)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetBufferParameterivARB" );
-      return;
-   }
-
-   switch (pname) {
-   case GL_BUFFER_SIZE_ARB:
-      *params = (GLint) bufObj->Size;
-      return;
-   case GL_BUFFER_USAGE_ARB:
-      *params = bufObj->Usage;
-      return;
-   case GL_BUFFER_ACCESS_ARB:
-      *params = simplified_access_mode(bufObj->AccessFlags);
-      return;
-   case GL_BUFFER_MAPPED_ARB:
-      *params = _mesa_bufferobj_mapped(bufObj);
-      return;
-   case GL_BUFFER_ACCESS_FLAGS:
-      if (ctx->VersionMajor < 3)
-         goto invalid_pname;
-      *params = bufObj->AccessFlags;
-      return;
-   case GL_BUFFER_MAP_OFFSET:
-      if (ctx->VersionMajor < 3)
-         goto invalid_pname;
-      *params = (GLint) bufObj->Offset;
-      return;
-   case GL_BUFFER_MAP_LENGTH:
-      if (ctx->VersionMajor < 3)
-         goto invalid_pname;
-      *params = (GLint) bufObj->Length;
-      return;
-   default:
-      ; /* fall-through */
-   }
-
-invalid_pname:
-   _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferParameterivARB(pname=%s)",
-               _mesa_lookup_enum_by_nr(pname));
-}
-
-
-/**
- * New in GL 3.2
- * This is pretty much a duplicate of GetBufferParameteriv() but the
- * GL_BUFFER_SIZE_ARB attribute will be 64-bits on a 64-bit system.
- */
-void GLAPIENTRY
-_mesa_GetBufferParameteri64v(GLenum target, GLenum pname, GLint64 *params)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   struct gl_buffer_object *bufObj;
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   bufObj = get_buffer(ctx, target);
-   if (!bufObj) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferParameteri64v(target)" );
-      return;
-   }
-   if (!_mesa_is_bufferobj(bufObj)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetBufferParameteri64v" );
-      return;
-   }
-
-   switch (pname) {
-   case GL_BUFFER_SIZE_ARB:
-      *params = bufObj->Size;
-      return;
-   case GL_BUFFER_USAGE_ARB:
-      *params = bufObj->Usage;
-      return;
-   case GL_BUFFER_ACCESS_ARB:
-      *params = simplified_access_mode(bufObj->AccessFlags);
-      return;
-   case GL_BUFFER_ACCESS_FLAGS:
-      if (ctx->VersionMajor < 3)
-         goto invalid_pname;
-      *params = bufObj->AccessFlags;
-      return;
-   case GL_BUFFER_MAPPED_ARB:
-      *params = _mesa_bufferobj_mapped(bufObj);
-      return;
-   case GL_BUFFER_MAP_OFFSET:
-      if (ctx->VersionMajor < 3)
-         goto invalid_pname;
-      *params = bufObj->Offset;
-      return;
-   case GL_BUFFER_MAP_LENGTH:
-      if (ctx->VersionMajor < 3)
-         goto invalid_pname;
-      *params = bufObj->Length;
-      return;
-   default:
-      ; /* fall-through */
-   }
-
-invalid_pname:
-   _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferParameteri64v(pname=%s)",
-               _mesa_lookup_enum_by_nr(pname));
-}
-
-
-void GLAPIENTRY
-_mesa_GetBufferPointervARB(GLenum target, GLenum pname, GLvoid **params)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   struct gl_buffer_object * bufObj;
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   if (pname != GL_BUFFER_MAP_POINTER_ARB) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferPointervARB(pname)");
-      return;
-   }
-
-   bufObj = get_buffer(ctx, target);
-   if (!bufObj) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferPointervARB(target)" );
-      return;
-   }
-   if (!_mesa_is_bufferobj(bufObj)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetBufferPointervARB" );
-      return;
-   }
-
-   *params = bufObj->Pointer;
-}
-
-
-void GLAPIENTRY
-_mesa_CopyBufferSubData(GLenum readTarget, GLenum writeTarget,
-                        GLintptr readOffset, GLintptr writeOffset,
-                        GLsizeiptr size)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   struct gl_buffer_object *src, *dst;
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   src = get_buffer(ctx, readTarget);
-   if (!src || !_mesa_is_bufferobj(src)) {
-      _mesa_error(ctx, GL_INVALID_ENUM,
-                  "glCopyBuffserSubData(readTarget = 0x%x)", readTarget);
-      return;
-   }
-
-   dst = get_buffer(ctx, writeTarget);
-   if (!dst || !_mesa_is_bufferobj(dst)) {
-      _mesa_error(ctx, GL_INVALID_ENUM,
-                  "glCopyBuffserSubData(writeTarget = 0x%x)", writeTarget);
-      return;
-   }
-
-   if (_mesa_bufferobj_mapped(src)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glCopyBuffserSubData(readBuffer is mapped)");
-      return;
-   }
-
-   if (_mesa_bufferobj_mapped(dst)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glCopyBuffserSubData(writeBuffer is mapped)");
-      return;
-   }
-
-   if (readOffset < 0) {
-      _mesa_error(ctx, GL_INVALID_VALUE,
-                  "glCopyBuffserSubData(readOffset = %d)", (int) readOffset);
-      return;
-   }
-
-   if (writeOffset < 0) {
-      _mesa_error(ctx, GL_INVALID_VALUE,
-                  "glCopyBuffserSubData(writeOffset = %d)", (int) writeOffset);
-      return;
-   }
-
-   if (readOffset + size > src->Size) {
-      _mesa_error(ctx, GL_INVALID_VALUE,
-                  "glCopyBuffserSubData(readOffset + size = %d)",
-                  (int) (readOffset + size));
-      return;
-   }
-
-   if (writeOffset + size > dst->Size) {
-      _mesa_error(ctx, GL_INVALID_VALUE,
-                  "glCopyBuffserSubData(writeOffset + size = %d)",
-                  (int) (writeOffset + size));
-      return;
-   }
-
-   if (src == dst) {
-      if (readOffset + size <= writeOffset) {
-         /* OK */
-      }
-      else if (writeOffset + size <= readOffset) {
-         /* OK */
-      }
-      else {
-         /* overlapping src/dst is illegal */
-         _mesa_error(ctx, GL_INVALID_VALUE,
-                     "glCopyBuffserSubData(overlapping src/dst)");
-         return;
-      }
-   }
-
-   ctx->Driver.CopyBufferSubData(ctx, src, dst, readOffset, writeOffset, size);
-}
-
-
-/**
- * See GL_ARB_map_buffer_range spec
- */
-void * GLAPIENTRY
-_mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length,
-                     GLbitfield access)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   struct gl_buffer_object *bufObj;
-   void *map;
-
-   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL);
-
-   if (!ctx->Extensions.ARB_map_buffer_range) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glMapBufferRange(extension not supported)");
-      return NULL;
-   }
-
-   if (offset < 0) {
-      _mesa_error(ctx, GL_INVALID_VALUE,
-                  "glMapBufferRange(offset = %ld)", (long)offset);
-      return NULL;
-   }
-
-   if (length < 0) {
-      _mesa_error(ctx, GL_INVALID_VALUE,
-                  "glMapBufferRange(length = %ld)", (long)length);
-      return NULL;
-   }
-
-   if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glMapBufferRange(access indicates neither read or write)");
-      return NULL;
-   }
-
-   if (access & GL_MAP_READ_BIT) {
-      if ((access & GL_MAP_INVALIDATE_RANGE_BIT) ||
-          (access & GL_MAP_INVALIDATE_BUFFER_BIT) ||
-          (access & GL_MAP_UNSYNCHRONIZED_BIT)) {
-         _mesa_error(ctx, GL_INVALID_OPERATION,
-                     "glMapBufferRange(invalid access flags)");
-         return NULL;
-      }
-   }
-
-   if ((access & GL_MAP_FLUSH_EXPLICIT_BIT) &&
-       ((access & GL_MAP_WRITE_BIT) == 0)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glMapBufferRange(invalid access flags)");
-      return NULL;
-   }
-
-   bufObj = get_buffer(ctx, target);
-   if (!bufObj || !_mesa_is_bufferobj(bufObj)) {
-      _mesa_error(ctx, GL_INVALID_ENUM,
-                  "glMapBufferRange(target = 0x%x)", target);
-      return NULL;
-   }
-
-   if (offset + length > bufObj->Size) {
-      _mesa_error(ctx, GL_INVALID_VALUE,
-                  "glMapBufferRange(offset + length > size)");
-      return NULL;
-   }
-
-   if (_mesa_bufferobj_mapped(bufObj)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glMapBufferRange(buffer already mapped)");
-      return NULL;
-   }
-      
-   ASSERT(ctx->Driver.MapBufferRange);
-   map = ctx->Driver.MapBufferRange(ctx, target, offset, length,
-                                    access, bufObj);
-   if (!map) {
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMapBufferARB(map failed)");
-   }
-   else {
-      /* The driver callback should have set all these fields.
-       * This is important because other modules (like VBO) might call
-       * the driver function directly.
-       */
-      ASSERT(bufObj->Pointer == map);
-      ASSERT(bufObj->Length == length);
-      ASSERT(bufObj->Offset == offset);
-      ASSERT(bufObj->AccessFlags == access);
-   }
-
-   return map;
-}
-
-
-/**
- * See GL_ARB_map_buffer_range spec
- */
-void GLAPIENTRY
-_mesa_FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   struct gl_buffer_object *bufObj;
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   if (!ctx->Extensions.ARB_map_buffer_range) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glMapBufferRange(extension not supported)");
-      return;
-   }
-
-   if (offset < 0) {
-      _mesa_error(ctx, GL_INVALID_VALUE,
-                  "glMapBufferRange(offset = %ld)", (long)offset);
-      return;
-   }
-
-   if (length < 0) {
-      _mesa_error(ctx, GL_INVALID_VALUE,
-                  "glMapBufferRange(length = %ld)", (long)length);
-      return;
-   }
-
-   bufObj = get_buffer(ctx, target);
-   if (!bufObj) {
-      _mesa_error(ctx, GL_INVALID_ENUM,
-                  "glMapBufferRange(target = 0x%x)", target);
-      return;
-   }
-
-   if (!_mesa_is_bufferobj(bufObj)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glMapBufferRange(current buffer is 0)");
-      return;
-   }
-
-   if (!_mesa_bufferobj_mapped(bufObj)) {
-      /* buffer is not mapped */
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glMapBufferRange(buffer is not mapped)");
-      return;
-   }
-
-   if ((bufObj->AccessFlags & GL_MAP_FLUSH_EXPLICIT_BIT) == 0) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glMapBufferRange(GL_MAP_FLUSH_EXPLICIT_BIT not set)");
-      return;
-   }
-
-   if (offset + length > bufObj->Length) {
-      _mesa_error(ctx, GL_INVALID_VALUE,
-		  "glMapBufferRange(offset %ld + length %ld > mapped length %ld)",
-		  (long)offset, (long)length, (long)bufObj->Length);
-      return;
-   }
-
-   ASSERT(bufObj->AccessFlags & GL_MAP_WRITE_BIT);
-
-   if (ctx->Driver.FlushMappedBufferRange)
-      ctx->Driver.FlushMappedBufferRange(ctx, target, offset, length, bufObj);
-}
-
-
-#if FEATURE_APPLE_object_purgeable
-static GLenum
-_mesa_BufferObjectPurgeable(struct gl_context *ctx, GLuint name, GLenum option)
-{
-   struct gl_buffer_object *bufObj;
-   GLenum retval;
-
-   bufObj = _mesa_lookup_bufferobj(ctx, name);
-   if (!bufObj) {
-      _mesa_error(ctx, GL_INVALID_VALUE,
-                  "glObjectPurgeable(name = 0x%x)", name);
-      return 0;
-   }
-   if (!_mesa_is_bufferobj(bufObj)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "glObjectPurgeable(buffer 0)" );
-      return 0;
-   }
-
-   if (bufObj->Purgeable) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glObjectPurgeable(name = 0x%x) is already purgeable", name);
-      return GL_VOLATILE_APPLE;
-   }
-
-   bufObj->Purgeable = GL_TRUE;
-
-   retval = GL_VOLATILE_APPLE;
-   if (ctx->Driver.BufferObjectPurgeable)
-      retval = ctx->Driver.BufferObjectPurgeable(ctx, bufObj, option);
-
-   return retval;
-}
-
-
-static GLenum
-_mesa_RenderObjectPurgeable(struct gl_context *ctx, GLuint name, GLenum option)
-{
-   struct gl_renderbuffer *bufObj;
-   GLenum retval;
-
-   bufObj = _mesa_lookup_renderbuffer(ctx, name);
-   if (!bufObj) {
-      _mesa_error(ctx, GL_INVALID_VALUE,
-                  "glObjectUnpurgeable(name = 0x%x)", name);
-      return 0;
-   }
-
-   if (bufObj->Purgeable) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glObjectPurgeable(name = 0x%x) is already purgeable", name);
-      return GL_VOLATILE_APPLE;
-   }
-
-   bufObj->Purgeable = GL_TRUE;
-
-   retval = GL_VOLATILE_APPLE;
-   if (ctx->Driver.RenderObjectPurgeable)
-      retval = ctx->Driver.RenderObjectPurgeable(ctx, bufObj, option);
-
-   return retval;
-}
-
-
-static GLenum
-_mesa_TextureObjectPurgeable(struct gl_context *ctx, GLuint name, GLenum option)
-{
-   struct gl_texture_object *bufObj;
-   GLenum retval;
-
-   bufObj = _mesa_lookup_texture(ctx, name);
-   if (!bufObj) {
-      _mesa_error(ctx, GL_INVALID_VALUE,
-                  "glObjectPurgeable(name = 0x%x)", name);
-      return 0;
-   }
-
-   if (bufObj->Purgeable) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glObjectPurgeable(name = 0x%x) is already purgeable", name);
-      return GL_VOLATILE_APPLE;
-   }
-
-   bufObj->Purgeable = GL_TRUE;
-
-   retval = GL_VOLATILE_APPLE;
-   if (ctx->Driver.TextureObjectPurgeable)
-      retval = ctx->Driver.TextureObjectPurgeable(ctx, bufObj, option);
-
-   return retval;
-}
-
-
-GLenum GLAPIENTRY
-_mesa_ObjectPurgeableAPPLE(GLenum objectType, GLuint name, GLenum option)
-{
-   GLenum retval;
-
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
-
-   if (name == 0) {
-      _mesa_error(ctx, GL_INVALID_VALUE,
-                  "glObjectPurgeable(name = 0x%x)", name);
-      return 0;
-   }
-
-   switch (option) {
-   case GL_VOLATILE_APPLE:
-   case GL_RELEASED_APPLE:
-      /* legal */
-      break;
-   default:
-      _mesa_error(ctx, GL_INVALID_ENUM,
-                  "glObjectPurgeable(name = 0x%x) invalid option: %d",
-                  name, option);
-      return 0;
-   }
-
-   switch (objectType) {
-   case GL_TEXTURE:
-      retval = _mesa_TextureObjectPurgeable (ctx, name, option);
-      break;
-   case GL_RENDERBUFFER_EXT:
-      retval = _mesa_RenderObjectPurgeable (ctx, name, option);
-      break;
-   case GL_BUFFER_OBJECT_APPLE:
-      retval = _mesa_BufferObjectPurgeable (ctx, name, option);
-      break;
-   default:
-      _mesa_error(ctx, GL_INVALID_ENUM,
-                  "glObjectPurgeable(name = 0x%x) invalid type: %d",
-                  name, objectType);
-      return 0;
-   }
-
-   /* In strict conformance to the spec, we must only return VOLATILE when
-    * when passed the VOLATILE option. Madness.
-    *
-    * XXX First fix the spec, then fix me.
-    */
-   return option == GL_VOLATILE_APPLE ? GL_VOLATILE_APPLE : retval;
-}
-
-
-static GLenum
-_mesa_BufferObjectUnpurgeable(struct gl_context *ctx, GLuint name, GLenum option)
-{
-   struct gl_buffer_object *bufObj;
-   GLenum retval;
-
-   bufObj = _mesa_lookup_bufferobj(ctx, name);
-   if (!bufObj) {
-      _mesa_error(ctx, GL_INVALID_VALUE,
-                  "glObjectUnpurgeable(name = 0x%x)", name);
-      return 0;
-   }
-
-   if (! bufObj->Purgeable) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glObjectUnpurgeable(name = 0x%x) object is "
-                  " already \"unpurged\"", name);
-      return 0;
-   }
-
-   bufObj->Purgeable = GL_FALSE;
-
-   retval = option;
-   if (ctx->Driver.BufferObjectUnpurgeable)
-      retval = ctx->Driver.BufferObjectUnpurgeable(ctx, bufObj, option);
-
-   return retval;
-}
-
-
-static GLenum
-_mesa_RenderObjectUnpurgeable(struct gl_context *ctx, GLuint name, GLenum option)
-{
-   struct gl_renderbuffer *bufObj;
-   GLenum retval;
-
-   bufObj = _mesa_lookup_renderbuffer(ctx, name);
-   if (!bufObj) {
-      _mesa_error(ctx, GL_INVALID_VALUE,
-                  "glObjectUnpurgeable(name = 0x%x)", name);
-      return 0;
-   }
-
-   if (! bufObj->Purgeable) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glObjectUnpurgeable(name = 0x%x) object is "
-                  " already \"unpurged\"", name);
-      return 0;
-   }
-
-   bufObj->Purgeable = GL_FALSE;
-
-   retval = option;
-   if (ctx->Driver.RenderObjectUnpurgeable)
-      retval = ctx->Driver.RenderObjectUnpurgeable(ctx, bufObj, option);
-
-   return retval;
-}
-
-
-static GLenum
-_mesa_TextureObjectUnpurgeable(struct gl_context *ctx, GLuint name, GLenum option)
-{
-   struct gl_texture_object *bufObj;
-   GLenum retval;
-
-   bufObj = _mesa_lookup_texture(ctx, name);
-   if (!bufObj) {
-      _mesa_error(ctx, GL_INVALID_VALUE,
-                  "glObjectUnpurgeable(name = 0x%x)", name);
-      return 0;
-   }
-
-   if (! bufObj->Purgeable) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glObjectUnpurgeable(name = 0x%x) object is"
-                  " already \"unpurged\"", name);
-      return 0;
-   }
-
-   bufObj->Purgeable = GL_FALSE;
-
-   retval = option;
-   if (ctx->Driver.TextureObjectUnpurgeable)
-      retval = ctx->Driver.TextureObjectUnpurgeable(ctx, bufObj, option);
-
-   return retval;
-}
-
-
-GLenum GLAPIENTRY
-_mesa_ObjectUnpurgeableAPPLE(GLenum objectType, GLuint name, GLenum option)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
-
-   if (name == 0) {
-      _mesa_error(ctx, GL_INVALID_VALUE,
-                  "glObjectUnpurgeable(name = 0x%x)", name);
-      return 0;
-   }
-
-   switch (option) {
-   case GL_RETAINED_APPLE:
-   case GL_UNDEFINED_APPLE:
-      /* legal */
-      break;
-   default:
-      _mesa_error(ctx, GL_INVALID_ENUM,
-                  "glObjectUnpurgeable(name = 0x%x) invalid option: %d",
-                  name, option);
-      return 0;
-   }
-
-   switch (objectType) {
-   case GL_BUFFER_OBJECT_APPLE:
-      return _mesa_BufferObjectUnpurgeable(ctx, name, option);
-   case GL_TEXTURE:
-      return _mesa_TextureObjectUnpurgeable(ctx, name, option);
-   case GL_RENDERBUFFER_EXT:
-      return _mesa_RenderObjectUnpurgeable(ctx, name, option);
-   default:
-      _mesa_error(ctx, GL_INVALID_ENUM,
-                  "glObjectUnpurgeable(name = 0x%x) invalid type: %d",
-                  name, objectType);
-      return 0;
-   }
-}
-
-
-static void
-_mesa_GetBufferObjectParameterivAPPLE(struct gl_context *ctx, GLuint name,
-                                      GLenum pname, GLint* params)
-{
-   struct gl_buffer_object *bufObj;
-
-   bufObj = _mesa_lookup_bufferobj(ctx, name);
-   if (!bufObj) {
-      _mesa_error(ctx, GL_INVALID_VALUE,
-                  "glGetObjectParameteriv(name = 0x%x) invalid object", name);
-      return;
-   }
-
-   switch (pname) {
-   case GL_PURGEABLE_APPLE:
-      *params = bufObj->Purgeable;
-      break;
-   default:
-      _mesa_error(ctx, GL_INVALID_ENUM,
-                  "glGetObjectParameteriv(name = 0x%x) invalid enum: %d",
-                  name, pname);
-      break;
-   }
-}
-
-
-static void
-_mesa_GetRenderObjectParameterivAPPLE(struct gl_context *ctx, GLuint name,
-                                      GLenum pname, GLint* params)
-{
-   struct gl_renderbuffer *bufObj;
-
-   bufObj = _mesa_lookup_renderbuffer(ctx, name);
-   if (!bufObj) {
-      _mesa_error(ctx, GL_INVALID_VALUE,
-                  "glObjectUnpurgeable(name = 0x%x)", name);
-      return;
-   }
-
-   switch (pname) {
-   case GL_PURGEABLE_APPLE:
-      *params = bufObj->Purgeable;
-      break;
-   default:
-      _mesa_error(ctx, GL_INVALID_ENUM,
-                  "glGetObjectParameteriv(name = 0x%x) invalid enum: %d",
-                  name, pname);
-      break;
-   }
-}
-
-
-static void
-_mesa_GetTextureObjectParameterivAPPLE(struct gl_context *ctx, GLuint name,
-                                       GLenum pname, GLint* params)
-{
-   struct gl_texture_object *bufObj;
-
-   bufObj = _mesa_lookup_texture(ctx, name);
-   if (!bufObj) {
-      _mesa_error(ctx, GL_INVALID_VALUE,
-                  "glObjectUnpurgeable(name = 0x%x)", name);
-      return;
-   }
-
-   switch (pname) {
-   case GL_PURGEABLE_APPLE:
-      *params = bufObj->Purgeable;
-      break;
-   default:
-      _mesa_error(ctx, GL_INVALID_ENUM,
-                  "glGetObjectParameteriv(name = 0x%x) invalid enum: %d",
-                  name, pname);
-      break;
-   }
-}
-
-
-void GLAPIENTRY
-_mesa_GetObjectParameterivAPPLE(GLenum objectType, GLuint name, GLenum pname,
-                                GLint* params)
-{
-   GET_CURRENT_CONTEXT(ctx);
-
-   if (name == 0) {
-      _mesa_error(ctx, GL_INVALID_VALUE,
-                  "glGetObjectParameteriv(name = 0x%x)", name);
-      return;
-   }
-
-   switch (objectType) {
-   case GL_TEXTURE:
-      _mesa_GetTextureObjectParameterivAPPLE (ctx, name, pname, params);
-      break;
-   case GL_BUFFER_OBJECT_APPLE:
-      _mesa_GetBufferObjectParameterivAPPLE (ctx, name, pname, params);
-      break;
-   case GL_RENDERBUFFER_EXT:
-      _mesa_GetRenderObjectParameterivAPPLE (ctx, name, pname, params);
-      break;
-   default:
-      _mesa_error(ctx, GL_INVALID_ENUM,
-                  "glGetObjectParameteriv(name = 0x%x) invalid type: %d",
-                  name, objectType);
-   }
-}
-
-#endif /* FEATURE_APPLE_object_purgeable */
+/*
+ * Mesa 3-D graphics library
+ * Version:  7.6
+ *
+ * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
+ * Copyright (C) 2009  VMware, Inc.  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"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+/**
+ * \file bufferobj.c
+ * \brief Functions for the GL_ARB_vertex/pixel_buffer_object extensions.
+ * \author Brian Paul, Ian Romanick
+ */
+
+
+#include "glheader.h"
+#include "enums.h"
+#include "hash.h"
+#include "imports.h"
+#include "image.h"
+#include "context.h"
+#include "bufferobj.h"
+#include "fbobject.h"
+#include "mfeatures.h"
+#include "mtypes.h"
+#include "texobj.h"
+
+
+/* Debug flags */
+/*#define VBO_DEBUG*/
+/*#define BOUNDS_CHECK*/
+
+
+#if FEATURE_OES_mapbuffer
+#define DEFAULT_ACCESS GL_MAP_WRITE_BIT
+#else
+#define DEFAULT_ACCESS (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)
+#endif
+
+
+/**
+ * Used as a placeholder for buffer objects between glGenBuffers() and
+ * glBindBuffer() so that glIsBuffer() can work correctly.
+ */
+static struct gl_buffer_object DummyBufferObject;
+
+
+/**
+ * Return pointer to address of a buffer object target.
+ * \param ctx  the GL context
+ * \param target  the buffer object target to be retrieved.
+ * \return   pointer to pointer to the buffer object bound to \c target in the
+ *           specified context or \c NULL if \c target is invalid.
+ */
+static INLINE struct gl_buffer_object **
+get_buffer_target(struct gl_context *ctx, GLenum target)
+{
+   switch (target) {
+   case GL_ARRAY_BUFFER_ARB:
+      return &ctx->Array.ArrayBufferObj;
+   case GL_ELEMENT_ARRAY_BUFFER_ARB:
+      return &ctx->Array.ElementArrayBufferObj;
+   case GL_PIXEL_PACK_BUFFER_EXT:
+      return &ctx->Pack.BufferObj;
+   case GL_PIXEL_UNPACK_BUFFER_EXT:
+      return &ctx->Unpack.BufferObj;
+   case GL_COPY_READ_BUFFER:
+      return &ctx->CopyReadBuffer;
+   case GL_COPY_WRITE_BUFFER:
+      return &ctx->CopyWriteBuffer;
+#if FEATURE_EXT_transform_feedback
+   case GL_TRANSFORM_FEEDBACK_BUFFER:
+      if (ctx->Extensions.EXT_transform_feedback) {
+         return &ctx->TransformFeedback.CurrentBuffer;
+      }
+      break;
+#endif
+   default:
+      return NULL;
+   }
+   return NULL;
+}
+
+
+/**
+ * Get the buffer object bound to the specified target in a GL context.
+ * \param ctx  the GL context
+ * \param target  the buffer object target to be retrieved.
+ * \return   pointer to the buffer object bound to \c target in the
+ *           specified context or \c NULL if \c target is invalid.
+ */
+static INLINE struct gl_buffer_object *
+get_buffer(struct gl_context *ctx, GLenum target)
+{
+   struct gl_buffer_object **bufObj = get_buffer_target(ctx, target);
+   if (bufObj)
+      return *bufObj;
+   return NULL;
+}
+
+
+/**
+ * Convert a GLbitfield describing the mapped buffer access flags
+ * into one of GL_READ_WRITE, GL_READ_ONLY, or GL_WRITE_ONLY.
+ */
+static GLenum
+simplified_access_mode(GLbitfield access)
+{
+   const GLbitfield rwFlags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT;
+   if ((access & rwFlags) == rwFlags)
+      return GL_READ_WRITE;
+   if ((access & GL_MAP_READ_BIT) == GL_MAP_READ_BIT)
+      return GL_READ_ONLY;
+   if ((access & GL_MAP_WRITE_BIT) == GL_MAP_WRITE_BIT)
+      return GL_WRITE_ONLY;
+   return GL_READ_WRITE; /* this should never happen, but no big deal */
+}
+
+
+/**
+ * Tests the subdata range parameters and sets the GL error code for
+ * \c glBufferSubDataARB and \c glGetBufferSubDataARB.
+ *
+ * \param ctx     GL context.
+ * \param target  Buffer object target on which to operate.
+ * \param offset  Offset of the first byte of the subdata range.
+ * \param size    Size, in bytes, of the subdata range.
+ * \param caller  Name of calling function for recording errors.
+ * \return   A pointer to the buffer object bound to \c target in the
+ *           specified context or \c NULL if any of the parameter or state
+ *           conditions for \c glBufferSubDataARB or \c glGetBufferSubDataARB
+ *           are invalid.
+ *
+ * \sa glBufferSubDataARB, glGetBufferSubDataARB
+ */
+static struct gl_buffer_object *
+buffer_object_subdata_range_good( struct gl_context * ctx, GLenum target, 
+                                  GLintptrARB offset, GLsizeiptrARB size,
+                                  const char *caller )
+{
+   struct gl_buffer_object *bufObj;
+
+   if (size < 0) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "%s(size < 0)", caller);
+      return NULL;
+   }
+
+   if (offset < 0) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "%s(offset < 0)", caller);
+      return NULL;
+   }
+
+   bufObj = get_buffer(ctx, target);
+   if (!bufObj) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", caller);
+      return NULL;
+   }
+   if (!_mesa_is_bufferobj(bufObj)) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller);
+      return NULL;
+   }
+   if (offset + size > bufObj->Size) {
+      _mesa_error(ctx, GL_INVALID_VALUE,
+		  "%s(size + offset > buffer size)", caller);
+      return NULL;
+   }
+   if (_mesa_bufferobj_mapped(bufObj)) {
+      /* Buffer is currently mapped */
+      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller);
+      return NULL;
+   }
+
+   return bufObj;
+}
+
+
+/**
+ * Allocate and initialize a new buffer object.
+ * 
+ * Default callback for the \c dd_function_table::NewBufferObject() hook.
+ */
+static struct gl_buffer_object *
+_mesa_new_buffer_object( struct gl_context *ctx, GLuint name, GLenum target )
+{
+   struct gl_buffer_object *obj;
+
+   (void) ctx;
+
+   obj = MALLOC_STRUCT(gl_buffer_object);
+   _mesa_initialize_buffer_object(obj, name, target);
+   return obj;
+}
+
+
+/**
+ * Delete a buffer object.
+ * 
+ * Default callback for the \c dd_function_table::DeleteBuffer() hook.
+ */
+static void
+_mesa_delete_buffer_object( struct gl_context *ctx, struct gl_buffer_object *bufObj )
+{
+   (void) ctx;
+
+   if (bufObj->Data)
+      free(bufObj->Data);
+
+   /* assign strange values here to help w/ debugging */
+   bufObj->RefCount = -1000;
+   bufObj->Name = ~0;
+
+   _glthread_DESTROY_MUTEX(bufObj->Mutex);
+   free(bufObj);
+}
+
+
+
+/**
+ * Set ptr to bufObj w/ reference counting.
+ */
+void
+_mesa_reference_buffer_object(struct gl_context *ctx,
+                              struct gl_buffer_object **ptr,
+                              struct gl_buffer_object *bufObj)
+{
+   if (*ptr == bufObj)
+      return;
+
+   if (*ptr) {
+      /* Unreference the old buffer */
+      GLboolean deleteFlag = GL_FALSE;
+      struct gl_buffer_object *oldObj = *ptr;
+
+      _glthread_LOCK_MUTEX(oldObj->Mutex);
+      ASSERT(oldObj->RefCount > 0);
+      oldObj->RefCount--;
+#if 0
+      printf("BufferObj %p %d DECR to %d\n",
+             (void *) oldObj, oldObj->Name, oldObj->RefCount);
+#endif
+      deleteFlag = (oldObj->RefCount == 0);
+      _glthread_UNLOCK_MUTEX(oldObj->Mutex);
+
+      if (deleteFlag) {
+
+         /* some sanity checking: don't delete a buffer still in use */
+#if 0
+         /* unfortunately, these tests are invalid during context tear-down */
+	 ASSERT(ctx->Array.ArrayBufferObj != bufObj);
+	 ASSERT(ctx->Array.ElementArrayBufferObj != bufObj);
+	 ASSERT(ctx->Array.ArrayObj->Vertex.BufferObj != bufObj);
+#endif
+
+	 ASSERT(ctx->Driver.DeleteBuffer);
+         ctx->Driver.DeleteBuffer(ctx, oldObj);
+      }
+
+      *ptr = NULL;
+   }
+   ASSERT(!*ptr);
+
+   if (bufObj) {
+      /* reference new buffer */
+      _glthread_LOCK_MUTEX(bufObj->Mutex);
+      if (bufObj->RefCount == 0) {
+         /* this buffer's being deleted (look just above) */
+         /* Not sure this can every really happen.  Warn if it does. */
+         _mesa_problem(NULL, "referencing deleted buffer object");
+         *ptr = NULL;
+      }
+      else {
+         bufObj->RefCount++;
+#if 0
+         printf("BufferObj %p %d INCR to %d\n",
+                (void *) bufObj, bufObj->Name, bufObj->RefCount);
+#endif
+         *ptr = bufObj;
+      }
+      _glthread_UNLOCK_MUTEX(bufObj->Mutex);
+   }
+}
+
+
+/**
+ * Initialize a buffer object to default values.
+ */
+void
+_mesa_initialize_buffer_object( struct gl_buffer_object *obj,
+				GLuint name, GLenum target )
+{
+   (void) target;
+
+   memset(obj, 0, sizeof(struct gl_buffer_object));
+   _glthread_INIT_MUTEX(obj->Mutex);
+   obj->RefCount = 1;
+   obj->Name = name;
+   obj->Usage = GL_STATIC_DRAW_ARB;
+   obj->AccessFlags = DEFAULT_ACCESS;
+}
+
+
+/**
+ * Allocate space for and store data in a buffer object.  Any data that was
+ * previously stored in the buffer object is lost.  If \c data is \c NULL,
+ * memory will be allocated, but no copy will occur.
+ *
+ * This is the default callback for \c dd_function_table::BufferData()
+ * Note that all GL error checking will have been done already.
+ *
+ * \param ctx     GL context.
+ * \param target  Buffer object target on which to operate.
+ * \param size    Size, in bytes, of the new data store.
+ * \param data    Pointer to the data to store in the buffer object.  This
+ *                pointer may be \c NULL.
+ * \param usage   Hints about how the data will be used.
+ * \param bufObj  Object to be used.
+ *
+ * \return GL_TRUE for success, GL_FALSE for failure
+ * \sa glBufferDataARB, dd_function_table::BufferData.
+ */
+static GLboolean
+_mesa_buffer_data( struct gl_context *ctx, GLenum target, GLsizeiptrARB size,
+		   const GLvoid * data, GLenum usage,
+		   struct gl_buffer_object * bufObj )
+{
+   void * new_data;
+
+   (void) ctx; (void) target;
+
+   new_data = _mesa_realloc( bufObj->Data, bufObj->Size, size );
+   if (new_data) {
+      bufObj->Data = (GLubyte *) new_data;
+      bufObj->Size = size;
+      bufObj->Usage = usage;
+
+      if (data) {
+	 memcpy( bufObj->Data, data, size );
+      }
+
+      return GL_TRUE;
+   }
+   else {
+      return GL_FALSE;
+   }
+}
+
+
+/**
+ * Replace data in a subrange of buffer object.  If the data range
+ * specified by \c size + \c offset extends beyond the end of the buffer or
+ * if \c data is \c NULL, no copy is performed.
+ *
+ * This is the default callback for \c dd_function_table::BufferSubData()
+ * Note that all GL error checking will have been done already.
+ *
+ * \param ctx     GL context.
+ * \param target  Buffer object target on which to operate.
+ * \param offset  Offset of the first byte to be modified.
+ * \param size    Size, in bytes, of the data range.
+ * \param data    Pointer to the data to store in the buffer object.
+ * \param bufObj  Object to be used.
+ *
+ * \sa glBufferSubDataARB, dd_function_table::BufferSubData.
+ */
+static void
+_mesa_buffer_subdata( struct gl_context *ctx, GLenum target, GLintptrARB offset,
+		      GLsizeiptrARB size, const GLvoid * data,
+		      struct gl_buffer_object * bufObj )
+{
+   (void) ctx; (void) target;
+
+   /* this should have been caught in _mesa_BufferSubData() */
+   ASSERT(size + offset <= bufObj->Size);
+
+   if (bufObj->Data) {
+      memcpy( (GLubyte *) bufObj->Data + offset, data, size );
+   }
+}
+
+
+/**
+ * Retrieve data from a subrange of buffer object.  If the data range
+ * specified by \c size + \c offset extends beyond the end of the buffer or
+ * if \c data is \c NULL, no copy is performed.
+ *
+ * This is the default callback for \c dd_function_table::GetBufferSubData()
+ * Note that all GL error checking will have been done already.
+ *
+ * \param ctx     GL context.
+ * \param target  Buffer object target on which to operate.
+ * \param offset  Offset of the first byte to be fetched.
+ * \param size    Size, in bytes, of the data range.
+ * \param data    Destination for data
+ * \param bufObj  Object to be used.
+ *
+ * \sa glBufferGetSubDataARB, dd_function_table::GetBufferSubData.
+ */
+static void
+_mesa_buffer_get_subdata( struct gl_context *ctx, GLenum target, GLintptrARB offset,
+			  GLsizeiptrARB size, GLvoid * data,
+			  struct gl_buffer_object * bufObj )
+{
+   (void) ctx; (void) target;
+
+   if (bufObj->Data && ((GLsizeiptrARB) (size + offset) <= bufObj->Size)) {
+      memcpy( data, (GLubyte *) bufObj->Data + offset, size );
+   }
+}
+
+
+/**
+ * Default callback for \c dd_function_tabel::MapBuffer().
+ *
+ * The function parameters will have been already tested for errors.
+ *
+ * \param ctx     GL context.
+ * \param target  Buffer object target on which to operate.
+ * \param access  Information about how the buffer will be accessed.
+ * \param bufObj  Object to be mapped.
+ * \return  A pointer to the object's internal data store that can be accessed
+ *          by the processor
+ *
+ * \sa glMapBufferARB, dd_function_table::MapBuffer
+ */
+static void *
+_mesa_buffer_map( struct gl_context *ctx, GLenum target, GLenum access,
+		  struct gl_buffer_object *bufObj )
+{
+   (void) ctx;
+   (void) target;
+   (void) access;
+   /* Just return a direct pointer to the data */
+   if (_mesa_bufferobj_mapped(bufObj)) {
+      /* already mapped! */
+      return NULL;
+   }
+   bufObj->Pointer = bufObj->Data;
+   bufObj->Length = bufObj->Size;
+   bufObj->Offset = 0;
+   return bufObj->Pointer;
+}
+
+
+/**
+ * Default fallback for \c dd_function_table::MapBufferRange().
+ * Called via glMapBufferRange().
+ */
+static void *
+_mesa_buffer_map_range( struct gl_context *ctx, GLenum target, GLintptr offset,
+                        GLsizeiptr length, GLbitfield access,
+                        struct gl_buffer_object *bufObj )
+{
+   (void) ctx;
+   (void) target;
+   assert(!_mesa_bufferobj_mapped(bufObj));
+   /* Just return a direct pointer to the data */
+   bufObj->Pointer = bufObj->Data + offset;
+   bufObj->Length = length;
+   bufObj->Offset = offset;
+   bufObj->AccessFlags = access;
+   return bufObj->Pointer;
+}
+
+
+/**
+ * Default fallback for \c dd_function_table::FlushMappedBufferRange().
+ * Called via glFlushMappedBufferRange().
+ */
+static void
+_mesa_buffer_flush_mapped_range( struct gl_context *ctx, GLenum target, 
+                                 GLintptr offset, GLsizeiptr length,
+                                 struct gl_buffer_object *obj )
+{
+   (void) ctx;
+   (void) target;
+   (void) offset;
+   (void) length;
+   (void) obj;
+   /* no-op */
+}
+
+
+/**
+ * Default callback for \c dd_function_table::MapBuffer().
+ *
+ * The input parameters will have been already tested for errors.
+ *
+ * \sa glUnmapBufferARB, dd_function_table::UnmapBuffer
+ */
+static GLboolean
+_mesa_buffer_unmap( struct gl_context *ctx, GLenum target,
+                    struct gl_buffer_object *bufObj )
+{
+   (void) ctx;
+   (void) target;
+   /* XXX we might assert here that bufObj->Pointer is non-null */
+   bufObj->Pointer = NULL;
+   bufObj->Length = 0;
+   bufObj->Offset = 0;
+   bufObj->AccessFlags = 0x0;
+   return GL_TRUE;
+}
+
+
+/**
+ * Default fallback for \c dd_function_table::CopyBufferSubData().
+ * Called via glCopyBuffserSubData().
+ */
+static void
+_mesa_copy_buffer_subdata(struct gl_context *ctx,
+                          struct gl_buffer_object *src,
+                          struct gl_buffer_object *dst,
+                          GLintptr readOffset, GLintptr writeOffset,
+                          GLsizeiptr size)
+{
+   GLubyte *srcPtr, *dstPtr;
+
+   /* buffer should not already be mapped */
+   assert(!_mesa_bufferobj_mapped(src));
+   assert(!_mesa_bufferobj_mapped(dst));
+
+   srcPtr = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_COPY_READ_BUFFER,
+                                              GL_READ_ONLY, src);
+   dstPtr = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_COPY_WRITE_BUFFER,
+                                              GL_WRITE_ONLY, dst);
+
+   if (srcPtr && dstPtr)
+      memcpy(dstPtr + writeOffset, srcPtr + readOffset, size);
+
+   ctx->Driver.UnmapBuffer(ctx, GL_COPY_READ_BUFFER, src);
+   ctx->Driver.UnmapBuffer(ctx, GL_COPY_WRITE_BUFFER, dst);
+}
+
+
+
+/**
+ * Initialize the state associated with buffer objects
+ */
+void
+_mesa_init_buffer_objects( struct gl_context *ctx )
+{
+   memset(&DummyBufferObject, 0, sizeof(DummyBufferObject));
+   DummyBufferObject.RefCount = 1000*1000*1000; /* never delete */
+
+   _mesa_reference_buffer_object(ctx, &ctx->Array.ArrayBufferObj,
+                                 ctx->Shared->NullBufferObj);
+   _mesa_reference_buffer_object(ctx, &ctx->Array.ElementArrayBufferObj,
+                                 ctx->Shared->NullBufferObj);
+
+   _mesa_reference_buffer_object(ctx, &ctx->CopyReadBuffer,
+                                 ctx->Shared->NullBufferObj);
+   _mesa_reference_buffer_object(ctx, &ctx->CopyWriteBuffer,
+                                 ctx->Shared->NullBufferObj);
+}
+
+
+void
+_mesa_free_buffer_objects( struct gl_context *ctx )
+{
+   _mesa_reference_buffer_object(ctx, &ctx->Array.ArrayBufferObj, NULL);
+   _mesa_reference_buffer_object(ctx, &ctx->Array.ElementArrayBufferObj, NULL);
+
+   _mesa_reference_buffer_object(ctx, &ctx->CopyReadBuffer, NULL);
+   _mesa_reference_buffer_object(ctx, &ctx->CopyWriteBuffer, NULL);
+}
+
+
+/**
+ * Bind the specified target to buffer for the specified context.
+ * Called by glBindBuffer() and other functions.
+ */
+static void
+bind_buffer_object(struct gl_context *ctx, GLenum target, GLuint buffer)
+{
+   struct gl_buffer_object *oldBufObj;
+   struct gl_buffer_object *newBufObj = NULL;
+   struct gl_buffer_object **bindTarget = NULL;
+
+   bindTarget = get_buffer_target(ctx, target);
+   if (!bindTarget) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferARB(target 0x%x)", target);
+      return;
+   }
+
+   /* Get pointer to old buffer object (to be unbound) */
+   oldBufObj = *bindTarget;
+   if (oldBufObj && oldBufObj->Name == buffer)
+      return;   /* rebinding the same buffer object- no change */
+
+   /*
+    * Get pointer to new buffer object (newBufObj)
+    */
+   if (buffer == 0) {
+      /* The spec says there's not a buffer object named 0, but we use
+       * one internally because it simplifies things.
+       */
+      newBufObj = ctx->Shared->NullBufferObj;
+   }
+   else {
+      /* non-default buffer object */
+      newBufObj = _mesa_lookup_bufferobj(ctx, buffer);
+      if (!newBufObj || newBufObj == &DummyBufferObject) {
+         /* If this is a new buffer object id, or one which was generated but
+          * never used before, allocate a buffer object now.
+          */
+         ASSERT(ctx->Driver.NewBufferObject);
+         newBufObj = ctx->Driver.NewBufferObject(ctx, buffer, target);
+         if (!newBufObj) {
+            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindBufferARB");
+            return;
+         }
+         _mesa_HashInsert(ctx->Shared->BufferObjects, buffer, newBufObj);
+      }
+   }
+   
+   /* bind new buffer */
+   _mesa_reference_buffer_object(ctx, bindTarget, newBufObj);
+
+   /* Pass BindBuffer call to device driver */
+   if (ctx->Driver.BindBuffer)
+      ctx->Driver.BindBuffer( ctx, target, newBufObj );
+}
+
+
+/**
+ * Update the default buffer objects in the given context to reference those
+ * specified in the shared state and release those referencing the old 
+ * shared state.
+ */
+void
+_mesa_update_default_objects_buffer_objects(struct gl_context *ctx)
+{
+   /* Bind the NullBufferObj to remove references to those
+    * in the shared context hash table.
+    */
+   bind_buffer_object( ctx, GL_ARRAY_BUFFER_ARB, 0);
+   bind_buffer_object( ctx, GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
+   bind_buffer_object( ctx, GL_PIXEL_PACK_BUFFER_ARB, 0);
+   bind_buffer_object( ctx, GL_PIXEL_UNPACK_BUFFER_ARB, 0);
+}
+
+
+/**
+ * When we're about to read pixel data out of a PBO (via glDrawPixels,
+ * glTexImage, etc) or write data into a PBO (via glReadPixels,
+ * glGetTexImage, etc) we call this function to check that we're not
+ * going to read out of bounds.
+ *
+ * XXX This would also be a convenient time to check that the PBO isn't
+ * currently mapped.  Whoever calls this function should check for that.
+ * Remember, we can't use a PBO when it's mapped!
+ *
+ * If we're not using a PBO, this is a no-op.
+ *
+ * \param width  width of image to read/write
+ * \param height  height of image to read/write
+ * \param depth  depth of image to read/write
+ * \param format  format of image to read/write
+ * \param type  datatype of image to read/write
+ * \param ptr  the user-provided pointer/offset
+ * \return GL_TRUE if the PBO access is OK, GL_FALSE if the access would
+ *         go out of bounds.
+ */
+GLboolean
+_mesa_validate_pbo_access(GLuint dimensions,
+                          const struct gl_pixelstore_attrib *pack,
+                          GLsizei width, GLsizei height, GLsizei depth,
+                          GLenum format, GLenum type, const GLvoid *ptr)
+{
+   GLvoid *start, *end;
+   const GLubyte *sizeAddr; /* buffer size, cast to a pointer */
+
+   if (!_mesa_is_bufferobj(pack->BufferObj))
+      return GL_TRUE;  /* no PBO, OK */
+
+   if (pack->BufferObj->Size == 0)
+      /* no buffer! */
+      return GL_FALSE;
+
+   /* get address of first pixel we'll read */
+   start = _mesa_image_address(dimensions, pack, ptr, width, height,
+                               format, type, 0, 0, 0);
+
+   /* get address just past the last pixel we'll read */
+   end =  _mesa_image_address(dimensions, pack, ptr, width, height,
+                              format, type, depth-1, height-1, width);
+
+
+   sizeAddr = ((const GLubyte *) 0) + pack->BufferObj->Size;
+
+   if ((const GLubyte *) start > sizeAddr) {
+      /* This will catch negative values / wrap-around */
+      return GL_FALSE;
+   }
+   if ((const GLubyte *) end > sizeAddr) {
+      /* Image read goes beyond end of buffer */
+      return GL_FALSE;
+   }
+
+   /* OK! */
+   return GL_TRUE;
+}
+
+
+/**
+ * For commands that read from a PBO (glDrawPixels, glTexImage,
+ * glPolygonStipple, etc), if we're reading from a PBO, map it read-only
+ * and return the pointer into the PBO.  If we're not reading from a
+ * PBO, return \p src as-is.
+ * If non-null return, must call _mesa_unmap_pbo_source() when done.
+ *
+ * \return NULL if error, else pointer to start of data
+ */
+const GLvoid *
+_mesa_map_pbo_source(struct gl_context *ctx,
+                     const struct gl_pixelstore_attrib *unpack,
+                     const GLvoid *src)
+{
+   const GLubyte *buf;
+
+   if (_mesa_is_bufferobj(unpack->BufferObj)) {
+      /* unpack from PBO */
+      buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
+                                              GL_READ_ONLY_ARB,
+                                              unpack->BufferObj);
+      if (!buf)
+         return NULL;
+
+      buf = ADD_POINTERS(buf, src);
+   }
+   else {
+      /* unpack from normal memory */
+      buf = src;
+   }
+
+   return buf;
+}
+
+
+/**
+ * Combine PBO-read validation and mapping.
+ * If any GL errors are detected, they'll be recorded and NULL returned.
+ * \sa _mesa_validate_pbo_access
+ * \sa _mesa_map_pbo_source
+ * A call to this function should have a matching call to
+ * _mesa_unmap_pbo_source().
+ */
+const GLvoid *
+_mesa_map_validate_pbo_source(struct gl_context *ctx,
+                              GLuint dimensions,
+                              const struct gl_pixelstore_attrib *unpack,
+                              GLsizei width, GLsizei height, GLsizei depth,
+                              GLenum format, GLenum type, const GLvoid *ptr,
+                              const char *where)
+{
+   ASSERT(dimensions == 1 || dimensions == 2 || dimensions == 3);
+
+   if (!_mesa_is_bufferobj(unpack->BufferObj)) {
+      /* non-PBO access: no validation to be done */
+      return ptr;
+   }
+
+   if (!_mesa_validate_pbo_access(dimensions, unpack,
+                                  width, height, depth, format, type, ptr)) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "%s(out of bounds PBO access)", where);
+      return NULL;
+   }
+
+   if (_mesa_bufferobj_mapped(unpack->BufferObj)) {
+      /* buffer is already mapped - that's an error */
+      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", where);
+      return NULL;
+   }
+
+   ptr = _mesa_map_pbo_source(ctx, unpack, ptr);
+   return ptr;
+}
+
+
+/**
+ * Counterpart to _mesa_map_pbo_source()
+ */
+void
+_mesa_unmap_pbo_source(struct gl_context *ctx,
+                       const struct gl_pixelstore_attrib *unpack)
+{
+   ASSERT(unpack != &ctx->Pack); /* catch pack/unpack mismatch */
+   if (_mesa_is_bufferobj(unpack->BufferObj)) {
+      ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
+                              unpack->BufferObj);
+   }
+}
+
+
+/**
+ * For commands that write to a PBO (glReadPixels, glGetColorTable, etc),
+ * if we're writing to a PBO, map it write-only and return the pointer
+ * into the PBO.  If we're not writing to a PBO, return \p dst as-is.
+ * If non-null return, must call _mesa_unmap_pbo_dest() when done.
+ *
+ * \return NULL if error, else pointer to start of data
+ */
+void *
+_mesa_map_pbo_dest(struct gl_context *ctx,
+                   const struct gl_pixelstore_attrib *pack,
+                   GLvoid *dest)
+{
+   void *buf;
+
+   if (_mesa_is_bufferobj(pack->BufferObj)) {
+      /* pack into PBO */
+      buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
+                                              GL_WRITE_ONLY_ARB,
+                                              pack->BufferObj);
+      if (!buf)
+         return NULL;
+
+      buf = ADD_POINTERS(buf, dest);
+   }
+   else {
+      /* pack to normal memory */
+      buf = dest;
+   }
+
+   return buf;
+}
+
+
+/**
+ * Combine PBO-write validation and mapping.
+ * If any GL errors are detected, they'll be recorded and NULL returned.
+ * \sa _mesa_validate_pbo_access
+ * \sa _mesa_map_pbo_dest
+ * A call to this function should have a matching call to
+ * _mesa_unmap_pbo_dest().
+ */
+GLvoid *
+_mesa_map_validate_pbo_dest(struct gl_context *ctx,
+                            GLuint dimensions,
+                            const struct gl_pixelstore_attrib *unpack,
+                            GLsizei width, GLsizei height, GLsizei depth,
+                            GLenum format, GLenum type, GLvoid *ptr,
+                            const char *where)
+{
+   ASSERT(dimensions == 1 || dimensions == 2 || dimensions == 3);
+
+   if (!_mesa_is_bufferobj(unpack->BufferObj)) {
+      /* non-PBO access: no validation to be done */
+      return ptr;
+   }
+
+   if (!_mesa_validate_pbo_access(dimensions, unpack,
+                                  width, height, depth, format, type, ptr)) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "%s(out of bounds PBO access)", where);
+      return NULL;
+   }
+
+   if (_mesa_bufferobj_mapped(unpack->BufferObj)) {
+      /* buffer is already mapped - that's an error */
+      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", where);
+      return NULL;
+   }
+
+   ptr = _mesa_map_pbo_dest(ctx, unpack, ptr);
+   return ptr;
+}
+
+
+/**
+ * Counterpart to _mesa_map_pbo_dest()
+ */
+void
+_mesa_unmap_pbo_dest(struct gl_context *ctx,
+                     const struct gl_pixelstore_attrib *pack)
+{
+   ASSERT(pack != &ctx->Unpack); /* catch pack/unpack mismatch */
+   if (_mesa_is_bufferobj(pack->BufferObj)) {
+      ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, pack->BufferObj);
+   }
+}
+
+
+
+/**
+ * Return the gl_buffer_object for the given ID.
+ * Always return NULL for ID 0.
+ */
+struct gl_buffer_object *
+_mesa_lookup_bufferobj(struct gl_context *ctx, GLuint buffer)
+{
+   if (buffer == 0)
+      return NULL;
+   else
+      return (struct gl_buffer_object *)
+         _mesa_HashLookup(ctx->Shared->BufferObjects, buffer);
+}
+
+
+/**
+ * If *ptr points to obj, set ptr = the Null/default buffer object.
+ * This is a helper for buffer object deletion.
+ * The GL spec says that deleting a buffer object causes it to get
+ * unbound from all arrays in the current context.
+ */
+static void
+unbind(struct gl_context *ctx,
+       struct gl_buffer_object **ptr,
+       struct gl_buffer_object *obj)
+{
+   if (*ptr == obj) {
+      _mesa_reference_buffer_object(ctx, ptr, ctx->Shared->NullBufferObj);
+   }
+}
+
+
+/**
+ * Plug default/fallback buffer object functions into the device
+ * driver hooks.
+ */
+void
+_mesa_init_buffer_object_functions(struct dd_function_table *driver)
+{
+   /* GL_ARB_vertex/pixel_buffer_object */
+   driver->NewBufferObject = _mesa_new_buffer_object;
+   driver->DeleteBuffer = _mesa_delete_buffer_object;
+   driver->BindBuffer = NULL;
+   driver->BufferData = _mesa_buffer_data;
+   driver->BufferSubData = _mesa_buffer_subdata;
+   driver->GetBufferSubData = _mesa_buffer_get_subdata;
+   driver->MapBuffer = _mesa_buffer_map;
+   driver->UnmapBuffer = _mesa_buffer_unmap;
+
+   /* GL_ARB_map_buffer_range */
+   driver->MapBufferRange = _mesa_buffer_map_range;
+   driver->FlushMappedBufferRange = _mesa_buffer_flush_mapped_range;
+
+   /* GL_ARB_copy_buffer */
+   driver->CopyBufferSubData = _mesa_copy_buffer_subdata;
+}
+
+
+
+/**********************************************************************/
+/* API Functions                                                      */
+/**********************************************************************/
+
+void GLAPIENTRY
+_mesa_BindBufferARB(GLenum target, GLuint buffer)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glBindBuffer(%s, %u)\n",
+                  _mesa_lookup_enum_by_nr(target), buffer);
+
+   bind_buffer_object(ctx, target, buffer);
+}
+
+
+/**
+ * Delete a set of buffer objects.
+ * 
+ * \param n      Number of buffer objects to delete.
+ * \param ids    Array of \c n buffer object IDs.
+ */
+void GLAPIENTRY
+_mesa_DeleteBuffersARB(GLsizei n, const GLuint *ids)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   GLsizei i;
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (n < 0) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteBuffersARB(n)");
+      return;
+   }
+
+   _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
+
+   for (i = 0; i < n; i++) {
+      struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, ids[i]);
+      if (bufObj) {
+         struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
+         GLuint j;
+
+         ASSERT(bufObj->Name == ids[i] || bufObj == &DummyBufferObject);
+
+         if (_mesa_bufferobj_mapped(bufObj)) {
+            /* if mapped, unmap it now */
+            ctx->Driver.UnmapBuffer(ctx, 0, bufObj);
+            bufObj->AccessFlags = DEFAULT_ACCESS;
+            bufObj->Pointer = NULL;
+         }
+
+         /* unbind any vertex pointers bound to this buffer */
+         unbind(ctx, &arrayObj->Vertex.BufferObj, bufObj);
+         unbind(ctx, &arrayObj->Weight.BufferObj, bufObj);
+         unbind(ctx, &arrayObj->Normal.BufferObj, bufObj);
+         unbind(ctx, &arrayObj->Color.BufferObj, bufObj);
+         unbind(ctx, &arrayObj->SecondaryColor.BufferObj, bufObj);
+         unbind(ctx, &arrayObj->FogCoord.BufferObj, bufObj);
+         unbind(ctx, &arrayObj->Index.BufferObj, bufObj);
+         unbind(ctx, &arrayObj->EdgeFlag.BufferObj, bufObj);
+         for (j = 0; j < Elements(arrayObj->TexCoord); j++) {
+            unbind(ctx, &arrayObj->TexCoord[j].BufferObj, bufObj);
+         }
+         for (j = 0; j < Elements(arrayObj->VertexAttrib); j++) {
+            unbind(ctx, &arrayObj->VertexAttrib[j].BufferObj, bufObj);
+         }
+
+         if (ctx->Array.ArrayBufferObj == bufObj) {
+            _mesa_BindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
+         }
+         if (ctx->Array.ElementArrayBufferObj == bufObj) {
+            _mesa_BindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 0 );
+         }
+
+         /* unbind any pixel pack/unpack pointers bound to this buffer */
+         if (ctx->Pack.BufferObj == bufObj) {
+            _mesa_BindBufferARB( GL_PIXEL_PACK_BUFFER_EXT, 0 );
+         }
+         if (ctx->Unpack.BufferObj == bufObj) {
+            _mesa_BindBufferARB( GL_PIXEL_UNPACK_BUFFER_EXT, 0 );
+         }
+
+         /* The ID is immediately freed for re-use */
+         _mesa_HashRemove(ctx->Shared->BufferObjects, ids[i]);
+         _mesa_reference_buffer_object(ctx, &bufObj, NULL);
+      }
+   }
+
+   _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
+}
+
+
+/**
+ * Generate a set of unique buffer object IDs and store them in \c buffer.
+ * 
+ * \param n       Number of IDs to generate.
+ * \param buffer  Array of \c n locations to store the IDs.
+ */
+void GLAPIENTRY
+_mesa_GenBuffersARB(GLsizei n, GLuint *buffer)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   GLuint first;
+   GLint i;
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glGenBuffers(%d)\n", n);
+
+   if (n < 0) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "glGenBuffersARB");
+      return;
+   }
+
+   if (!buffer) {
+      return;
+   }
+
+   /*
+    * This must be atomic (generation and allocation of buffer object IDs)
+    */
+   _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
+
+   first = _mesa_HashFindFreeKeyBlock(ctx->Shared->BufferObjects, n);
+
+   /* Insert the ID and pointer to dummy buffer object into hash table */
+   for (i = 0; i < n; i++) {
+      _mesa_HashInsert(ctx->Shared->BufferObjects, first + i,
+                       &DummyBufferObject);
+      buffer[i] = first + i;
+   }
+
+   _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
+}
+
+
+/**
+ * Determine if ID is the name of a buffer object.
+ * 
+ * \param id  ID of the potential buffer object.
+ * \return  \c GL_TRUE if \c id is the name of a buffer object, 
+ *          \c GL_FALSE otherwise.
+ */
+GLboolean GLAPIENTRY
+_mesa_IsBufferARB(GLuint id)
+{
+   struct gl_buffer_object *bufObj;
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
+
+   _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
+   bufObj = _mesa_lookup_bufferobj(ctx, id);
+   _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
+
+   return bufObj && bufObj != &DummyBufferObject;
+}
+
+
+void GLAPIENTRY
+_mesa_BufferDataARB(GLenum target, GLsizeiptrARB size,
+                    const GLvoid * data, GLenum usage)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_buffer_object *bufObj;
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glBufferData(%s, %ld, %p, %s)\n",
+                  _mesa_lookup_enum_by_nr(target),
+                  (long int) size, data,
+                  _mesa_lookup_enum_by_nr(usage));
+
+   if (size < 0) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "glBufferDataARB(size < 0)");
+      return;
+   }
+
+   switch (usage) {
+   case GL_STREAM_DRAW_ARB:
+   case GL_STREAM_READ_ARB:
+   case GL_STREAM_COPY_ARB:
+   case GL_STATIC_DRAW_ARB:
+   case GL_STATIC_READ_ARB:
+   case GL_STATIC_COPY_ARB:
+   case GL_DYNAMIC_DRAW_ARB:
+   case GL_DYNAMIC_READ_ARB:
+   case GL_DYNAMIC_COPY_ARB:
+      /* OK */
+      break;
+   default:
+      _mesa_error(ctx, GL_INVALID_ENUM, "glBufferDataARB(usage)");
+      return;
+   }
+
+   bufObj = get_buffer(ctx, target);
+   if (!bufObj) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glBufferDataARB(target)" );
+      return;
+   }
+   if (!_mesa_is_bufferobj(bufObj)) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "glBufferDataARB(buffer 0)" );
+      return;
+   }
+   
+   if (_mesa_bufferobj_mapped(bufObj)) {
+      /* Unmap the existing buffer.  We'll replace it now.  Not an error. */
+      ctx->Driver.UnmapBuffer(ctx, target, bufObj);
+      bufObj->AccessFlags = DEFAULT_ACCESS;
+      ASSERT(bufObj->Pointer == NULL);
+   }  
+
+   FLUSH_VERTICES(ctx, _NEW_BUFFER_OBJECT);
+
+   bufObj->Written = GL_TRUE;
+
+#ifdef VBO_DEBUG
+   printf("glBufferDataARB(%u, sz %ld, from %p, usage 0x%x)\n",
+                bufObj->Name, size, data, usage);
+#endif
+
+#ifdef BOUNDS_CHECK
+   size += 100;
+#endif
+
+   ASSERT(ctx->Driver.BufferData);
+   if (!ctx->Driver.BufferData( ctx, target, size, data, usage, bufObj )) {
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBufferDataARB()");
+   }
+}
+
+
+void GLAPIENTRY
+_mesa_BufferSubDataARB(GLenum target, GLintptrARB offset,
+                       GLsizeiptrARB size, const GLvoid * data)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_buffer_object *bufObj;
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   bufObj = buffer_object_subdata_range_good( ctx, target, offset, size,
+                                              "glBufferSubDataARB" );
+   if (!bufObj) {
+      /* error already recorded */
+      return;
+   }
+
+   if (size == 0)
+      return;
+
+   bufObj->Written = GL_TRUE;
+
+   ASSERT(ctx->Driver.BufferSubData);
+   ctx->Driver.BufferSubData( ctx, target, offset, size, data, bufObj );
+}
+
+
+void GLAPIENTRY
+_mesa_GetBufferSubDataARB(GLenum target, GLintptrARB offset,
+                          GLsizeiptrARB size, void * data)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_buffer_object *bufObj;
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   bufObj = buffer_object_subdata_range_good( ctx, target, offset, size,
+                                              "glGetBufferSubDataARB" );
+   if (!bufObj) {
+      /* error already recorded */
+      return;
+   }
+
+   ASSERT(ctx->Driver.GetBufferSubData);
+   ctx->Driver.GetBufferSubData( ctx, target, offset, size, data, bufObj );
+}
+
+
+void * GLAPIENTRY
+_mesa_MapBufferARB(GLenum target, GLenum access)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_buffer_object * bufObj;
+   GLbitfield accessFlags;
+   void *map;
+
+   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL);
+
+   switch (access) {
+   case GL_READ_ONLY_ARB:
+      accessFlags = GL_MAP_READ_BIT;
+      break;
+   case GL_WRITE_ONLY_ARB:
+      accessFlags = GL_MAP_WRITE_BIT;
+      break;
+   case GL_READ_WRITE_ARB:
+      accessFlags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT;
+      break;
+   default:
+      _mesa_error(ctx, GL_INVALID_ENUM, "glMapBufferARB(access)");
+      return NULL;
+   }
+
+   bufObj = get_buffer(ctx, target);
+   if (!bufObj) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glMapBufferARB(target)" );
+      return NULL;
+   }
+   if (!_mesa_is_bufferobj(bufObj)) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "glMapBufferARB(buffer 0)" );
+      return NULL;
+   }
+   if (_mesa_bufferobj_mapped(bufObj)) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "glMapBufferARB(already mapped)");
+      return NULL;
+   }
+
+   ASSERT(ctx->Driver.MapBuffer);
+   map = ctx->Driver.MapBuffer( ctx, target, access, bufObj );
+   if (!map) {
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMapBufferARB(map failed)");
+      return NULL;
+   }
+   else {
+      /* The driver callback should have set these fields.
+       * This is important because other modules (like VBO) might call
+       * the driver function directly.
+       */
+      ASSERT(bufObj->Pointer == map);
+      ASSERT(bufObj->Length == bufObj->Size);
+      ASSERT(bufObj->Offset == 0);
+      bufObj->AccessFlags = accessFlags;
+   }
+
+   if (access == GL_WRITE_ONLY_ARB || access == GL_READ_WRITE_ARB)
+      bufObj->Written = GL_TRUE;
+
+#ifdef VBO_DEBUG
+   printf("glMapBufferARB(%u, sz %ld, access 0x%x)\n",
+	  bufObj->Name, bufObj->Size, access);
+   if (access == GL_WRITE_ONLY_ARB) {
+      GLuint i;
+      GLubyte *b = (GLubyte *) bufObj->Pointer;
+      for (i = 0; i < bufObj->Size; i++)
+         b[i] = i & 0xff;
+   }
+#endif
+
+#ifdef BOUNDS_CHECK
+   {
+      GLubyte *buf = (GLubyte *) bufObj->Pointer;
+      GLuint i;
+      /* buffer is 100 bytes larger than requested, fill with magic value */
+      for (i = 0; i < 100; i++) {
+         buf[bufObj->Size - i - 1] = 123;
+      }
+   }
+#endif
+
+   return bufObj->Pointer;
+}
+
+
+GLboolean GLAPIENTRY
+_mesa_UnmapBufferARB(GLenum target)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_buffer_object *bufObj;
+   GLboolean status = GL_TRUE;
+   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
+
+   bufObj = get_buffer(ctx, target);
+   if (!bufObj) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glUnmapBufferARB(target)" );
+      return GL_FALSE;
+   }
+   if (!_mesa_is_bufferobj(bufObj)) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "glUnmapBufferARB" );
+      return GL_FALSE;
+   }
+   if (!_mesa_bufferobj_mapped(bufObj)) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "glUnmapBufferARB");
+      return GL_FALSE;
+   }
+
+#ifdef BOUNDS_CHECK
+   if (bufObj->Access != GL_READ_ONLY_ARB) {
+      GLubyte *buf = (GLubyte *) bufObj->Pointer;
+      GLuint i;
+      /* check that last 100 bytes are still = magic value */
+      for (i = 0; i < 100; i++) {
+         GLuint pos = bufObj->Size - i - 1;
+         if (buf[pos] != 123) {
+            _mesa_warning(ctx, "Out of bounds buffer object write detected"
+                          " at position %d (value = %u)\n",
+                          pos, buf[pos]);
+         }
+      }
+   }
+#endif
+
+#ifdef VBO_DEBUG
+   if (bufObj->AccessFlags & GL_MAP_WRITE_BIT) {
+      GLuint i, unchanged = 0;
+      GLubyte *b = (GLubyte *) bufObj->Pointer;
+      GLint pos = -1;
+      /* check which bytes changed */
+      for (i = 0; i < bufObj->Size - 1; i++) {
+         if (b[i] == (i & 0xff) && b[i+1] == ((i+1) & 0xff)) {
+            unchanged++;
+            if (pos == -1)
+               pos = i;
+         }
+      }
+      if (unchanged) {
+         printf("glUnmapBufferARB(%u): %u of %ld unchanged, starting at %d\n",
+                      bufObj->Name, unchanged, bufObj->Size, pos);
+      }
+   }
+#endif
+
+   status = ctx->Driver.UnmapBuffer( ctx, target, bufObj );
+   bufObj->AccessFlags = DEFAULT_ACCESS;
+   ASSERT(bufObj->Pointer == NULL);
+   ASSERT(bufObj->Offset == 0);
+   ASSERT(bufObj->Length == 0);
+
+   return status;
+}
+
+
+void GLAPIENTRY
+_mesa_GetBufferParameterivARB(GLenum target, GLenum pname, GLint *params)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_buffer_object *bufObj;
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   bufObj = get_buffer(ctx, target);
+   if (!bufObj) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferParameterivARB(target)" );
+      return;
+   }
+   if (!_mesa_is_bufferobj(bufObj)) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetBufferParameterivARB" );
+      return;
+   }
+
+   switch (pname) {
+   case GL_BUFFER_SIZE_ARB:
+      *params = (GLint) bufObj->Size;
+      return;
+   case GL_BUFFER_USAGE_ARB:
+      *params = bufObj->Usage;
+      return;
+   case GL_BUFFER_ACCESS_ARB:
+      *params = simplified_access_mode(bufObj->AccessFlags);
+      return;
+   case GL_BUFFER_MAPPED_ARB:
+      *params = _mesa_bufferobj_mapped(bufObj);
+      return;
+   case GL_BUFFER_ACCESS_FLAGS:
+      if (ctx->VersionMajor < 3)
+         goto invalid_pname;
+      *params = bufObj->AccessFlags;
+      return;
+   case GL_BUFFER_MAP_OFFSET:
+      if (ctx->VersionMajor < 3)
+         goto invalid_pname;
+      *params = (GLint) bufObj->Offset;
+      return;
+   case GL_BUFFER_MAP_LENGTH:
+      if (ctx->VersionMajor < 3)
+         goto invalid_pname;
+      *params = (GLint) bufObj->Length;
+      return;
+   default:
+      ; /* fall-through */
+   }
+
+invalid_pname:
+   _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferParameterivARB(pname=%s)",
+               _mesa_lookup_enum_by_nr(pname));
+}
+
+
+/**
+ * New in GL 3.2
+ * This is pretty much a duplicate of GetBufferParameteriv() but the
+ * GL_BUFFER_SIZE_ARB attribute will be 64-bits on a 64-bit system.
+ */
+void GLAPIENTRY
+_mesa_GetBufferParameteri64v(GLenum target, GLenum pname, GLint64 *params)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_buffer_object *bufObj;
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   bufObj = get_buffer(ctx, target);
+   if (!bufObj) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferParameteri64v(target)" );
+      return;
+   }
+   if (!_mesa_is_bufferobj(bufObj)) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetBufferParameteri64v" );
+      return;
+   }
+
+   switch (pname) {
+   case GL_BUFFER_SIZE_ARB:
+      *params = bufObj->Size;
+      return;
+   case GL_BUFFER_USAGE_ARB:
+      *params = bufObj->Usage;
+      return;
+   case GL_BUFFER_ACCESS_ARB:
+      *params = simplified_access_mode(bufObj->AccessFlags);
+      return;
+   case GL_BUFFER_ACCESS_FLAGS:
+      if (ctx->VersionMajor < 3)
+         goto invalid_pname;
+      *params = bufObj->AccessFlags;
+      return;
+   case GL_BUFFER_MAPPED_ARB:
+      *params = _mesa_bufferobj_mapped(bufObj);
+      return;
+   case GL_BUFFER_MAP_OFFSET:
+      if (ctx->VersionMajor < 3)
+         goto invalid_pname;
+      *params = bufObj->Offset;
+      return;
+   case GL_BUFFER_MAP_LENGTH:
+      if (ctx->VersionMajor < 3)
+         goto invalid_pname;
+      *params = bufObj->Length;
+      return;
+   default:
+      ; /* fall-through */
+   }
+
+invalid_pname:
+   _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferParameteri64v(pname=%s)",
+               _mesa_lookup_enum_by_nr(pname));
+}
+
+
+void GLAPIENTRY
+_mesa_GetBufferPointervARB(GLenum target, GLenum pname, GLvoid **params)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_buffer_object * bufObj;
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (pname != GL_BUFFER_MAP_POINTER_ARB) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferPointervARB(pname)");
+      return;
+   }
+
+   bufObj = get_buffer(ctx, target);
+   if (!bufObj) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferPointervARB(target)" );
+      return;
+   }
+   if (!_mesa_is_bufferobj(bufObj)) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetBufferPointervARB" );
+      return;
+   }
+
+   *params = bufObj->Pointer;
+}
+
+
+void GLAPIENTRY
+_mesa_CopyBufferSubData(GLenum readTarget, GLenum writeTarget,
+                        GLintptr readOffset, GLintptr writeOffset,
+                        GLsizeiptr size)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_buffer_object *src, *dst;
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   src = get_buffer(ctx, readTarget);
+   if (!src || !_mesa_is_bufferobj(src)) {
+      _mesa_error(ctx, GL_INVALID_ENUM,
+                  "glCopyBuffserSubData(readTarget = 0x%x)", readTarget);
+      return;
+   }
+
+   dst = get_buffer(ctx, writeTarget);
+   if (!dst || !_mesa_is_bufferobj(dst)) {
+      _mesa_error(ctx, GL_INVALID_ENUM,
+                  "glCopyBuffserSubData(writeTarget = 0x%x)", writeTarget);
+      return;
+   }
+
+   if (_mesa_bufferobj_mapped(src)) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glCopyBuffserSubData(readBuffer is mapped)");
+      return;
+   }
+
+   if (_mesa_bufferobj_mapped(dst)) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glCopyBuffserSubData(writeBuffer is mapped)");
+      return;
+   }
+
+   if (readOffset < 0) {
+      _mesa_error(ctx, GL_INVALID_VALUE,
+                  "glCopyBuffserSubData(readOffset = %d)", (int) readOffset);
+      return;
+   }
+
+   if (writeOffset < 0) {
+      _mesa_error(ctx, GL_INVALID_VALUE,
+                  "glCopyBuffserSubData(writeOffset = %d)", (int) writeOffset);
+      return;
+   }
+
+   if (readOffset + size > src->Size) {
+      _mesa_error(ctx, GL_INVALID_VALUE,
+                  "glCopyBuffserSubData(readOffset + size = %d)",
+                  (int) (readOffset + size));
+      return;
+   }
+
+   if (writeOffset + size > dst->Size) {
+      _mesa_error(ctx, GL_INVALID_VALUE,
+                  "glCopyBuffserSubData(writeOffset + size = %d)",
+                  (int) (writeOffset + size));
+      return;
+   }
+
+   if (src == dst) {
+      if (readOffset + size <= writeOffset) {
+         /* OK */
+      }
+      else if (writeOffset + size <= readOffset) {
+         /* OK */
+      }
+      else {
+         /* overlapping src/dst is illegal */
+         _mesa_error(ctx, GL_INVALID_VALUE,
+                     "glCopyBuffserSubData(overlapping src/dst)");
+         return;
+      }
+   }
+
+   ctx->Driver.CopyBufferSubData(ctx, src, dst, readOffset, writeOffset, size);
+}
+
+
+/**
+ * See GL_ARB_map_buffer_range spec
+ */
+void * GLAPIENTRY
+_mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length,
+                     GLbitfield access)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_buffer_object *bufObj;
+   void *map;
+
+   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL);
+
+   if (!ctx->Extensions.ARB_map_buffer_range) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glMapBufferRange(extension not supported)");
+      return NULL;
+   }
+
+   if (offset < 0) {
+      _mesa_error(ctx, GL_INVALID_VALUE,
+                  "glMapBufferRange(offset = %ld)", (long)offset);
+      return NULL;
+   }
+
+   if (length < 0) {
+      _mesa_error(ctx, GL_INVALID_VALUE,
+                  "glMapBufferRange(length = %ld)", (long)length);
+      return NULL;
+   }
+
+   if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glMapBufferRange(access indicates neither read or write)");
+      return NULL;
+   }
+
+   if (access & GL_MAP_READ_BIT) {
+      if ((access & GL_MAP_INVALIDATE_RANGE_BIT) ||
+          (access & GL_MAP_INVALIDATE_BUFFER_BIT) ||
+          (access & GL_MAP_UNSYNCHRONIZED_BIT)) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glMapBufferRange(invalid access flags)");
+         return NULL;
+      }
+   }
+
+   if ((access & GL_MAP_FLUSH_EXPLICIT_BIT) &&
+       ((access & GL_MAP_WRITE_BIT) == 0)) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glMapBufferRange(invalid access flags)");
+      return NULL;
+   }
+
+   bufObj = get_buffer(ctx, target);
+   if (!bufObj || !_mesa_is_bufferobj(bufObj)) {
+      _mesa_error(ctx, GL_INVALID_ENUM,
+                  "glMapBufferRange(target = 0x%x)", target);
+      return NULL;
+   }
+
+   if (offset + length > bufObj->Size) {
+      _mesa_error(ctx, GL_INVALID_VALUE,
+                  "glMapBufferRange(offset + length > size)");
+      return NULL;
+   }
+
+   if (_mesa_bufferobj_mapped(bufObj)) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glMapBufferRange(buffer already mapped)");
+      return NULL;
+   }
+      
+   ASSERT(ctx->Driver.MapBufferRange);
+   map = ctx->Driver.MapBufferRange(ctx, target, offset, length,
+                                    access, bufObj);
+   if (!map) {
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMapBufferARB(map failed)");
+   }
+   else {
+      /* The driver callback should have set all these fields.
+       * This is important because other modules (like VBO) might call
+       * the driver function directly.
+       */
+      ASSERT(bufObj->Pointer == map);
+      ASSERT(bufObj->Length == length);
+      ASSERT(bufObj->Offset == offset);
+      ASSERT(bufObj->AccessFlags == access);
+   }
+
+   return map;
+}
+
+
+/**
+ * See GL_ARB_map_buffer_range spec
+ */
+void GLAPIENTRY
+_mesa_FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_buffer_object *bufObj;
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (!ctx->Extensions.ARB_map_buffer_range) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glMapBufferRange(extension not supported)");
+      return;
+   }
+
+   if (offset < 0) {
+      _mesa_error(ctx, GL_INVALID_VALUE,
+                  "glMapBufferRange(offset = %ld)", (long)offset);
+      return;
+   }
+
+   if (length < 0) {
+      _mesa_error(ctx, GL_INVALID_VALUE,
+                  "glMapBufferRange(length = %ld)", (long)length);
+      return;
+   }
+
+   bufObj = get_buffer(ctx, target);
+   if (!bufObj) {
+      _mesa_error(ctx, GL_INVALID_ENUM,
+                  "glMapBufferRange(target = 0x%x)", target);
+      return;
+   }
+
+   if (!_mesa_is_bufferobj(bufObj)) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glMapBufferRange(current buffer is 0)");
+      return;
+   }
+
+   if (!_mesa_bufferobj_mapped(bufObj)) {
+      /* buffer is not mapped */
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glMapBufferRange(buffer is not mapped)");
+      return;
+   }
+
+   if ((bufObj->AccessFlags & GL_MAP_FLUSH_EXPLICIT_BIT) == 0) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glMapBufferRange(GL_MAP_FLUSH_EXPLICIT_BIT not set)");
+      return;
+   }
+
+   if (offset + length > bufObj->Length) {
+      _mesa_error(ctx, GL_INVALID_VALUE,
+		  "glMapBufferRange(offset %ld + length %ld > mapped length %ld)",
+		  (long)offset, (long)length, (long)bufObj->Length);
+      return;
+   }
+
+   ASSERT(bufObj->AccessFlags & GL_MAP_WRITE_BIT);
+
+   if (ctx->Driver.FlushMappedBufferRange)
+      ctx->Driver.FlushMappedBufferRange(ctx, target, offset, length, bufObj);
+}
+
+
+#if FEATURE_APPLE_object_purgeable
+static GLenum
+_mesa_BufferObjectPurgeable(struct gl_context *ctx, GLuint name, GLenum option)
+{
+   struct gl_buffer_object *bufObj;
+   GLenum retval;
+
+   bufObj = _mesa_lookup_bufferobj(ctx, name);
+   if (!bufObj) {
+      _mesa_error(ctx, GL_INVALID_VALUE,
+                  "glObjectPurgeable(name = 0x%x)", name);
+      return 0;
+   }
+   if (!_mesa_is_bufferobj(bufObj)) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "glObjectPurgeable(buffer 0)" );
+      return 0;
+   }
+
+   if (bufObj->Purgeable) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glObjectPurgeable(name = 0x%x) is already purgeable", name);
+      return GL_VOLATILE_APPLE;
+   }
+
+   bufObj->Purgeable = GL_TRUE;
+
+   retval = GL_VOLATILE_APPLE;
+   if (ctx->Driver.BufferObjectPurgeable)
+      retval = ctx->Driver.BufferObjectPurgeable(ctx, bufObj, option);
+
+   return retval;
+}
+
+
+static GLenum
+_mesa_RenderObjectPurgeable(struct gl_context *ctx, GLuint name, GLenum option)
+{
+   struct gl_renderbuffer *bufObj;
+   GLenum retval;
+
+   bufObj = _mesa_lookup_renderbuffer(ctx, name);
+   if (!bufObj) {
+      _mesa_error(ctx, GL_INVALID_VALUE,
+                  "glObjectUnpurgeable(name = 0x%x)", name);
+      return 0;
+   }
+
+   if (bufObj->Purgeable) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glObjectPurgeable(name = 0x%x) is already purgeable", name);
+      return GL_VOLATILE_APPLE;
+   }
+
+   bufObj->Purgeable = GL_TRUE;
+
+   retval = GL_VOLATILE_APPLE;
+   if (ctx->Driver.RenderObjectPurgeable)
+      retval = ctx->Driver.RenderObjectPurgeable(ctx, bufObj, option);
+
+   return retval;
+}
+
+
+static GLenum
+_mesa_TextureObjectPurgeable(struct gl_context *ctx, GLuint name, GLenum option)
+{
+   struct gl_texture_object *bufObj;
+   GLenum retval;
+
+   bufObj = _mesa_lookup_texture(ctx, name);
+   if (!bufObj) {
+      _mesa_error(ctx, GL_INVALID_VALUE,
+                  "glObjectPurgeable(name = 0x%x)", name);
+      return 0;
+   }
+
+   if (bufObj->Purgeable) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glObjectPurgeable(name = 0x%x) is already purgeable", name);
+      return GL_VOLATILE_APPLE;
+   }
+
+   bufObj->Purgeable = GL_TRUE;
+
+   retval = GL_VOLATILE_APPLE;
+   if (ctx->Driver.TextureObjectPurgeable)
+      retval = ctx->Driver.TextureObjectPurgeable(ctx, bufObj, option);
+
+   return retval;
+}
+
+
+GLenum GLAPIENTRY
+_mesa_ObjectPurgeableAPPLE(GLenum objectType, GLuint name, GLenum option)
+{
+   GLenum retval;
+
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
+
+   if (name == 0) {
+      _mesa_error(ctx, GL_INVALID_VALUE,
+                  "glObjectPurgeable(name = 0x%x)", name);
+      return 0;
+   }
+
+   switch (option) {
+   case GL_VOLATILE_APPLE:
+   case GL_RELEASED_APPLE:
+      /* legal */
+      break;
+   default:
+      _mesa_error(ctx, GL_INVALID_ENUM,
+                  "glObjectPurgeable(name = 0x%x) invalid option: %d",
+                  name, option);
+      return 0;
+   }
+
+   switch (objectType) {
+   case GL_TEXTURE:
+      retval = _mesa_TextureObjectPurgeable (ctx, name, option);
+      break;
+   case GL_RENDERBUFFER_EXT:
+      retval = _mesa_RenderObjectPurgeable (ctx, name, option);
+      break;
+   case GL_BUFFER_OBJECT_APPLE:
+      retval = _mesa_BufferObjectPurgeable (ctx, name, option);
+      break;
+   default:
+      _mesa_error(ctx, GL_INVALID_ENUM,
+                  "glObjectPurgeable(name = 0x%x) invalid type: %d",
+                  name, objectType);
+      return 0;
+   }
+
+   /* In strict conformance to the spec, we must only return VOLATILE when
+    * when passed the VOLATILE option. Madness.
+    *
+    * XXX First fix the spec, then fix me.
+    */
+   return option == GL_VOLATILE_APPLE ? GL_VOLATILE_APPLE : retval;
+}
+
+
+static GLenum
+_mesa_BufferObjectUnpurgeable(struct gl_context *ctx, GLuint name, GLenum option)
+{
+   struct gl_buffer_object *bufObj;
+   GLenum retval;
+
+   bufObj = _mesa_lookup_bufferobj(ctx, name);
+   if (!bufObj) {
+      _mesa_error(ctx, GL_INVALID_VALUE,
+                  "glObjectUnpurgeable(name = 0x%x)", name);
+      return 0;
+   }
+
+   if (! bufObj->Purgeable) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glObjectUnpurgeable(name = 0x%x) object is "
+                  " already \"unpurged\"", name);
+      return 0;
+   }
+
+   bufObj->Purgeable = GL_FALSE;
+
+   retval = option;
+   if (ctx->Driver.BufferObjectUnpurgeable)
+      retval = ctx->Driver.BufferObjectUnpurgeable(ctx, bufObj, option);
+
+   return retval;
+}
+
+
+static GLenum
+_mesa_RenderObjectUnpurgeable(struct gl_context *ctx, GLuint name, GLenum option)
+{
+   struct gl_renderbuffer *bufObj;
+   GLenum retval;
+
+   bufObj = _mesa_lookup_renderbuffer(ctx, name);
+   if (!bufObj) {
+      _mesa_error(ctx, GL_INVALID_VALUE,
+                  "glObjectUnpurgeable(name = 0x%x)", name);
+      return 0;
+   }
+
+   if (! bufObj->Purgeable) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glObjectUnpurgeable(name = 0x%x) object is "
+                  " already \"unpurged\"", name);
+      return 0;
+   }
+
+   bufObj->Purgeable = GL_FALSE;
+
+   retval = option;
+   if (ctx->Driver.RenderObjectUnpurgeable)
+      retval = ctx->Driver.RenderObjectUnpurgeable(ctx, bufObj, option);
+
+   return retval;
+}
+
+
+static GLenum
+_mesa_TextureObjectUnpurgeable(struct gl_context *ctx, GLuint name, GLenum option)
+{
+   struct gl_texture_object *bufObj;
+   GLenum retval;
+
+   bufObj = _mesa_lookup_texture(ctx, name);
+   if (!bufObj) {
+      _mesa_error(ctx, GL_INVALID_VALUE,
+                  "glObjectUnpurgeable(name = 0x%x)", name);
+      return 0;
+   }
+
+   if (! bufObj->Purgeable) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glObjectUnpurgeable(name = 0x%x) object is"
+                  " already \"unpurged\"", name);
+      return 0;
+   }
+
+   bufObj->Purgeable = GL_FALSE;
+
+   retval = option;
+   if (ctx->Driver.TextureObjectUnpurgeable)
+      retval = ctx->Driver.TextureObjectUnpurgeable(ctx, bufObj, option);
+
+   return retval;
+}
+
+
+GLenum GLAPIENTRY
+_mesa_ObjectUnpurgeableAPPLE(GLenum objectType, GLuint name, GLenum option)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
+
+   if (name == 0) {
+      _mesa_error(ctx, GL_INVALID_VALUE,
+                  "glObjectUnpurgeable(name = 0x%x)", name);
+      return 0;
+   }
+
+   switch (option) {
+   case GL_RETAINED_APPLE:
+   case GL_UNDEFINED_APPLE:
+      /* legal */
+      break;
+   default:
+      _mesa_error(ctx, GL_INVALID_ENUM,
+                  "glObjectUnpurgeable(name = 0x%x) invalid option: %d",
+                  name, option);
+      return 0;
+   }
+
+   switch (objectType) {
+   case GL_BUFFER_OBJECT_APPLE:
+      return _mesa_BufferObjectUnpurgeable(ctx, name, option);
+   case GL_TEXTURE:
+      return _mesa_TextureObjectUnpurgeable(ctx, name, option);
+   case GL_RENDERBUFFER_EXT:
+      return _mesa_RenderObjectUnpurgeable(ctx, name, option);
+   default:
+      _mesa_error(ctx, GL_INVALID_ENUM,
+                  "glObjectUnpurgeable(name = 0x%x) invalid type: %d",
+                  name, objectType);
+      return 0;
+   }
+}
+
+
+static void
+_mesa_GetBufferObjectParameterivAPPLE(struct gl_context *ctx, GLuint name,
+                                      GLenum pname, GLint* params)
+{
+   struct gl_buffer_object *bufObj;
+
+   bufObj = _mesa_lookup_bufferobj(ctx, name);
+   if (!bufObj) {
+      _mesa_error(ctx, GL_INVALID_VALUE,
+                  "glGetObjectParameteriv(name = 0x%x) invalid object", name);
+      return;
+   }
+
+   switch (pname) {
+   case GL_PURGEABLE_APPLE:
+      *params = bufObj->Purgeable;
+      break;
+   default:
+      _mesa_error(ctx, GL_INVALID_ENUM,
+                  "glGetObjectParameteriv(name = 0x%x) invalid enum: %d",
+                  name, pname);
+      break;
+   }
+}
+
+
+static void
+_mesa_GetRenderObjectParameterivAPPLE(struct gl_context *ctx, GLuint name,
+                                      GLenum pname, GLint* params)
+{
+   struct gl_renderbuffer *bufObj;
+
+   bufObj = _mesa_lookup_renderbuffer(ctx, name);
+   if (!bufObj) {
+      _mesa_error(ctx, GL_INVALID_VALUE,
+                  "glObjectUnpurgeable(name = 0x%x)", name);
+      return;
+   }
+
+   switch (pname) {
+   case GL_PURGEABLE_APPLE:
+      *params = bufObj->Purgeable;
+      break;
+   default:
+      _mesa_error(ctx, GL_INVALID_ENUM,
+                  "glGetObjectParameteriv(name = 0x%x) invalid enum: %d",
+                  name, pname);
+      break;
+   }
+}
+
+
+static void
+_mesa_GetTextureObjectParameterivAPPLE(struct gl_context *ctx, GLuint name,
+                                       GLenum pname, GLint* params)
+{
+   struct gl_texture_object *bufObj;
+
+   bufObj = _mesa_lookup_texture(ctx, name);
+   if (!bufObj) {
+      _mesa_error(ctx, GL_INVALID_VALUE,
+                  "glObjectUnpurgeable(name = 0x%x)", name);
+      return;
+   }
+
+   switch (pname) {
+   case GL_PURGEABLE_APPLE:
+      *params = bufObj->Purgeable;
+      break;
+   default:
+      _mesa_error(ctx, GL_INVALID_ENUM,
+                  "glGetObjectParameteriv(name = 0x%x) invalid enum: %d",
+                  name, pname);
+      break;
+   }
+}
+
+
+void GLAPIENTRY
+_mesa_GetObjectParameterivAPPLE(GLenum objectType, GLuint name, GLenum pname,
+                                GLint* params)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   if (name == 0) {
+      _mesa_error(ctx, GL_INVALID_VALUE,
+                  "glGetObjectParameteriv(name = 0x%x)", name);
+      return;
+   }
+
+   switch (objectType) {
+   case GL_TEXTURE:
+      _mesa_GetTextureObjectParameterivAPPLE (ctx, name, pname, params);
+      break;
+   case GL_BUFFER_OBJECT_APPLE:
+      _mesa_GetBufferObjectParameterivAPPLE (ctx, name, pname, params);
+      break;
+   case GL_RENDERBUFFER_EXT:
+      _mesa_GetRenderObjectParameterivAPPLE (ctx, name, pname, params);
+      break;
+   default:
+      _mesa_error(ctx, GL_INVALID_ENUM,
+                  "glGetObjectParameteriv(name = 0x%x) invalid type: %d",
+                  name, objectType);
+   }
+}
+
+#endif /* FEATURE_APPLE_object_purgeable */
diff --git a/mesalib/src/mesa/main/context.c b/mesalib/src/mesa/main/context.c
index e017939a4..a94231455 100644
--- a/mesalib/src/mesa/main/context.c
+++ b/mesalib/src/mesa/main/context.c
@@ -886,12 +886,12 @@ _mesa_alloc_dispatch_table(int size)
  * \param driverContext pointer to driver-specific context data
  */
 GLboolean
-_mesa_initialize_context_for_api(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)
+_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;
@@ -1028,25 +1028,6 @@ _mesa_initialize_context_for_api(struct gl_context *ctx,
 }
 
 
-/**
- * Initialize an OpenGL context.
- */
-GLboolean
-_mesa_initialize_context(struct gl_context *ctx,
-                         const struct gl_config *visual,
-                         struct gl_context *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 struct gl_context structure.
  * Note that the driver needs to pass in its dd_function_table here since
@@ -1063,11 +1044,11 @@ _mesa_initialize_context(struct gl_context *ctx,
  * \return pointer to a new __struct gl_contextRec or NULL if error.
  */
 struct gl_context *
-_mesa_create_context_for_api(gl_api api,
-			     const struct gl_config *visual,
-			     struct gl_context *share_list,
-			     const struct dd_function_table *driverFunctions,
-			     void *driverContext)
+_mesa_create_context(gl_api api,
+                     const struct gl_config *visual,
+                     struct gl_context *share_list,
+                     const struct dd_function_table *driverFunctions,
+                     void *driverContext)
 {
    struct gl_context *ctx;
 
@@ -1078,8 +1059,8 @@ _mesa_create_context_for_api(gl_api api,
    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 {
@@ -1089,22 +1070,6 @@ _mesa_create_context_for_api(gl_api api,
 }
 
 
-/**
- * Create an OpenGL context.
- */
-struct gl_context *
-_mesa_create_context(const struct gl_config *visual,
-		     struct gl_context *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.
  * 
diff --git a/mesalib/src/mesa/main/context.h b/mesalib/src/mesa/main/context.h
index bcadaea4f..4e391dde4 100644
--- a/mesalib/src/mesa/main/context.h
+++ b/mesalib/src/mesa/main/context.h
@@ -1,326 +1,313 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5.1
- *
- * Copyright (C) 1999-2006  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"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-/**
- * \file context.h
- * Mesa context and visual-related functions.
- *
- * There are three large Mesa data types/classes which are meant to be
- * used by device drivers:
- * - struct gl_context: this contains the Mesa rendering state
- * - struct gl_config:  this describes the color buffer (RGB vs. ci), whether or not
- *   there's a depth buffer, stencil buffer, etc.
- * - struct gl_framebuffer:  contains pointers to the depth buffer, stencil buffer,
- *   accum buffer and alpha buffers.
- *
- * These types should be encapsulated by corresponding device driver
- * data types.  See xmesa.h and xmesaP.h for an example.
- *
- * In OOP terms, struct gl_context, struct gl_config, and struct gl_framebuffer are base classes
- * which the device driver must derive from.
- *
- * The following functions create and destroy these data types.
- */
-
-
-#ifndef CONTEXT_H
-#define CONTEXT_H
-
-
-#include "imports.h"
-#include "mtypes.h"
-
-
-struct _glapi_table;
-
-
-/** \name Visual-related functions */
-/*@{*/
- 
-extern struct gl_config *
-_mesa_create_visual( GLboolean dbFlag,
-                     GLboolean stereoFlag,
-                     GLint redBits,
-                     GLint greenBits,
-                     GLint blueBits,
-                     GLint alphaBits,
-                     GLint depthBits,
-                     GLint stencilBits,
-                     GLint accumRedBits,
-                     GLint accumGreenBits,
-                     GLint accumBlueBits,
-                     GLint accumAlphaBits,
-                     GLint numSamples );
-
-extern GLboolean
-_mesa_initialize_visual( struct gl_config *v,
-                         GLboolean dbFlag,
-                         GLboolean stereoFlag,
-                         GLint redBits,
-                         GLint greenBits,
-                         GLint blueBits,
-                         GLint alphaBits,
-                         GLint depthBits,
-                         GLint stencilBits,
-                         GLint accumRedBits,
-                         GLint accumGreenBits,
-                         GLint accumBlueBits,
-                         GLint accumAlphaBits,
-                         GLint numSamples );
-
-extern void
-_mesa_destroy_visual( struct gl_config *vis );
-
-/*@}*/
-
-
-/** \name Context-related functions */
-/*@{*/
-
-extern struct gl_context *
-_mesa_create_context( const struct gl_config *visual,
-                      struct gl_context *share_list,
-                      const struct dd_function_table *driverFunctions,
-                      void *driverContext );
-
-extern GLboolean
-_mesa_initialize_context( struct gl_context *ctx,
-                          const struct gl_config *visual,
-                          struct gl_context *share_list,
-                          const struct dd_function_table *driverFunctions,
-                          void *driverContext );
-
-extern struct gl_context *
-_mesa_create_context_for_api(gl_api api,
-			     const struct gl_config *visual,
-			     struct gl_context *share_list,
-			     const struct dd_function_table *driverFunctions,
-			     void *driverContext);
-
-extern GLboolean
-_mesa_initialize_context_for_api(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);
-
-extern void
-_mesa_free_context_data( struct gl_context *ctx );
-
-extern void
-_mesa_destroy_context( struct gl_context *ctx );
-
-
-extern void
-_mesa_copy_context(const struct gl_context *src, struct gl_context *dst, GLuint mask);
-
-
-extern void
-_mesa_check_init_viewport(struct gl_context *ctx, GLuint width, GLuint height);
-
-extern GLboolean
-_mesa_make_current( struct gl_context *ctx, struct gl_framebuffer *drawBuffer,
-                    struct gl_framebuffer *readBuffer );
-
-extern GLboolean
-_mesa_share_state(struct gl_context *ctx, struct gl_context *ctxToShare);
-
-extern struct gl_context *
-_mesa_get_current_context(void);
-
-/*@}*/
-
-extern void
-_mesa_init_get_hash(struct gl_context *ctx);
-
-extern void
-_mesa_notifySwapBuffers(struct gl_context *gc);
-
-
-extern struct _glapi_table *
-_mesa_get_dispatch(struct gl_context *ctx);
-
-
-void
-_mesa_set_mvp_with_dp4( struct gl_context *ctx,
-                        GLboolean flag );
-
-
-extern GLboolean
-_mesa_valid_to_render(struct gl_context *ctx, const char *where);
-
-
-
-/** \name Miscellaneous */
-/*@{*/
-
-extern void
-_mesa_record_error( struct gl_context *ctx, GLenum error );
-
-
-extern void
-_mesa_finish(struct gl_context *ctx);
-
-extern void
-_mesa_flush(struct gl_context *ctx);
-
-
-extern void GLAPIENTRY
-_mesa_Finish( void );
-
-extern void GLAPIENTRY
-_mesa_Flush( void );
-
-/*@}*/
-
-
-/**
- * \name Macros for flushing buffered rendering commands before state changes,
- * checking if inside glBegin/glEnd, etc.
- */
-/*@{*/
-
-/**
- * Flush vertices.
- *
- * \param ctx GL context.
- * \param newstate new state.
- *
- * Checks if dd_function_table::NeedFlush is marked to flush stored vertices,
- * and calls dd_function_table::FlushVertices if so. Marks
- * __struct gl_contextRec::NewState with \p newstate.
- */
-#define FLUSH_VERTICES(ctx, newstate)				\
-do {								\
-   if (MESA_VERBOSE & VERBOSE_STATE)				\
-      _mesa_debug(ctx, "FLUSH_VERTICES in %s\n", MESA_FUNCTION);\
-   if (ctx->Driver.NeedFlush & FLUSH_STORED_VERTICES)		\
-      ctx->Driver.FlushVertices(ctx, FLUSH_STORED_VERTICES);	\
-   ctx->NewState |= newstate;					\
-} while (0)
-
-/**
- * Flush current state.
- *
- * \param ctx GL context.
- * \param newstate new state.
- *
- * Checks if dd_function_table::NeedFlush is marked to flush current state,
- * and calls dd_function_table::FlushVertices if so. Marks
- * __struct gl_contextRec::NewState with \p newstate.
- */
-#define FLUSH_CURRENT(ctx, newstate)				\
-do {								\
-   if (MESA_VERBOSE & VERBOSE_STATE)				\
-      _mesa_debug(ctx, "FLUSH_CURRENT in %s\n", MESA_FUNCTION);	\
-   if (ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT)		\
-      ctx->Driver.FlushVertices(ctx, FLUSH_UPDATE_CURRENT);	\
-   ctx->NewState |= newstate;					\
-} while (0)
-
-/**
- * Macro to assert that the API call was made outside the
- * glBegin()/glEnd() pair, with return value.
- * 
- * \param ctx GL context.
- * \param retval value to return value in case the assertion fails.
- */
-#define ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, retval)		\
-do {									\
-   if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {	\
-      _mesa_error(ctx, GL_INVALID_OPERATION, "Inside glBegin/glEnd");	\
-      return retval;							\
-   }									\
-} while (0)
-
-/**
- * Macro to assert that the API call was made outside the
- * glBegin()/glEnd() pair.
- * 
- * \param ctx GL context.
- */
-#define ASSERT_OUTSIDE_BEGIN_END(ctx)					\
-do {									\
-   if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {	\
-      _mesa_error(ctx, GL_INVALID_OPERATION, "Inside glBegin/glEnd");	\
-      return;								\
-   }									\
-} while (0)
-
-/**
- * Macro to assert that the API call was made outside the
- * glBegin()/glEnd() pair and flush the vertices.
- * 
- * \param ctx GL context.
- */
-#define ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx)				\
-do {									\
-   ASSERT_OUTSIDE_BEGIN_END(ctx);					\
-   FLUSH_VERTICES(ctx, 0);						\
-} while (0)
-
-/**
- * Macro to assert that the API call was made outside the
- * glBegin()/glEnd() pair and flush the vertices, with return value.
- * 
- * \param ctx GL context.
- * \param retval value to return value in case the assertion fails.
- */
-#define ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH_WITH_RETVAL(ctx, retval)	\
-do {									\
-   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, retval);			\
-   FLUSH_VERTICES(ctx, 0);						\
-} while (0)
-
-/*@}*/
-
-
-
-/**
- * Is the secondary color needed?
- */
-#define NEED_SECONDARY_COLOR(CTX)					\
-   (((CTX)->Light.Enabled &&						\
-     (CTX)->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)	\
-    || (CTX)->Fog.ColorSumEnabled					\
-    || ((CTX)->VertexProgram._Current &&				\
-        ((CTX)->VertexProgram._Current != (CTX)->VertexProgram._TnlProgram) &&    \
-        ((CTX)->VertexProgram._Current->Base.InputsRead & VERT_BIT_COLOR1)) \
-    || ((CTX)->FragmentProgram._Current &&				\
-        ((CTX)->FragmentProgram._Current != (CTX)->FragmentProgram._TexEnvProgram) &&  \
-        ((CTX)->FragmentProgram._Current->Base.InputsRead & FRAG_BIT_COL1)) \
-   )
-
-
-/**
- * Is RGBA LogicOp enabled?
- */
-#define RGBA_LOGICOP_ENABLED(CTX) \
-  ((CTX)->Color.ColorLogicOpEnabled || \
-   ((CTX)->Color.BlendEnabled && (CTX)->Color.Blend[0].EquationRGB == GL_LOGIC_OP))
-
-
-#endif /* CONTEXT_H */
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5.1
+ *
+ * Copyright (C) 1999-2006  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"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+/**
+ * \file context.h
+ * Mesa context and visual-related functions.
+ *
+ * There are three large Mesa data types/classes which are meant to be
+ * used by device drivers:
+ * - struct gl_context: this contains the Mesa rendering state
+ * - struct gl_config:  this describes the color buffer (RGB vs. ci), whether or not
+ *   there's a depth buffer, stencil buffer, etc.
+ * - struct gl_framebuffer:  contains pointers to the depth buffer, stencil buffer,
+ *   accum buffer and alpha buffers.
+ *
+ * These types should be encapsulated by corresponding device driver
+ * data types.  See xmesa.h and xmesaP.h for an example.
+ *
+ * In OOP terms, struct gl_context, struct gl_config, and struct gl_framebuffer are base classes
+ * which the device driver must derive from.
+ *
+ * The following functions create and destroy these data types.
+ */
+
+
+#ifndef CONTEXT_H
+#define CONTEXT_H
+
+
+#include "imports.h"
+#include "mtypes.h"
+
+
+struct _glapi_table;
+
+
+/** \name Visual-related functions */
+/*@{*/
+ 
+extern struct gl_config *
+_mesa_create_visual( GLboolean dbFlag,
+                     GLboolean stereoFlag,
+                     GLint redBits,
+                     GLint greenBits,
+                     GLint blueBits,
+                     GLint alphaBits,
+                     GLint depthBits,
+                     GLint stencilBits,
+                     GLint accumRedBits,
+                     GLint accumGreenBits,
+                     GLint accumBlueBits,
+                     GLint accumAlphaBits,
+                     GLint numSamples );
+
+extern GLboolean
+_mesa_initialize_visual( struct gl_config *v,
+                         GLboolean dbFlag,
+                         GLboolean stereoFlag,
+                         GLint redBits,
+                         GLint greenBits,
+                         GLint blueBits,
+                         GLint alphaBits,
+                         GLint depthBits,
+                         GLint stencilBits,
+                         GLint accumRedBits,
+                         GLint accumGreenBits,
+                         GLint accumBlueBits,
+                         GLint accumAlphaBits,
+                         GLint numSamples );
+
+extern void
+_mesa_destroy_visual( struct gl_config *vis );
+
+/*@}*/
+
+
+/** \name Context-related functions */
+/*@{*/
+
+extern GLboolean
+_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 );
+
+extern 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);
+
+extern void
+_mesa_free_context_data( struct gl_context *ctx );
+
+extern void
+_mesa_destroy_context( struct gl_context *ctx );
+
+
+extern void
+_mesa_copy_context(const struct gl_context *src, struct gl_context *dst, GLuint mask);
+
+
+extern void
+_mesa_check_init_viewport(struct gl_context *ctx, GLuint width, GLuint height);
+
+extern GLboolean
+_mesa_make_current( struct gl_context *ctx, struct gl_framebuffer *drawBuffer,
+                    struct gl_framebuffer *readBuffer );
+
+extern GLboolean
+_mesa_share_state(struct gl_context *ctx, struct gl_context *ctxToShare);
+
+extern struct gl_context *
+_mesa_get_current_context(void);
+
+/*@}*/
+
+extern void
+_mesa_init_get_hash(struct gl_context *ctx);
+
+extern void
+_mesa_notifySwapBuffers(struct gl_context *gc);
+
+
+extern struct _glapi_table *
+_mesa_get_dispatch(struct gl_context *ctx);
+
+
+void
+_mesa_set_mvp_with_dp4( struct gl_context *ctx,
+                        GLboolean flag );
+
+
+extern GLboolean
+_mesa_valid_to_render(struct gl_context *ctx, const char *where);
+
+
+
+/** \name Miscellaneous */
+/*@{*/
+
+extern void
+_mesa_record_error( struct gl_context *ctx, GLenum error );
+
+
+extern void
+_mesa_finish(struct gl_context *ctx);
+
+extern void
+_mesa_flush(struct gl_context *ctx);
+
+
+extern void GLAPIENTRY
+_mesa_Finish( void );
+
+extern void GLAPIENTRY
+_mesa_Flush( void );
+
+/*@}*/
+
+
+/**
+ * \name Macros for flushing buffered rendering commands before state changes,
+ * checking if inside glBegin/glEnd, etc.
+ */
+/*@{*/
+
+/**
+ * Flush vertices.
+ *
+ * \param ctx GL context.
+ * \param newstate new state.
+ *
+ * Checks if dd_function_table::NeedFlush is marked to flush stored vertices,
+ * and calls dd_function_table::FlushVertices if so. Marks
+ * __struct gl_contextRec::NewState with \p newstate.
+ */
+#define FLUSH_VERTICES(ctx, newstate)				\
+do {								\
+   if (MESA_VERBOSE & VERBOSE_STATE)				\
+      _mesa_debug(ctx, "FLUSH_VERTICES in %s\n", MESA_FUNCTION);\
+   if (ctx->Driver.NeedFlush & FLUSH_STORED_VERTICES)		\
+      ctx->Driver.FlushVertices(ctx, FLUSH_STORED_VERTICES);	\
+   ctx->NewState |= newstate;					\
+} while (0)
+
+/**
+ * Flush current state.
+ *
+ * \param ctx GL context.
+ * \param newstate new state.
+ *
+ * Checks if dd_function_table::NeedFlush is marked to flush current state,
+ * and calls dd_function_table::FlushVertices if so. Marks
+ * __struct gl_contextRec::NewState with \p newstate.
+ */
+#define FLUSH_CURRENT(ctx, newstate)				\
+do {								\
+   if (MESA_VERBOSE & VERBOSE_STATE)				\
+      _mesa_debug(ctx, "FLUSH_CURRENT in %s\n", MESA_FUNCTION);	\
+   if (ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT)		\
+      ctx->Driver.FlushVertices(ctx, FLUSH_UPDATE_CURRENT);	\
+   ctx->NewState |= newstate;					\
+} while (0)
+
+/**
+ * Macro to assert that the API call was made outside the
+ * glBegin()/glEnd() pair, with return value.
+ * 
+ * \param ctx GL context.
+ * \param retval value to return value in case the assertion fails.
+ */
+#define ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, retval)		\
+do {									\
+   if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {	\
+      _mesa_error(ctx, GL_INVALID_OPERATION, "Inside glBegin/glEnd");	\
+      return retval;							\
+   }									\
+} while (0)
+
+/**
+ * Macro to assert that the API call was made outside the
+ * glBegin()/glEnd() pair.
+ * 
+ * \param ctx GL context.
+ */
+#define ASSERT_OUTSIDE_BEGIN_END(ctx)					\
+do {									\
+   if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {	\
+      _mesa_error(ctx, GL_INVALID_OPERATION, "Inside glBegin/glEnd");	\
+      return;								\
+   }									\
+} while (0)
+
+/**
+ * Macro to assert that the API call was made outside the
+ * glBegin()/glEnd() pair and flush the vertices.
+ * 
+ * \param ctx GL context.
+ */
+#define ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx)				\
+do {									\
+   ASSERT_OUTSIDE_BEGIN_END(ctx);					\
+   FLUSH_VERTICES(ctx, 0);						\
+} while (0)
+
+/**
+ * Macro to assert that the API call was made outside the
+ * glBegin()/glEnd() pair and flush the vertices, with return value.
+ * 
+ * \param ctx GL context.
+ * \param retval value to return value in case the assertion fails.
+ */
+#define ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH_WITH_RETVAL(ctx, retval)	\
+do {									\
+   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, retval);			\
+   FLUSH_VERTICES(ctx, 0);						\
+} while (0)
+
+/*@}*/
+
+
+
+/**
+ * Is the secondary color needed?
+ */
+#define NEED_SECONDARY_COLOR(CTX)					\
+   (((CTX)->Light.Enabled &&						\
+     (CTX)->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)	\
+    || (CTX)->Fog.ColorSumEnabled					\
+    || ((CTX)->VertexProgram._Current &&				\
+        ((CTX)->VertexProgram._Current != (CTX)->VertexProgram._TnlProgram) &&    \
+        ((CTX)->VertexProgram._Current->Base.InputsRead & VERT_BIT_COLOR1)) \
+    || ((CTX)->FragmentProgram._Current &&				\
+        ((CTX)->FragmentProgram._Current != (CTX)->FragmentProgram._TexEnvProgram) &&  \
+        ((CTX)->FragmentProgram._Current->Base.InputsRead & FRAG_BIT_COL1)) \
+   )
+
+
+/**
+ * Is RGBA LogicOp enabled?
+ */
+#define RGBA_LOGICOP_ENABLED(CTX) \
+  ((CTX)->Color.ColorLogicOpEnabled || \
+   ((CTX)->Color.BlendEnabled && (CTX)->Color.Blend[0].EquationRGB == GL_LOGIC_OP))
+
+
+#endif /* CONTEXT_H */
diff --git a/mesalib/src/mesa/main/depth.c b/mesalib/src/mesa/main/depth.c
index fe1380e71..52c69a6bc 100644
--- a/mesalib/src/mesa/main/depth.c
+++ b/mesalib/src/mesa/main/depth.c
@@ -1,168 +1,174 @@
-/*
- * Mesa 3-D graphics library
- * Version:  7.1
- *
- * 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"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#include "glheader.h"
-#include "imports.h"
-#include "context.h"
-#include "depth.h"
-#include "enums.h"
-#include "macros.h"
-#include "mtypes.h"
-
-
-/**********************************************************************/
-/*****                          API Functions                     *****/
-/**********************************************************************/
-
-
-
-void GLAPIENTRY
-_mesa_ClearDepth( GLclampd depth )
-{
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   depth = CLAMP( depth, 0.0, 1.0 );
-
-   if (ctx->Depth.Clear == depth)
-      return;
-
-   FLUSH_VERTICES(ctx, _NEW_DEPTH);
-   ctx->Depth.Clear = depth;
-   if (ctx->Driver.ClearDepth)
-      (*ctx->Driver.ClearDepth)( ctx, ctx->Depth.Clear );
-}
-
-
-void GLAPIENTRY
-_mesa_ClearDepthf( GLclampf depth )
-{
-   _mesa_ClearDepth(depth);
-}
-
-
-void GLAPIENTRY
-_mesa_DepthFunc( GLenum func )
-{
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   if (MESA_VERBOSE & VERBOSE_API)
-      _mesa_debug(ctx, "glDepthFunc %s\n", _mesa_lookup_enum_by_nr(func));
-
-   switch (func) {
-   case GL_LESS:    /* (default) pass if incoming z < stored z */
-   case GL_GEQUAL:
-   case GL_LEQUAL:
-   case GL_GREATER:
-   case GL_NOTEQUAL:
-   case GL_EQUAL:
-   case GL_ALWAYS:
-   case GL_NEVER:
-      break;
-   default:
-      _mesa_error( ctx, GL_INVALID_ENUM, "glDepth.Func" );
-      return;
-   }
-
-   if (ctx->Depth.Func == func)
-      return;
-
-   FLUSH_VERTICES(ctx, _NEW_DEPTH);
-   ctx->Depth.Func = func;
-
-   if (ctx->Driver.DepthFunc)
-      ctx->Driver.DepthFunc( ctx, func );
-}
-
-
-
-void GLAPIENTRY
-_mesa_DepthMask( GLboolean flag )
-{
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   if (MESA_VERBOSE & VERBOSE_API)
-      _mesa_debug(ctx, "glDepthMask %d\n", flag);
-
-   /*
-    * GL_TRUE indicates depth buffer writing is enabled (default)
-    * GL_FALSE indicates depth buffer writing is disabled
-    */
-   if (ctx->Depth.Mask == flag)
-      return;
-
-   FLUSH_VERTICES(ctx, _NEW_DEPTH);
-   ctx->Depth.Mask = flag;
-
-   if (ctx->Driver.DepthMask)
-      ctx->Driver.DepthMask( ctx, flag );
-}
-
-
-
-/**
- * Specified by the GL_EXT_depth_bounds_test extension.
- */
-void GLAPIENTRY
-_mesa_DepthBoundsEXT( GLclampd zmin, GLclampd zmax )
-{
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   if (zmin > zmax) {
-      _mesa_error(ctx, GL_INVALID_VALUE, "glDepthBoundsEXT(zmin > zmax)");
-      return;
-   }
-
-   zmin = CLAMP(zmin, 0.0, 1.0);
-   zmax = CLAMP(zmax, 0.0, 1.0);
-
-   if (ctx->Depth.BoundsMin == zmin && ctx->Depth.BoundsMax == zmax)
-      return;
-
-   FLUSH_VERTICES(ctx, _NEW_DEPTH);
-   ctx->Depth.BoundsMin = (GLfloat) zmin;
-   ctx->Depth.BoundsMax = (GLfloat) zmax;
-}
-
-
-/**********************************************************************/
-/*****                      Initialization                        *****/
-/**********************************************************************/
-
-
-/**
- * Initialize the depth buffer attribute group in the given context.
- */
-void
-_mesa_init_depth(struct gl_context *ctx)
-{
-   ctx->Depth.Test = GL_FALSE;
-   ctx->Depth.Clear = 1.0;
-   ctx->Depth.Func = GL_LESS;
-   ctx->Depth.Mask = GL_TRUE;
-}
+/*
+ * Mesa 3-D graphics library
+ * Version:  7.1
+ *
+ * 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"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#include "glheader.h"
+#include "imports.h"
+#include "context.h"
+#include "depth.h"
+#include "enums.h"
+#include "macros.h"
+#include "mtypes.h"
+
+
+/**********************************************************************/
+/*****                          API Functions                     *****/
+/**********************************************************************/
+
+
+
+void GLAPIENTRY
+_mesa_ClearDepth( GLclampd depth )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glClearDepth(%f)\n", depth);
+
+   depth = CLAMP( depth, 0.0, 1.0 );
+
+   if (ctx->Depth.Clear == depth)
+      return;
+
+   FLUSH_VERTICES(ctx, _NEW_DEPTH);
+   ctx->Depth.Clear = depth;
+   if (ctx->Driver.ClearDepth)
+      (*ctx->Driver.ClearDepth)( ctx, ctx->Depth.Clear );
+}
+
+
+void GLAPIENTRY
+_mesa_ClearDepthf( GLclampf depth )
+{
+   _mesa_ClearDepth(depth);
+}
+
+
+void GLAPIENTRY
+_mesa_DepthFunc( GLenum func )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glDepthFunc %s\n", _mesa_lookup_enum_by_nr(func));
+
+   switch (func) {
+   case GL_LESS:    /* (default) pass if incoming z < stored z */
+   case GL_GEQUAL:
+   case GL_LEQUAL:
+   case GL_GREATER:
+   case GL_NOTEQUAL:
+   case GL_EQUAL:
+   case GL_ALWAYS:
+   case GL_NEVER:
+      break;
+   default:
+      _mesa_error( ctx, GL_INVALID_ENUM, "glDepth.Func" );
+      return;
+   }
+
+   if (ctx->Depth.Func == func)
+      return;
+
+   FLUSH_VERTICES(ctx, _NEW_DEPTH);
+   ctx->Depth.Func = func;
+
+   if (ctx->Driver.DepthFunc)
+      ctx->Driver.DepthFunc( ctx, func );
+}
+
+
+
+void GLAPIENTRY
+_mesa_DepthMask( GLboolean flag )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glDepthMask %d\n", flag);
+
+   /*
+    * GL_TRUE indicates depth buffer writing is enabled (default)
+    * GL_FALSE indicates depth buffer writing is disabled
+    */
+   if (ctx->Depth.Mask == flag)
+      return;
+
+   FLUSH_VERTICES(ctx, _NEW_DEPTH);
+   ctx->Depth.Mask = flag;
+
+   if (ctx->Driver.DepthMask)
+      ctx->Driver.DepthMask( ctx, flag );
+}
+
+
+
+/**
+ * Specified by the GL_EXT_depth_bounds_test extension.
+ */
+void GLAPIENTRY
+_mesa_DepthBoundsEXT( GLclampd zmin, GLclampd zmax )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glDepthBounds(%f, %f)\n", zmin, zmax);
+
+   if (zmin > zmax) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "glDepthBoundsEXT(zmin > zmax)");
+      return;
+   }
+
+   zmin = CLAMP(zmin, 0.0, 1.0);
+   zmax = CLAMP(zmax, 0.0, 1.0);
+
+   if (ctx->Depth.BoundsMin == zmin && ctx->Depth.BoundsMax == zmax)
+      return;
+
+   FLUSH_VERTICES(ctx, _NEW_DEPTH);
+   ctx->Depth.BoundsMin = (GLfloat) zmin;
+   ctx->Depth.BoundsMax = (GLfloat) zmax;
+}
+
+
+/**********************************************************************/
+/*****                      Initialization                        *****/
+/**********************************************************************/
+
+
+/**
+ * Initialize the depth buffer attribute group in the given context.
+ */
+void
+_mesa_init_depth(struct gl_context *ctx)
+{
+   ctx->Depth.Test = GL_FALSE;
+   ctx->Depth.Clear = 1.0;
+   ctx->Depth.Func = GL_LESS;
+   ctx->Depth.Mask = GL_TRUE;
+}
diff --git a/mesalib/src/mesa/main/hint.c b/mesalib/src/mesa/main/hint.c
index 96f5f4d6b..ff8d88fff 100644
--- a/mesalib/src/mesa/main/hint.c
+++ b/mesalib/src/mesa/main/hint.c
@@ -1,146 +1,147 @@
-
-/*
- * Mesa 3-D graphics library
- * Version:  4.1
- *
- * Copyright (C) 1999-2002  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"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#include "glheader.h"
-#include "enums.h"
-#include "context.h"
-#include "hint.h"
-#include "imports.h"
-#include "mtypes.h"
-
-
-
-void GLAPIENTRY
-_mesa_Hint( GLenum target, GLenum mode )
-{
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   if (MESA_VERBOSE & VERBOSE_API)
-      _mesa_debug(ctx, "glHint %s %d\n",
-                  _mesa_lookup_enum_by_nr(target), mode);
-
-   if (mode != GL_NICEST && mode != GL_FASTEST && mode != GL_DONT_CARE) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glHint(mode)");
-      return;
-   }
-
-   switch (target) {
-      case GL_FOG_HINT:
-         if (ctx->Hint.Fog == mode)
-	    return;
-	 FLUSH_VERTICES(ctx, _NEW_HINT);
-         ctx->Hint.Fog = mode;
-         break;
-      case GL_LINE_SMOOTH_HINT:
-         if (ctx->Hint.LineSmooth == mode)
-	    return;
-	 FLUSH_VERTICES(ctx, _NEW_HINT);
-         ctx->Hint.LineSmooth = mode;
-         break;
-      case GL_PERSPECTIVE_CORRECTION_HINT:
-         if (ctx->Hint.PerspectiveCorrection == mode)
-	    return;
-	 FLUSH_VERTICES(ctx, _NEW_HINT);
-         ctx->Hint.PerspectiveCorrection = mode;
-         break;
-      case GL_POINT_SMOOTH_HINT:
-         if (ctx->Hint.PointSmooth == mode)
-	    return;
-	 FLUSH_VERTICES(ctx, _NEW_HINT);
-         ctx->Hint.PointSmooth = mode;
-         break;
-      case GL_POLYGON_SMOOTH_HINT:
-         if (ctx->Hint.PolygonSmooth == mode)
-	    return;
-	 FLUSH_VERTICES(ctx, _NEW_HINT);
-         ctx->Hint.PolygonSmooth = mode;
-         break;
-
-      /* GL_EXT_clip_volume_hint */
-      case GL_CLIP_VOLUME_CLIPPING_HINT_EXT:
-         if (ctx->Hint.ClipVolumeClipping == mode)
-	    return;
-	 FLUSH_VERTICES(ctx, _NEW_HINT);
-         ctx->Hint.ClipVolumeClipping = mode;
-         break;
-
-      /* GL_ARB_texture_compression */
-      case GL_TEXTURE_COMPRESSION_HINT_ARB:
-	 if (ctx->Hint.TextureCompression == mode)
-	    return;
-	 FLUSH_VERTICES(ctx, _NEW_HINT);
-	 ctx->Hint.TextureCompression = mode;
-         break;
-
-      /* GL_SGIS_generate_mipmap */
-      case GL_GENERATE_MIPMAP_HINT_SGIS:
-         if (ctx->Hint.GenerateMipmap == mode)
-            return;
-	 FLUSH_VERTICES(ctx, _NEW_HINT);
-	 ctx->Hint.GenerateMipmap = mode;
-         break;
-
-      /* GL_ARB_fragment_shader */
-      case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB:
-         if (!ctx->Extensions.ARB_fragment_shader) {
-            _mesa_error(ctx, GL_INVALID_ENUM, "glHint(target)");
-            return;
-         }
-         if (ctx->Hint.FragmentShaderDerivative == mode)
-            return;
-         FLUSH_VERTICES(ctx, _NEW_HINT);
-         ctx->Hint.FragmentShaderDerivative = mode;
-         break;
-
-      default:
-         _mesa_error(ctx, GL_INVALID_ENUM, "glHint(target)");
-         return;
-   }
-
-   if (ctx->Driver.Hint) {
-      (*ctx->Driver.Hint)( ctx, target, mode );
-   }
-}
-
-
-/**********************************************************************/
-/*****                      Initialization                        *****/
-/**********************************************************************/
-
-void _mesa_init_hint( struct gl_context * ctx )
-{
-   /* Hint group */
-   ctx->Hint.PerspectiveCorrection = GL_DONT_CARE;
-   ctx->Hint.PointSmooth = GL_DONT_CARE;
-   ctx->Hint.LineSmooth = GL_DONT_CARE;
-   ctx->Hint.PolygonSmooth = GL_DONT_CARE;
-   ctx->Hint.Fog = GL_DONT_CARE;
-   ctx->Hint.ClipVolumeClipping = GL_DONT_CARE;
-   ctx->Hint.TextureCompression = GL_DONT_CARE;
-   ctx->Hint.GenerateMipmap = GL_DONT_CARE;
-   ctx->Hint.FragmentShaderDerivative = GL_DONT_CARE;
-}
+
+/*
+ * Mesa 3-D graphics library
+ * Version:  4.1
+ *
+ * Copyright (C) 1999-2002  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"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#include "glheader.h"
+#include "enums.h"
+#include "context.h"
+#include "hint.h"
+#include "imports.h"
+#include "mtypes.h"
+
+
+
+void GLAPIENTRY
+_mesa_Hint( GLenum target, GLenum mode )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glHint %s %s\n",
+                  _mesa_lookup_enum_by_nr(target),
+                  _mesa_lookup_enum_by_nr(mode));
+
+   if (mode != GL_NICEST && mode != GL_FASTEST && mode != GL_DONT_CARE) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glHint(mode)");
+      return;
+   }
+
+   switch (target) {
+      case GL_FOG_HINT:
+         if (ctx->Hint.Fog == mode)
+	    return;
+	 FLUSH_VERTICES(ctx, _NEW_HINT);
+         ctx->Hint.Fog = mode;
+         break;
+      case GL_LINE_SMOOTH_HINT:
+         if (ctx->Hint.LineSmooth == mode)
+	    return;
+	 FLUSH_VERTICES(ctx, _NEW_HINT);
+         ctx->Hint.LineSmooth = mode;
+         break;
+      case GL_PERSPECTIVE_CORRECTION_HINT:
+         if (ctx->Hint.PerspectiveCorrection == mode)
+	    return;
+	 FLUSH_VERTICES(ctx, _NEW_HINT);
+         ctx->Hint.PerspectiveCorrection = mode;
+         break;
+      case GL_POINT_SMOOTH_HINT:
+         if (ctx->Hint.PointSmooth == mode)
+	    return;
+	 FLUSH_VERTICES(ctx, _NEW_HINT);
+         ctx->Hint.PointSmooth = mode;
+         break;
+      case GL_POLYGON_SMOOTH_HINT:
+         if (ctx->Hint.PolygonSmooth == mode)
+	    return;
+	 FLUSH_VERTICES(ctx, _NEW_HINT);
+         ctx->Hint.PolygonSmooth = mode;
+         break;
+
+      /* GL_EXT_clip_volume_hint */
+      case GL_CLIP_VOLUME_CLIPPING_HINT_EXT:
+         if (ctx->Hint.ClipVolumeClipping == mode)
+	    return;
+	 FLUSH_VERTICES(ctx, _NEW_HINT);
+         ctx->Hint.ClipVolumeClipping = mode;
+         break;
+
+      /* GL_ARB_texture_compression */
+      case GL_TEXTURE_COMPRESSION_HINT_ARB:
+	 if (ctx->Hint.TextureCompression == mode)
+	    return;
+	 FLUSH_VERTICES(ctx, _NEW_HINT);
+	 ctx->Hint.TextureCompression = mode;
+         break;
+
+      /* GL_SGIS_generate_mipmap */
+      case GL_GENERATE_MIPMAP_HINT_SGIS:
+         if (ctx->Hint.GenerateMipmap == mode)
+            return;
+	 FLUSH_VERTICES(ctx, _NEW_HINT);
+	 ctx->Hint.GenerateMipmap = mode;
+         break;
+
+      /* GL_ARB_fragment_shader */
+      case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB:
+         if (!ctx->Extensions.ARB_fragment_shader) {
+            _mesa_error(ctx, GL_INVALID_ENUM, "glHint(target)");
+            return;
+         }
+         if (ctx->Hint.FragmentShaderDerivative == mode)
+            return;
+         FLUSH_VERTICES(ctx, _NEW_HINT);
+         ctx->Hint.FragmentShaderDerivative = mode;
+         break;
+
+      default:
+         _mesa_error(ctx, GL_INVALID_ENUM, "glHint(target)");
+         return;
+   }
+
+   if (ctx->Driver.Hint) {
+      (*ctx->Driver.Hint)( ctx, target, mode );
+   }
+}
+
+
+/**********************************************************************/
+/*****                      Initialization                        *****/
+/**********************************************************************/
+
+void _mesa_init_hint( struct gl_context * ctx )
+{
+   /* Hint group */
+   ctx->Hint.PerspectiveCorrection = GL_DONT_CARE;
+   ctx->Hint.PointSmooth = GL_DONT_CARE;
+   ctx->Hint.LineSmooth = GL_DONT_CARE;
+   ctx->Hint.PolygonSmooth = GL_DONT_CARE;
+   ctx->Hint.Fog = GL_DONT_CARE;
+   ctx->Hint.ClipVolumeClipping = GL_DONT_CARE;
+   ctx->Hint.TextureCompression = GL_DONT_CARE;
+   ctx->Hint.GenerateMipmap = GL_DONT_CARE;
+   ctx->Hint.FragmentShaderDerivative = GL_DONT_CARE;
+}
diff --git a/mesalib/src/mesa/main/lines.c b/mesalib/src/mesa/main/lines.c
index 79385cd75..79bf5679d 100644
--- a/mesalib/src/mesa/main/lines.c
+++ b/mesalib/src/mesa/main/lines.c
@@ -1,111 +1,117 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5.3
- *
- * Copyright (C) 1999-2006  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"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#include "glheader.h"
-#include "context.h"
-#include "lines.h"
-#include "macros.h"
-#include "mtypes.h"
-
-
-/**
- * Set the line width.
- *
- * \param width line width in pixels.
- *
- * \sa glLineWidth().
- */
-void GLAPIENTRY
-_mesa_LineWidth( GLfloat width )
-{
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   if (width<=0.0) {
-      _mesa_error( ctx, GL_INVALID_VALUE, "glLineWidth" );
-      return;
-   }
-
-   if (ctx->Line.Width == width)
-      return;
-
-   FLUSH_VERTICES(ctx, _NEW_LINE);
-   ctx->Line.Width = width;
-
-   if (ctx->Driver.LineWidth)
-      ctx->Driver.LineWidth(ctx, width);
-}
-
-
-/**
- * Set the line stipple pattern.
- *
- * \param factor pattern scale factor.
- * \param pattern bit pattern.
- * 
- * \sa glLineStipple().
- *
- * Updates gl_line_attrib::StippleFactor and gl_line_attrib::StipplePattern. On
- * change flushes the vertices and notifies the driver via
- * the dd_function_table::LineStipple callback.
- */
-void GLAPIENTRY
-_mesa_LineStipple( GLint factor, GLushort pattern )
-{
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   factor = CLAMP( factor, 1, 256 );
-
-   if (ctx->Line.StippleFactor == factor &&
-       ctx->Line.StipplePattern == pattern)
-      return;
-
-   FLUSH_VERTICES(ctx, _NEW_LINE);
-   ctx->Line.StippleFactor = factor;
-   ctx->Line.StipplePattern = pattern;
-
-   if (ctx->Driver.LineStipple)
-      ctx->Driver.LineStipple( ctx, factor, pattern );
-}
-
-
-/**
- * Initialize the context line state.
- *
- * \param ctx GL context.
- *
- * Initializes __struct gl_contextRec::Line and line related constants in
- * __struct gl_contextRec::Const.
- */
-void GLAPIENTRY
-_mesa_init_line( struct gl_context * ctx )
-{
-   ctx->Line.SmoothFlag = GL_FALSE;
-   ctx->Line.StippleFlag = GL_FALSE;
-   ctx->Line.Width = 1.0;
-   ctx->Line.StipplePattern = 0xffff;
-   ctx->Line.StippleFactor = 1;
-}
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5.3
+ *
+ * Copyright (C) 1999-2006  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"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#include "glheader.h"
+#include "context.h"
+#include "lines.h"
+#include "macros.h"
+#include "mtypes.h"
+
+
+/**
+ * Set the line width.
+ *
+ * \param width line width in pixels.
+ *
+ * \sa glLineWidth().
+ */
+void GLAPIENTRY
+_mesa_LineWidth( GLfloat width )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glLineWidth %f\n", width);
+
+   if (width<=0.0) {
+      _mesa_error( ctx, GL_INVALID_VALUE, "glLineWidth" );
+      return;
+   }
+
+   if (ctx->Line.Width == width)
+      return;
+
+   FLUSH_VERTICES(ctx, _NEW_LINE);
+   ctx->Line.Width = width;
+
+   if (ctx->Driver.LineWidth)
+      ctx->Driver.LineWidth(ctx, width);
+}
+
+
+/**
+ * Set the line stipple pattern.
+ *
+ * \param factor pattern scale factor.
+ * \param pattern bit pattern.
+ * 
+ * \sa glLineStipple().
+ *
+ * Updates gl_line_attrib::StippleFactor and gl_line_attrib::StipplePattern. On
+ * change flushes the vertices and notifies the driver via
+ * the dd_function_table::LineStipple callback.
+ */
+void GLAPIENTRY
+_mesa_LineStipple( GLint factor, GLushort pattern )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glLineStipple %d %u\n", factor, pattern);
+
+   factor = CLAMP( factor, 1, 256 );
+
+   if (ctx->Line.StippleFactor == factor &&
+       ctx->Line.StipplePattern == pattern)
+      return;
+
+   FLUSH_VERTICES(ctx, _NEW_LINE);
+   ctx->Line.StippleFactor = factor;
+   ctx->Line.StipplePattern = pattern;
+
+   if (ctx->Driver.LineStipple)
+      ctx->Driver.LineStipple( ctx, factor, pattern );
+}
+
+
+/**
+ * Initialize the context line state.
+ *
+ * \param ctx GL context.
+ *
+ * Initializes __struct gl_contextRec::Line and line related constants in
+ * __struct gl_contextRec::Const.
+ */
+void GLAPIENTRY
+_mesa_init_line( struct gl_context * ctx )
+{
+   ctx->Line.SmoothFlag = GL_FALSE;
+   ctx->Line.StippleFlag = GL_FALSE;
+   ctx->Line.Width = 1.0;
+   ctx->Line.StipplePattern = 0xffff;
+   ctx->Line.StippleFactor = 1;
+}
diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h
index 4e7621239..6f0aac6ee 100644
--- a/mesalib/src/mesa/main/mtypes.h
+++ b/mesalib/src/mesa/main/mtypes.h
@@ -84,23 +84,8 @@
 /*@{*/
 typedef GLuint64 GLbitfield64;
 
-#define BITFIELD64_ONE         1ULL
-#define BITFIELD64_ALLONES     ~0ULL
-
 /** Set a single bit */
-#define BITFIELD64_BIT(b)      (BITFIELD64_ONE << (b))
-
-/** Set a mask of the least significant \c b bits */
-#define BITFIELD64_MASK(b)     (((b) >= 64) ? BITFIELD64_ALLONES : \
-				(BITFIELD64_BIT(b) - 1))
-
-/**
- * Set all bits from l (low bit) to h (high bit), inclusive.
- *
- * \note \C BITFIELD_64_RANGE(0, 63) return 64 set bits.
- */
-#define BITFIELD64_RANGE(l, h) (BITFIELD64_MASK((h) + 1) & ~BITFIELD64_MASK(l))
-/*@}*/
+#define BITFIELD64_BIT(b)      (1ULL << (b))
 
 
 /**
diff --git a/mesalib/src/mesa/main/queryobj.c b/mesalib/src/mesa/main/queryobj.c
index 1c45c38b9..fa35c6ce5 100644
--- a/mesalib/src/mesa/main/queryobj.c
+++ b/mesalib/src/mesa/main/queryobj.c
@@ -1,585 +1,623 @@
-/*
- * Mesa 3-D graphics library
- * Version:  7.1
- *
- * 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"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#include "glheader.h"
-#include "context.h"
-#include "hash.h"
-#include "imports.h"
-#include "queryobj.h"
-#include "mfeatures.h"
-#include "mtypes.h"
-#include "main/dispatch.h"
-
-
-#if FEATURE_queryobj
-
-
-/**
- * Allocate a new query object.  This is a fallback routine called via
- * ctx->Driver.NewQueryObject().
- * \param ctx - rendering context
- * \param id - the new object's ID
- * \return pointer to new query_object object or NULL if out of memory.
- */
-static struct gl_query_object *
-_mesa_new_query_object(struct gl_context *ctx, GLuint id)
-{
-   struct gl_query_object *q = MALLOC_STRUCT(gl_query_object);
-   (void) ctx;
-   if (q) {
-      q->Id = id;
-      q->Result = 0;
-      q->Active = GL_FALSE;
-      q->Ready = GL_TRUE;   /* correct, see spec */
-   }
-   return q;
-}
-
-
-/**
- * Begin a query.  Software driver fallback.
- * Called via ctx->Driver.BeginQuery().
- */
-static void
-_mesa_begin_query(struct gl_context *ctx, struct gl_query_object *q)
-{
-   /* no-op */
-}
-
-
-/**
- * End a query.  Software driver fallback.
- * Called via ctx->Driver.EndQuery().
- */
-static void
-_mesa_end_query(struct gl_context *ctx, struct gl_query_object *q)
-{
-   q->Ready = GL_TRUE;
-}
-
-
-/**
- * Wait for query to complete.  Software driver fallback.
- * Called via ctx->Driver.WaitQuery().
- */
-static void
-_mesa_wait_query(struct gl_context *ctx, struct gl_query_object *q)
-{
-   /* For software drivers, _mesa_end_query() should have completed the query.
-    * For real hardware, implement a proper WaitQuery() driver function,
-    * which may require issuing a flush.
-    */
-   assert(q->Ready);
-}
-
-
-/**
- * Check if a query results are ready.  Software driver fallback.
- * Called via ctx->Driver.CheckQuery().
- */
-static void
-_mesa_check_query(struct gl_context *ctx, struct gl_query_object *q)
-{
-   /* No-op for sw rendering.
-    * HW drivers may need to flush at this time.
-    */
-}
-
-
-/**
- * Delete a query object.  Called via ctx->Driver.DeleteQuery().
- * Not removed from hash table here.
- */
-static void
-_mesa_delete_query(struct gl_context *ctx, struct gl_query_object *q)
-{
-   free(q);
-}
-
-
-void
-_mesa_init_query_object_functions(struct dd_function_table *driver)
-{
-   driver->NewQueryObject = _mesa_new_query_object;
-   driver->DeleteQuery = _mesa_delete_query;
-   driver->BeginQuery = _mesa_begin_query;
-   driver->EndQuery = _mesa_end_query;
-   driver->WaitQuery = _mesa_wait_query;
-   driver->CheckQuery = _mesa_check_query;
-}
-
-
-/**
- * Return pointer to the query object binding point for the given target.
- * \return NULL if invalid target, else the address of binding point
- */
-static struct gl_query_object **
-get_query_binding_point(struct gl_context *ctx, GLenum target)
-{
-   switch (target) {
-   case GL_SAMPLES_PASSED_ARB:
-      if (ctx->Extensions.ARB_occlusion_query)
-         return &ctx->Query.CurrentOcclusionObject;
-      else
-         return NULL;
-   case GL_ANY_SAMPLES_PASSED:
-      if (ctx->Extensions.ARB_occlusion_query2)
-         return &ctx->Query.CurrentOcclusionObject;
-      else
-         return NULL;
-   case GL_TIME_ELAPSED_EXT:
-      if (ctx->Extensions.EXT_timer_query)
-         return &ctx->Query.CurrentTimerObject;
-      else
-         return NULL;
-#if FEATURE_EXT_transform_feedback
-   case GL_PRIMITIVES_GENERATED:
-      if (ctx->Extensions.EXT_transform_feedback)
-         return &ctx->Query.PrimitivesGenerated;
-      else
-         return NULL;
-   case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
-      if (ctx->Extensions.EXT_transform_feedback)
-         return &ctx->Query.PrimitivesWritten;
-      else
-         return NULL;
-#endif
-   default:
-      return NULL;
-   }
-}
-
-
-void GLAPIENTRY
-_mesa_GenQueriesARB(GLsizei n, GLuint *ids)
-{
-   GLuint first;
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   if (n < 0) {
-      _mesa_error(ctx, GL_INVALID_VALUE, "glGenQueriesARB(n < 0)");
-      return;
-   }
-
-   /* No query objects can be active at this time! */
-   if (ctx->Query.CurrentOcclusionObject ||
-       ctx->Query.CurrentTimerObject) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "glGenQueriesARB");
-      return;
-   }
-
-   first = _mesa_HashFindFreeKeyBlock(ctx->Query.QueryObjects, n);
-   if (first) {
-      GLsizei i;
-      for (i = 0; i < n; i++) {
-         struct gl_query_object *q
-            = ctx->Driver.NewQueryObject(ctx, first + i);
-         if (!q) {
-            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenQueriesARB");
-            return;
-         }
-         ids[i] = first + i;
-         _mesa_HashInsert(ctx->Query.QueryObjects, first + i, q);
-      }
-   }
-}
-
-
-void GLAPIENTRY
-_mesa_DeleteQueriesARB(GLsizei n, const GLuint *ids)
-{
-   GLint i;
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   if (n < 0) {
-      _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteQueriesARB(n < 0)");
-      return;
-   }
-
-   /* No query objects can be active at this time! */
-   if (ctx->Query.CurrentOcclusionObject ||
-       ctx->Query.CurrentTimerObject) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "glDeleteQueriesARB");
-      return;
-   }
-
-   for (i = 0; i < n; i++) {
-      if (ids[i] > 0) {
-         struct gl_query_object *q = _mesa_lookup_query_object(ctx, ids[i]);
-         if (q) {
-            ASSERT(!q->Active); /* should be caught earlier */
-            _mesa_HashRemove(ctx->Query.QueryObjects, ids[i]);
-            ctx->Driver.DeleteQuery(ctx, q);
-         }
-      }
-   }
-}
-
-
-GLboolean GLAPIENTRY
-_mesa_IsQueryARB(GLuint id)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
-
-   if (id && _mesa_lookup_query_object(ctx, id))
-      return GL_TRUE;
-   else
-      return GL_FALSE;
-}
-
-
-static void GLAPIENTRY
-_mesa_BeginQueryARB(GLenum target, GLuint id)
-{
-   struct gl_query_object *q, **bindpt;
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   FLUSH_VERTICES(ctx, _NEW_DEPTH);
-
-   bindpt = get_query_binding_point(ctx, target);
-   if (!bindpt) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glBeginQueryARB(target)");
-      return;
-   }
-
-   if (id == 0) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginQueryARB(id==0)");
-      return;
-   }
-
-   q = _mesa_lookup_query_object(ctx, id);
-   if (!q) {
-      /* create new object */
-      q = ctx->Driver.NewQueryObject(ctx, id);
-      if (!q) {
-         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBeginQueryARB");
-         return;
-      }
-      _mesa_HashInsert(ctx->Query.QueryObjects, id, q);
-   }
-   else {
-      /* pre-existing object */
-      if (q->Active) {
-         _mesa_error(ctx, GL_INVALID_OPERATION,
-                     "glBeginQueryARB(query already active)");
-         return;
-      }
-   }
-
-   q->Target = target;
-   q->Active = GL_TRUE;
-   q->Result = 0;
-   q->Ready = GL_FALSE;
-
-   /* XXX should probably refcount query objects */
-   *bindpt = q;
-
-   ctx->Driver.BeginQuery(ctx, q);
-}
-
-
-static void GLAPIENTRY
-_mesa_EndQueryARB(GLenum target)
-{
-   struct gl_query_object *q, **bindpt;
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   FLUSH_VERTICES(ctx, _NEW_DEPTH);
-
-   bindpt = get_query_binding_point(ctx, target);
-   if (!bindpt) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)");
-      return;
-   }
-
-   /* XXX should probably refcount query objects */
-   q = *bindpt;
-   *bindpt = NULL;
-
-   if (!q || !q->Active) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glEndQueryARB(no matching glBeginQueryARB)");
-      return;
-   }
-
-   q->Active = GL_FALSE;
-   ctx->Driver.EndQuery(ctx, q);
-}
-
-
-void GLAPIENTRY
-_mesa_GetQueryivARB(GLenum target, GLenum pname, GLint *params)
-{
-   struct gl_query_object *q, **bindpt;
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   bindpt = get_query_binding_point(ctx, target);
-   if (!bindpt) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryARB(target)");
-      return;
-   }
-
-   q = *bindpt;
-
-   switch (pname) {
-      case GL_QUERY_COUNTER_BITS_ARB:
-         *params = 8 * sizeof(q->Result);
-         break;
-      case GL_CURRENT_QUERY_ARB:
-         *params = q ? q->Id : 0;
-         break;
-      default:
-         _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryivARB(pname)");
-         return;
-   }
-}
-
-
-void GLAPIENTRY
-_mesa_GetQueryObjectivARB(GLuint id, GLenum pname, GLint *params)
-{
-   struct gl_query_object *q = NULL;
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   if (id)
-      q = _mesa_lookup_query_object(ctx, id);
-
-   if (!q || q->Active) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glGetQueryObjectivARB(id=%d is invalid or active)", id);
-      return;
-   }
-
-   switch (pname) {
-      case GL_QUERY_RESULT_ARB:
-         if (!q->Ready)
-            ctx->Driver.WaitQuery(ctx, q);
-         /* if result is too large for returned type, clamp to max value */
-         if (q->Target == GL_ANY_SAMPLES_PASSED) {
-            if (q->Result)
-               *params = GL_TRUE;
-            else
-               *params = GL_FALSE;
-         } else {
-            if (q->Result > 0x7fffffff) {
-               *params = 0x7fffffff;
-            }
-            else {
-               *params = (GLint)q->Result;
-            }
-         }
-         break;
-      case GL_QUERY_RESULT_AVAILABLE_ARB:
-	 if (!q->Ready)
-	    ctx->Driver.CheckQuery( ctx, q );
-         *params = q->Ready;
-         break;
-      default:
-         _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectivARB(pname)");
-         return;
-   }
-}
-
-
-void GLAPIENTRY
-_mesa_GetQueryObjectuivARB(GLuint id, GLenum pname, GLuint *params)
-{
-   struct gl_query_object *q = NULL;
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   if (id)
-      q = _mesa_lookup_query_object(ctx, id);
-
-   if (!q || q->Active) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glGetQueryObjectuivARB(id=%d is invalid or active)", id);
-      return;
-   }
-
-   switch (pname) {
-      case GL_QUERY_RESULT_ARB:
-         if (!q->Ready)
-            ctx->Driver.WaitQuery(ctx, q);
-         /* if result is too large for returned type, clamp to max value */
-         if (q->Target == GL_ANY_SAMPLES_PASSED) {
-            if (q->Result)
-               *params = GL_TRUE;
-            else
-               *params = GL_FALSE;
-         } else {
-            if (q->Result > 0xffffffff) {
-               *params = 0xffffffff;
-            }
-            else {
-               *params = (GLuint)q->Result;
-            }
-         }
-         break;
-      case GL_QUERY_RESULT_AVAILABLE_ARB:
-	 if (!q->Ready)
-	    ctx->Driver.CheckQuery( ctx, q );
-         *params = q->Ready;
-         break;
-      default:
-         _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectuivARB(pname)");
-         return;
-   }
-}
-
-
-/**
- * New with GL_EXT_timer_query
- */
-static void GLAPIENTRY
-_mesa_GetQueryObjecti64vEXT(GLuint id, GLenum pname, GLint64EXT *params)
-{
-   struct gl_query_object *q = NULL;
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   if (id)
-      q = _mesa_lookup_query_object(ctx, id);
-
-   if (!q || q->Active) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glGetQueryObjectui64vARB(id=%d is invalid or active)", id);
-      return;
-   }
-
-   switch (pname) {
-      case GL_QUERY_RESULT_ARB:
-         if (!q->Ready)
-            ctx->Driver.WaitQuery(ctx, q);
-         *params = q->Result;
-         break;
-      case GL_QUERY_RESULT_AVAILABLE_ARB:
-	 if (!q->Ready)
-	    ctx->Driver.CheckQuery( ctx, q );
-         *params = q->Ready;
-         break;
-      default:
-         _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjecti64vARB(pname)");
-         return;
-   }
-}
-
-
-/**
- * New with GL_EXT_timer_query
- */
-static void GLAPIENTRY
-_mesa_GetQueryObjectui64vEXT(GLuint id, GLenum pname, GLuint64EXT *params)
-{
-   struct gl_query_object *q = NULL;
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   if (id)
-      q = _mesa_lookup_query_object(ctx, id);
-
-   if (!q || q->Active) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glGetQueryObjectuui64vARB(id=%d is invalid or active)", id);
-      return;
-   }
-
-   switch (pname) {
-      case GL_QUERY_RESULT_ARB:
-         if (!q->Ready)
-            ctx->Driver.WaitQuery(ctx, q);
-         *params = q->Result;
-         break;
-      case GL_QUERY_RESULT_AVAILABLE_ARB:
-	 if (!q->Ready)
-	    ctx->Driver.CheckQuery( ctx, q );
-         *params = q->Ready;
-         break;
-      default:
-         _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectui64vARB(pname)");
-         return;
-   }
-}
-
-
-void
-_mesa_init_queryobj_dispatch(struct _glapi_table *disp)
-{
-   SET_GenQueriesARB(disp, _mesa_GenQueriesARB);
-   SET_DeleteQueriesARB(disp, _mesa_DeleteQueriesARB);
-   SET_IsQueryARB(disp, _mesa_IsQueryARB);
-   SET_BeginQueryARB(disp, _mesa_BeginQueryARB);
-   SET_EndQueryARB(disp, _mesa_EndQueryARB);
-   SET_GetQueryivARB(disp, _mesa_GetQueryivARB);
-   SET_GetQueryObjectivARB(disp, _mesa_GetQueryObjectivARB);
-   SET_GetQueryObjectuivARB(disp, _mesa_GetQueryObjectuivARB);
-
-   SET_GetQueryObjecti64vEXT(disp, _mesa_GetQueryObjecti64vEXT);
-   SET_GetQueryObjectui64vEXT(disp, _mesa_GetQueryObjectui64vEXT);
-}
-
-
-#endif /* FEATURE_queryobj */
-
-
-/**
- * Allocate/init the context state related to query objects.
- */
-void
-_mesa_init_queryobj(struct gl_context *ctx)
-{
-   ctx->Query.QueryObjects = _mesa_NewHashTable();
-   ctx->Query.CurrentOcclusionObject = NULL;
-}
-
-
-/**
- * Callback for deleting a query object.  Called by _mesa_HashDeleteAll().
- */
-static void
-delete_queryobj_cb(GLuint id, void *data, void *userData)
-{
-   struct gl_query_object *q= (struct gl_query_object *) data;
-   struct gl_context *ctx = (struct gl_context *)userData;
-   ctx->Driver.DeleteQuery(ctx, q);
-}
-
-
-/**
- * Free the context state related to query objects.
- */
-void
-_mesa_free_queryobj_data(struct gl_context *ctx)
-{
-   _mesa_HashDeleteAll(ctx->Query.QueryObjects, delete_queryobj_cb, ctx);
-   _mesa_DeleteHashTable(ctx->Query.QueryObjects);
-}
+/*
+ * Mesa 3-D graphics library
+ * Version:  7.1
+ *
+ * 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"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#include "glheader.h"
+#include "context.h"
+#include "enums.h"
+#include "hash.h"
+#include "imports.h"
+#include "queryobj.h"
+#include "mfeatures.h"
+#include "mtypes.h"
+#include "main/dispatch.h"
+
+
+#if FEATURE_queryobj
+
+
+/**
+ * Allocate a new query object.  This is a fallback routine called via
+ * ctx->Driver.NewQueryObject().
+ * \param ctx - rendering context
+ * \param id - the new object's ID
+ * \return pointer to new query_object object or NULL if out of memory.
+ */
+static struct gl_query_object *
+_mesa_new_query_object(struct gl_context *ctx, GLuint id)
+{
+   struct gl_query_object *q = MALLOC_STRUCT(gl_query_object);
+   (void) ctx;
+   if (q) {
+      q->Id = id;
+      q->Result = 0;
+      q->Active = GL_FALSE;
+      q->Ready = GL_TRUE;   /* correct, see spec */
+   }
+   return q;
+}
+
+
+/**
+ * Begin a query.  Software driver fallback.
+ * Called via ctx->Driver.BeginQuery().
+ */
+static void
+_mesa_begin_query(struct gl_context *ctx, struct gl_query_object *q)
+{
+   /* no-op */
+}
+
+
+/**
+ * End a query.  Software driver fallback.
+ * Called via ctx->Driver.EndQuery().
+ */
+static void
+_mesa_end_query(struct gl_context *ctx, struct gl_query_object *q)
+{
+   q->Ready = GL_TRUE;
+}
+
+
+/**
+ * Wait for query to complete.  Software driver fallback.
+ * Called via ctx->Driver.WaitQuery().
+ */
+static void
+_mesa_wait_query(struct gl_context *ctx, struct gl_query_object *q)
+{
+   /* For software drivers, _mesa_end_query() should have completed the query.
+    * For real hardware, implement a proper WaitQuery() driver function,
+    * which may require issuing a flush.
+    */
+   assert(q->Ready);
+}
+
+
+/**
+ * Check if a query results are ready.  Software driver fallback.
+ * Called via ctx->Driver.CheckQuery().
+ */
+static void
+_mesa_check_query(struct gl_context *ctx, struct gl_query_object *q)
+{
+   /* No-op for sw rendering.
+    * HW drivers may need to flush at this time.
+    */
+}
+
+
+/**
+ * Delete a query object.  Called via ctx->Driver.DeleteQuery().
+ * Not removed from hash table here.
+ */
+static void
+_mesa_delete_query(struct gl_context *ctx, struct gl_query_object *q)
+{
+   free(q);
+}
+
+
+void
+_mesa_init_query_object_functions(struct dd_function_table *driver)
+{
+   driver->NewQueryObject = _mesa_new_query_object;
+   driver->DeleteQuery = _mesa_delete_query;
+   driver->BeginQuery = _mesa_begin_query;
+   driver->EndQuery = _mesa_end_query;
+   driver->WaitQuery = _mesa_wait_query;
+   driver->CheckQuery = _mesa_check_query;
+}
+
+
+/**
+ * Return pointer to the query object binding point for the given target.
+ * \return NULL if invalid target, else the address of binding point
+ */
+static struct gl_query_object **
+get_query_binding_point(struct gl_context *ctx, GLenum target)
+{
+   switch (target) {
+   case GL_SAMPLES_PASSED_ARB:
+      if (ctx->Extensions.ARB_occlusion_query)
+         return &ctx->Query.CurrentOcclusionObject;
+      else
+         return NULL;
+   case GL_ANY_SAMPLES_PASSED:
+      if (ctx->Extensions.ARB_occlusion_query2)
+         return &ctx->Query.CurrentOcclusionObject;
+      else
+         return NULL;
+   case GL_TIME_ELAPSED_EXT:
+      if (ctx->Extensions.EXT_timer_query)
+         return &ctx->Query.CurrentTimerObject;
+      else
+         return NULL;
+#if FEATURE_EXT_transform_feedback
+   case GL_PRIMITIVES_GENERATED:
+      if (ctx->Extensions.EXT_transform_feedback)
+         return &ctx->Query.PrimitivesGenerated;
+      else
+         return NULL;
+   case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
+      if (ctx->Extensions.EXT_transform_feedback)
+         return &ctx->Query.PrimitivesWritten;
+      else
+         return NULL;
+#endif
+   default:
+      return NULL;
+   }
+}
+
+
+void GLAPIENTRY
+_mesa_GenQueriesARB(GLsizei n, GLuint *ids)
+{
+   GLuint first;
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glGenQueries(%d)\n", n);
+
+   if (n < 0) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "glGenQueriesARB(n < 0)");
+      return;
+   }
+
+   /* No query objects can be active at this time! */
+   if (ctx->Query.CurrentOcclusionObject ||
+       ctx->Query.CurrentTimerObject) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "glGenQueriesARB");
+      return;
+   }
+
+   first = _mesa_HashFindFreeKeyBlock(ctx->Query.QueryObjects, n);
+   if (first) {
+      GLsizei i;
+      for (i = 0; i < n; i++) {
+         struct gl_query_object *q
+            = ctx->Driver.NewQueryObject(ctx, first + i);
+         if (!q) {
+            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenQueriesARB");
+            return;
+         }
+         ids[i] = first + i;
+         _mesa_HashInsert(ctx->Query.QueryObjects, first + i, q);
+      }
+   }
+}
+
+
+void GLAPIENTRY
+_mesa_DeleteQueriesARB(GLsizei n, const GLuint *ids)
+{
+   GLint i;
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glDeleeteQueries(%d)\n", n);
+
+   if (n < 0) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteQueriesARB(n < 0)");
+      return;
+   }
+
+   /* No query objects can be active at this time! */
+   if (ctx->Query.CurrentOcclusionObject ||
+       ctx->Query.CurrentTimerObject) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "glDeleteQueriesARB");
+      return;
+   }
+
+   for (i = 0; i < n; i++) {
+      if (ids[i] > 0) {
+         struct gl_query_object *q = _mesa_lookup_query_object(ctx, ids[i]);
+         if (q) {
+            ASSERT(!q->Active); /* should be caught earlier */
+            _mesa_HashRemove(ctx->Query.QueryObjects, ids[i]);
+            ctx->Driver.DeleteQuery(ctx, q);
+         }
+      }
+   }
+}
+
+
+GLboolean GLAPIENTRY
+_mesa_IsQueryARB(GLuint id)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
+
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glIsQuery(%u)\n", id);
+
+   if (id && _mesa_lookup_query_object(ctx, id))
+      return GL_TRUE;
+   else
+      return GL_FALSE;
+}
+
+
+static void GLAPIENTRY
+_mesa_BeginQueryARB(GLenum target, GLuint id)
+{
+   struct gl_query_object *q, **bindpt;
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glBeginQuery(%s, %u)\n",
+                  _mesa_lookup_enum_by_nr(target), id);
+
+   FLUSH_VERTICES(ctx, _NEW_DEPTH);
+
+   bindpt = get_query_binding_point(ctx, target);
+   if (!bindpt) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glBeginQueryARB(target)");
+      return;
+   }
+
+   if (id == 0) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginQueryARB(id==0)");
+      return;
+   }
+
+   q = _mesa_lookup_query_object(ctx, id);
+   if (!q) {
+      /* create new object */
+      q = ctx->Driver.NewQueryObject(ctx, id);
+      if (!q) {
+         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBeginQueryARB");
+         return;
+      }
+      _mesa_HashInsert(ctx->Query.QueryObjects, id, q);
+   }
+   else {
+      /* pre-existing object */
+      if (q->Active) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glBeginQueryARB(query already active)");
+         return;
+      }
+   }
+
+   q->Target = target;
+   q->Active = GL_TRUE;
+   q->Result = 0;
+   q->Ready = GL_FALSE;
+
+   /* XXX should probably refcount query objects */
+   *bindpt = q;
+
+   ctx->Driver.BeginQuery(ctx, q);
+}
+
+
+static void GLAPIENTRY
+_mesa_EndQueryARB(GLenum target)
+{
+   struct gl_query_object *q, **bindpt;
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glEndQuery(%s)\n", _mesa_lookup_enum_by_nr(target));
+
+   FLUSH_VERTICES(ctx, _NEW_DEPTH);
+
+   bindpt = get_query_binding_point(ctx, target);
+   if (!bindpt) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)");
+      return;
+   }
+
+   /* XXX should probably refcount query objects */
+   q = *bindpt;
+   *bindpt = NULL;
+
+   if (!q || !q->Active) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glEndQueryARB(no matching glBeginQueryARB)");
+      return;
+   }
+
+   q->Active = GL_FALSE;
+   ctx->Driver.EndQuery(ctx, q);
+}
+
+
+void GLAPIENTRY
+_mesa_GetQueryivARB(GLenum target, GLenum pname, GLint *params)
+{
+   struct gl_query_object *q, **bindpt;
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glGetQueryiv(%s, %s)\n",
+                  _mesa_lookup_enum_by_nr(target),
+                  _mesa_lookup_enum_by_nr(pname));
+
+   bindpt = get_query_binding_point(ctx, target);
+   if (!bindpt) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryARB(target)");
+      return;
+   }
+
+   q = *bindpt;
+
+   switch (pname) {
+      case GL_QUERY_COUNTER_BITS_ARB:
+         *params = 8 * sizeof(q->Result);
+         break;
+      case GL_CURRENT_QUERY_ARB:
+         *params = q ? q->Id : 0;
+         break;
+      default:
+         _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryivARB(pname)");
+         return;
+   }
+}
+
+
+void GLAPIENTRY
+_mesa_GetQueryObjectivARB(GLuint id, GLenum pname, GLint *params)
+{
+   struct gl_query_object *q = NULL;
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glGetQueryObjectiv(%u, %s)\n", id,
+                  _mesa_lookup_enum_by_nr(pname));
+
+   if (id)
+      q = _mesa_lookup_query_object(ctx, id);
+
+   if (!q || q->Active) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glGetQueryObjectivARB(id=%d is invalid or active)", id);
+      return;
+   }
+
+   switch (pname) {
+      case GL_QUERY_RESULT_ARB:
+         if (!q->Ready)
+            ctx->Driver.WaitQuery(ctx, q);
+         /* if result is too large for returned type, clamp to max value */
+         if (q->Target == GL_ANY_SAMPLES_PASSED) {
+            if (q->Result)
+               *params = GL_TRUE;
+            else
+               *params = GL_FALSE;
+         } else {
+            if (q->Result > 0x7fffffff) {
+               *params = 0x7fffffff;
+            }
+            else {
+               *params = (GLint)q->Result;
+            }
+         }
+         break;
+      case GL_QUERY_RESULT_AVAILABLE_ARB:
+	 if (!q->Ready)
+	    ctx->Driver.CheckQuery( ctx, q );
+         *params = q->Ready;
+         break;
+      default:
+         _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectivARB(pname)");
+         return;
+   }
+}
+
+
+void GLAPIENTRY
+_mesa_GetQueryObjectuivARB(GLuint id, GLenum pname, GLuint *params)
+{
+   struct gl_query_object *q = NULL;
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glGetQueryObjectuiv(%u, %s)\n", id,
+                  _mesa_lookup_enum_by_nr(pname));
+
+   if (id)
+      q = _mesa_lookup_query_object(ctx, id);
+
+   if (!q || q->Active) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glGetQueryObjectuivARB(id=%d is invalid or active)", id);
+      return;
+   }
+
+   switch (pname) {
+      case GL_QUERY_RESULT_ARB:
+         if (!q->Ready)
+            ctx->Driver.WaitQuery(ctx, q);
+         /* if result is too large for returned type, clamp to max value */
+         if (q->Target == GL_ANY_SAMPLES_PASSED) {
+            if (q->Result)
+               *params = GL_TRUE;
+            else
+               *params = GL_FALSE;
+         } else {
+            if (q->Result > 0xffffffff) {
+               *params = 0xffffffff;
+            }
+            else {
+               *params = (GLuint)q->Result;
+            }
+         }
+         break;
+      case GL_QUERY_RESULT_AVAILABLE_ARB:
+	 if (!q->Ready)
+	    ctx->Driver.CheckQuery( ctx, q );
+         *params = q->Ready;
+         break;
+      default:
+         _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectuivARB(pname)");
+         return;
+   }
+}
+
+
+/**
+ * New with GL_EXT_timer_query
+ */
+static void GLAPIENTRY
+_mesa_GetQueryObjecti64vEXT(GLuint id, GLenum pname, GLint64EXT *params)
+{
+   struct gl_query_object *q = NULL;
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glGetQueryObjecti64v(%u, %s)\n", id,
+                  _mesa_lookup_enum_by_nr(pname));
+
+   if (id)
+      q = _mesa_lookup_query_object(ctx, id);
+
+   if (!q || q->Active) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glGetQueryObjectui64vARB(id=%d is invalid or active)", id);
+      return;
+   }
+
+   switch (pname) {
+      case GL_QUERY_RESULT_ARB:
+         if (!q->Ready)
+            ctx->Driver.WaitQuery(ctx, q);
+         *params = q->Result;
+         break;
+      case GL_QUERY_RESULT_AVAILABLE_ARB:
+	 if (!q->Ready)
+	    ctx->Driver.CheckQuery( ctx, q );
+         *params = q->Ready;
+         break;
+      default:
+         _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjecti64vARB(pname)");
+         return;
+   }
+}
+
+
+/**
+ * New with GL_EXT_timer_query
+ */
+static void GLAPIENTRY
+_mesa_GetQueryObjectui64vEXT(GLuint id, GLenum pname, GLuint64EXT *params)
+{
+   struct gl_query_object *q = NULL;
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glGetQueryObjectui64v(%u, %s)\n", id,
+                  _mesa_lookup_enum_by_nr(pname));
+
+   if (id)
+      q = _mesa_lookup_query_object(ctx, id);
+
+   if (!q || q->Active) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glGetQueryObjectuui64vARB(id=%d is invalid or active)", id);
+      return;
+   }
+
+   switch (pname) {
+      case GL_QUERY_RESULT_ARB:
+         if (!q->Ready)
+            ctx->Driver.WaitQuery(ctx, q);
+         *params = q->Result;
+         break;
+      case GL_QUERY_RESULT_AVAILABLE_ARB:
+	 if (!q->Ready)
+	    ctx->Driver.CheckQuery( ctx, q );
+         *params = q->Ready;
+         break;
+      default:
+         _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectui64vARB(pname)");
+         return;
+   }
+}
+
+
+void
+_mesa_init_queryobj_dispatch(struct _glapi_table *disp)
+{
+   SET_GenQueriesARB(disp, _mesa_GenQueriesARB);
+   SET_DeleteQueriesARB(disp, _mesa_DeleteQueriesARB);
+   SET_IsQueryARB(disp, _mesa_IsQueryARB);
+   SET_BeginQueryARB(disp, _mesa_BeginQueryARB);
+   SET_EndQueryARB(disp, _mesa_EndQueryARB);
+   SET_GetQueryivARB(disp, _mesa_GetQueryivARB);
+   SET_GetQueryObjectivARB(disp, _mesa_GetQueryObjectivARB);
+   SET_GetQueryObjectuivARB(disp, _mesa_GetQueryObjectuivARB);
+
+   SET_GetQueryObjecti64vEXT(disp, _mesa_GetQueryObjecti64vEXT);
+   SET_GetQueryObjectui64vEXT(disp, _mesa_GetQueryObjectui64vEXT);
+}
+
+
+#endif /* FEATURE_queryobj */
+
+
+/**
+ * Allocate/init the context state related to query objects.
+ */
+void
+_mesa_init_queryobj(struct gl_context *ctx)
+{
+   ctx->Query.QueryObjects = _mesa_NewHashTable();
+   ctx->Query.CurrentOcclusionObject = NULL;
+}
+
+
+/**
+ * Callback for deleting a query object.  Called by _mesa_HashDeleteAll().
+ */
+static void
+delete_queryobj_cb(GLuint id, void *data, void *userData)
+{
+   struct gl_query_object *q= (struct gl_query_object *) data;
+   struct gl_context *ctx = (struct gl_context *)userData;
+   ctx->Driver.DeleteQuery(ctx, q);
+}
+
+
+/**
+ * Free the context state related to query objects.
+ */
+void
+_mesa_free_queryobj_data(struct gl_context *ctx)
+{
+   _mesa_HashDeleteAll(ctx->Query.QueryObjects, delete_queryobj_cb, ctx);
+   _mesa_DeleteHashTable(ctx->Query.QueryObjects);
+}
diff --git a/mesalib/src/mesa/main/shaderapi.c b/mesalib/src/mesa/main/shaderapi.c
index f2b8aa449..11b0f884f 100644
--- a/mesalib/src/mesa/main/shaderapi.c
+++ b/mesalib/src/mesa/main/shaderapi.c
@@ -1184,6 +1184,8 @@ void GLAPIENTRY
 _mesa_CompileShaderARB(GLhandleARB shaderObj)
 {
    GET_CURRENT_CONTEXT(ctx);
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glCompileShader %u\n", shaderObj);
    compile_shader(ctx, shaderObj);
 }
 
@@ -1192,6 +1194,8 @@ GLuint GLAPIENTRY
 _mesa_CreateShader(GLenum type)
 {
    GET_CURRENT_CONTEXT(ctx);
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glCreateShader %s\n", _mesa_lookup_enum_by_nr(type));
    return create_shader(ctx, type);
 }
 
@@ -1208,6 +1212,8 @@ GLuint GLAPIENTRY
 _mesa_CreateProgram(void)
 {
    GET_CURRENT_CONTEXT(ctx);
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glCreateProgram\n");
    return create_shader_program(ctx);
 }
 
@@ -1223,6 +1229,11 @@ _mesa_CreateProgramObjectARB(void)
 void GLAPIENTRY
 _mesa_DeleteObjectARB(GLhandleARB obj)
 {
+   if (MESA_VERBOSE & VERBOSE_API) {
+      GET_CURRENT_CONTEXT(ctx);
+      _mesa_debug(ctx, "glDeleteObjectARB(%u)\n", obj);
+   }
+
    if (obj) {
       GET_CURRENT_CONTEXT(ctx);
       if (is_program(ctx, obj)) {
diff --git a/mesalib/src/mesa/main/stencil.c b/mesalib/src/mesa/main/stencil.c
index c63b14d27..d898bf1d7 100644
--- a/mesalib/src/mesa/main/stencil.c
+++ b/mesalib/src/mesa/main/stencil.c
@@ -1,590 +1,614 @@
-/*
- * Mesa 3-D graphics library
- * Version:  7.1
- *
- * 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"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-/**
- * \file stencil.c
- * Stencil operations.
- *
- * Note: There's some conflict between GL_EXT_stencil_two_side and
- * OpenGL 2.0's two-sided stencil feature.
- *
- * With GL_EXT_stencil_two_side, calling glStencilOp/Func/Mask() only the
- * front OR back face state (as set by glActiveStencilFaceEXT) is set.
- *
- * But with OpenGL 2.0, calling glStencilOp/Func/Mask() sets BOTH the
- * front AND back state.
- *
- * Also, note that GL_ATI_separate_stencil is different as well:
- * glStencilFuncSeparateATI(GLenum frontfunc, GLenum backfunc, ...)  vs.
- * glStencilFuncSeparate(GLenum face, GLenum func, ...).
- *
- * This problem is solved by keeping three sets of stencil state:
- *  state[0] = GL_FRONT state.
- *  state[1] = OpenGL 2.0 / GL_ATI_separate_stencil GL_BACK state.
- *  state[2] = GL_EXT_stencil_two_side GL_BACK state.
- */
-
-
-#include "glheader.h"
-#include "imports.h"
-#include "context.h"
-#include "macros.h"
-#include "stencil.h"
-#include "mtypes.h"
-
-
-static GLboolean
-validate_stencil_op(struct gl_context *ctx, GLenum op)
-{
-   switch (op) {
-   case GL_KEEP:
-   case GL_ZERO:
-   case GL_REPLACE:
-   case GL_INCR:
-   case GL_DECR:
-   case GL_INVERT:
-      return GL_TRUE;
-   case GL_INCR_WRAP_EXT:
-   case GL_DECR_WRAP_EXT:
-      if (ctx->Extensions.EXT_stencil_wrap) {
-         return GL_TRUE;
-      }
-      /* FALL-THROUGH */
-   default:
-      return GL_FALSE;
-   }
-}
-
-
-static GLboolean
-validate_stencil_func(struct gl_context *ctx, GLenum func)
-{
-   switch (func) {
-   case GL_NEVER:
-   case GL_LESS:
-   case GL_LEQUAL:
-   case GL_GREATER:
-   case GL_GEQUAL:
-   case GL_EQUAL:
-   case GL_NOTEQUAL:
-   case GL_ALWAYS:
-      return GL_TRUE;
-   default:
-      return GL_FALSE;
-   }
-}
-
-
-/**
- * Set the clear value for the stencil buffer.
- *
- * \param s clear value.
- *
- * \sa glClearStencil().
- *
- * Updates gl_stencil_attrib::Clear. On change
- * flushes the vertices and notifies the driver via
- * the dd_function_table::ClearStencil callback.
- */
-void GLAPIENTRY
-_mesa_ClearStencil( GLint s )
-{
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   if (ctx->Stencil.Clear == (GLuint) s)
-      return;
-
-   FLUSH_VERTICES(ctx, _NEW_STENCIL);
-   ctx->Stencil.Clear = (GLuint) s;
-
-   if (ctx->Driver.ClearStencil) {
-      ctx->Driver.ClearStencil( ctx, s );
-   }
-}
-
-
-/**
- * Set the function and reference value for stencil testing.
- *
- * \param frontfunc front test function.
- * \param backfunc back test function.
- * \param ref front and back reference value.
- * \param mask front and back bitmask.
- *
- * \sa glStencilFunc().
- *
- * Verifies the parameters and updates the respective values in
- * __struct gl_contextRec::Stencil. On change flushes the vertices and notifies the
- * driver via the dd_function_table::StencilFunc callback.
- */
-void GLAPIENTRY
-_mesa_StencilFuncSeparateATI( GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask )
-{
-   GET_CURRENT_CONTEXT(ctx);
-   const GLint stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1;
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   if (!validate_stencil_func(ctx, frontfunc)) {
-      _mesa_error(ctx, GL_INVALID_ENUM,
-                  "glStencilFuncSeparateATI(frontfunc)");
-      return;
-   }
-   if (!validate_stencil_func(ctx, backfunc)) {
-      _mesa_error(ctx, GL_INVALID_ENUM,
-                  "glStencilFuncSeparateATI(backfunc)");
-      return;
-   }
-
-   ref = CLAMP( ref, 0, stencilMax );
-
-   /* set both front and back state */
-   if (ctx->Stencil.Function[0] == frontfunc &&
-       ctx->Stencil.Function[1] == backfunc &&
-       ctx->Stencil.ValueMask[0] == mask &&
-       ctx->Stencil.ValueMask[1] == mask &&
-       ctx->Stencil.Ref[0] == ref &&
-       ctx->Stencil.Ref[1] == ref)
-      return;
-   FLUSH_VERTICES(ctx, _NEW_STENCIL);
-   ctx->Stencil.Function[0]  = frontfunc;
-   ctx->Stencil.Function[1]  = backfunc;
-   ctx->Stencil.Ref[0]       = ctx->Stencil.Ref[1]       = ref;
-   ctx->Stencil.ValueMask[0] = ctx->Stencil.ValueMask[1] = mask;
-   if (ctx->Driver.StencilFuncSeparate) {
-      ctx->Driver.StencilFuncSeparate(ctx, GL_FRONT,
-                                      frontfunc, ref, mask);
-      ctx->Driver.StencilFuncSeparate(ctx, GL_BACK,
-                                      backfunc, ref, mask);
-   }
-}
-
-
-/**
- * Set the function and reference value for stencil testing.
- *
- * \param func test function.
- * \param ref reference value.
- * \param mask bitmask.
- *
- * \sa glStencilFunc().
- *
- * Verifies the parameters and updates the respective values in
- * __struct gl_contextRec::Stencil. On change flushes the vertices and notifies the
- * driver via the dd_function_table::StencilFunc callback.
- */
-void GLAPIENTRY
-_mesa_StencilFunc( GLenum func, GLint ref, GLuint mask )
-{
-   GET_CURRENT_CONTEXT(ctx);
-   const GLint stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1;
-   const GLint face = ctx->Stencil.ActiveFace;
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   if (!validate_stencil_func(ctx, func)) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFunc(func)");
-      return;
-   }
-
-   ref = CLAMP( ref, 0, stencilMax );
-
-   if (face != 0) {
-      if (ctx->Stencil.Function[face] == func &&
-          ctx->Stencil.ValueMask[face] == mask &&
-          ctx->Stencil.Ref[face] == ref)
-         return;
-      FLUSH_VERTICES(ctx, _NEW_STENCIL);
-      ctx->Stencil.Function[face] = func;
-      ctx->Stencil.Ref[face] = ref;
-      ctx->Stencil.ValueMask[face] = mask;
-
-      /* Only propagate the change to the driver if EXT_stencil_two_side
-       * is enabled.
-       */
-      if (ctx->Driver.StencilFuncSeparate && ctx->Stencil.TestTwoSide) {
-         ctx->Driver.StencilFuncSeparate(ctx, GL_BACK, func, ref, mask);
-      }
-   }
-   else {
-      /* set both front and back state */
-      if (ctx->Stencil.Function[0] == func &&
-          ctx->Stencil.Function[1] == func &&
-          ctx->Stencil.ValueMask[0] == mask &&
-          ctx->Stencil.ValueMask[1] == mask &&
-          ctx->Stencil.Ref[0] == ref &&
-          ctx->Stencil.Ref[1] == ref)
-         return;
-      FLUSH_VERTICES(ctx, _NEW_STENCIL);
-      ctx->Stencil.Function[0]  = ctx->Stencil.Function[1]  = func;
-      ctx->Stencil.Ref[0]       = ctx->Stencil.Ref[1]       = ref;
-      ctx->Stencil.ValueMask[0] = ctx->Stencil.ValueMask[1] = mask;
-      if (ctx->Driver.StencilFuncSeparate) {
-         ctx->Driver.StencilFuncSeparate(ctx,
-					 ((ctx->Stencil.TestTwoSide)
-					  ? GL_FRONT : GL_FRONT_AND_BACK),
-                                         func, ref, mask);
-      }
-   }
-}
-
-
-/**
- * Set the stencil writing mask.
- *
- * \param mask bit-mask to enable/disable writing of individual bits in the
- * stencil planes.
- *
- * \sa glStencilMask().
- *
- * Updates gl_stencil_attrib::WriteMask. On change flushes the vertices and
- * notifies the driver via the dd_function_table::StencilMask callback.
- */
-void GLAPIENTRY
-_mesa_StencilMask( GLuint mask )
-{
-   GET_CURRENT_CONTEXT(ctx);
-   const GLint face = ctx->Stencil.ActiveFace;
-
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   if (face != 0) {
-      /* Only modify the EXT_stencil_two_side back-face state.
-       */
-      if (ctx->Stencil.WriteMask[face] == mask)
-         return;
-      FLUSH_VERTICES(ctx, _NEW_STENCIL);
-      ctx->Stencil.WriteMask[face] = mask;
-
-      /* Only propagate the change to the driver if EXT_stencil_two_side
-       * is enabled.
-       */
-      if (ctx->Driver.StencilMaskSeparate && ctx->Stencil.TestTwoSide) {
-         ctx->Driver.StencilMaskSeparate(ctx, GL_BACK, mask);
-      }
-   }
-   else {
-      /* set both front and back state */
-      if (ctx->Stencil.WriteMask[0] == mask &&
-          ctx->Stencil.WriteMask[1] == mask)
-         return;
-      FLUSH_VERTICES(ctx, _NEW_STENCIL);
-      ctx->Stencil.WriteMask[0] = ctx->Stencil.WriteMask[1] = mask;
-      if (ctx->Driver.StencilMaskSeparate) {
-         ctx->Driver.StencilMaskSeparate(ctx,
-					 ((ctx->Stencil.TestTwoSide)
-					  ? GL_FRONT : GL_FRONT_AND_BACK),
-					  mask);
-      }
-   }
-}
-
-
-/**
- * Set the stencil test actions.
- *
- * \param fail action to take when stencil test fails.
- * \param zfail action to take when stencil test passes, but depth test fails.
- * \param zpass action to take when stencil test passes and the depth test
- * passes (or depth testing is not enabled).
- * 
- * \sa glStencilOp().
- * 
- * Verifies the parameters and updates the respective fields in
- * __struct gl_contextRec::Stencil. On change flushes the vertices and notifies the
- * driver via the dd_function_table::StencilOp callback.
- */
-void GLAPIENTRY
-_mesa_StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   const GLint face = ctx->Stencil.ActiveFace;
-
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   if (!validate_stencil_op(ctx, fail)) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp(sfail)");
-      return;
-   }
-   if (!validate_stencil_op(ctx, zfail)) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp(zfail)");
-      return;
-   }
-   if (!validate_stencil_op(ctx, zpass)) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp(zpass)");
-      return;
-   }
-
-   if (face != 0) {
-      /* only set active face state */
-      if (ctx->Stencil.ZFailFunc[face] == zfail &&
-          ctx->Stencil.ZPassFunc[face] == zpass &&
-          ctx->Stencil.FailFunc[face] == fail)
-         return;
-      FLUSH_VERTICES(ctx, _NEW_STENCIL);
-      ctx->Stencil.ZFailFunc[face] = zfail;
-      ctx->Stencil.ZPassFunc[face] = zpass;
-      ctx->Stencil.FailFunc[face] = fail;
-
-      /* Only propagate the change to the driver if EXT_stencil_two_side
-       * is enabled.
-       */
-      if (ctx->Driver.StencilOpSeparate && ctx->Stencil.TestTwoSide) {
-         ctx->Driver.StencilOpSeparate(ctx, GL_BACK, fail, zfail, zpass);
-      }
-   }
-   else {
-      /* set both front and back state */
-      if (ctx->Stencil.ZFailFunc[0] == zfail &&
-          ctx->Stencil.ZFailFunc[1] == zfail &&
-          ctx->Stencil.ZPassFunc[0] == zpass &&
-          ctx->Stencil.ZPassFunc[1] == zpass &&
-          ctx->Stencil.FailFunc[0] == fail &&
-          ctx->Stencil.FailFunc[1] == fail)
-         return;
-      FLUSH_VERTICES(ctx, _NEW_STENCIL);
-      ctx->Stencil.ZFailFunc[0] = ctx->Stencil.ZFailFunc[1] = zfail;
-      ctx->Stencil.ZPassFunc[0] = ctx->Stencil.ZPassFunc[1] = zpass;
-      ctx->Stencil.FailFunc[0]  = ctx->Stencil.FailFunc[1]  = fail;
-      if (ctx->Driver.StencilOpSeparate) {
-         ctx->Driver.StencilOpSeparate(ctx,
-				       ((ctx->Stencil.TestTwoSide)
-					? GL_FRONT : GL_FRONT_AND_BACK),
-                                       fail, zfail, zpass);
-      }
-   }
-}
-
-
-
-#if _HAVE_FULL_GL
-/* GL_EXT_stencil_two_side */
-void GLAPIENTRY
-_mesa_ActiveStencilFaceEXT(GLenum face)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   if (!ctx->Extensions.EXT_stencil_two_side) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "glActiveStencilFaceEXT");
-      return;
-   }
-
-   if (face == GL_FRONT || face == GL_BACK) {
-      FLUSH_VERTICES(ctx, _NEW_STENCIL);
-      ctx->Stencil.ActiveFace = (face == GL_FRONT) ? 0 : 2;
-   }
-   else {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glActiveStencilFaceEXT(face)");
-   }
-}
-#endif
-
-
-
-/**
- * OpenGL 2.0 function.
- * \todo Make StencilOp() call this function.  And eventually remove the
- * ctx->Driver.StencilOp function and use ctx->Driver.StencilOpSeparate
- * instead.
- */
-void GLAPIENTRY
-_mesa_StencilOpSeparate(GLenum face, GLenum sfail, GLenum zfail, GLenum zpass)
-{
-   GLboolean set = GL_FALSE;
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   if (!validate_stencil_op(ctx, sfail)) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(sfail)");
-      return;
-   }
-   if (!validate_stencil_op(ctx, zfail)) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(zfail)");
-      return;
-   }
-   if (!validate_stencil_op(ctx, zpass)) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(zpass)");
-      return;
-   }
-   if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(face)");
-      return;
-   }
-
-   if (face != GL_BACK) {
-      /* set front */
-      if (ctx->Stencil.ZFailFunc[0] != zfail ||
-          ctx->Stencil.ZPassFunc[0] != zpass ||
-          ctx->Stencil.FailFunc[0] != sfail){
-         FLUSH_VERTICES(ctx, _NEW_STENCIL);
-         ctx->Stencil.ZFailFunc[0] = zfail;
-         ctx->Stencil.ZPassFunc[0] = zpass;
-         ctx->Stencil.FailFunc[0] = sfail;
-         set = GL_TRUE;
-      }
-   }
-   if (face != GL_FRONT) {
-      /* set back */
-      if (ctx->Stencil.ZFailFunc[1] != zfail ||
-          ctx->Stencil.ZPassFunc[1] != zpass ||
-          ctx->Stencil.FailFunc[1] != sfail) {
-         FLUSH_VERTICES(ctx, _NEW_STENCIL);
-         ctx->Stencil.ZFailFunc[1] = zfail;
-         ctx->Stencil.ZPassFunc[1] = zpass;
-         ctx->Stencil.FailFunc[1] = sfail;
-         set = GL_TRUE;
-      }
-   }
-   if (set && ctx->Driver.StencilOpSeparate) {
-      ctx->Driver.StencilOpSeparate(ctx, face, sfail, zfail, zpass);
-   }
-}
-
-
-/* OpenGL 2.0 */
-void GLAPIENTRY
-_mesa_StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   const GLint stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1;
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFuncSeparate(face)");
-      return;
-   }
-   if (!validate_stencil_func(ctx, func)) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFuncSeparate(func)");
-      return;
-   }
-
-   ref = CLAMP(ref, 0, stencilMax);
-
-   FLUSH_VERTICES(ctx, _NEW_STENCIL);
-
-   if (face != GL_BACK) {
-      /* set front */
-      ctx->Stencil.Function[0] = func;
-      ctx->Stencil.Ref[0] = ref;
-      ctx->Stencil.ValueMask[0] = mask;
-   }
-   if (face != GL_FRONT) {
-      /* set back */
-      ctx->Stencil.Function[1] = func;
-      ctx->Stencil.Ref[1] = ref;
-      ctx->Stencil.ValueMask[1] = mask;
-   }
-   if (ctx->Driver.StencilFuncSeparate) {
-      ctx->Driver.StencilFuncSeparate(ctx, face, func, ref, mask);
-   }
-}
-
-
-/* OpenGL 2.0 */
-void GLAPIENTRY
-_mesa_StencilMaskSeparate(GLenum face, GLuint mask)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
-   if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glStencilaMaskSeparate(face)");
-      return;
-   }
-
-   FLUSH_VERTICES(ctx, _NEW_STENCIL);
-
-   if (face != GL_BACK) {
-      ctx->Stencil.WriteMask[0] = mask;
-   }
-   if (face != GL_FRONT) {
-      ctx->Stencil.WriteMask[1] = mask;
-   }
-   if (ctx->Driver.StencilMaskSeparate) {
-      ctx->Driver.StencilMaskSeparate(ctx, face, mask);
-   }
-}
-
-
-/**
- * Update derived stencil state.
- */
-void
-_mesa_update_stencil(struct gl_context *ctx)
-{
-   const GLint face = ctx->Stencil._BackFace;
-
-   ctx->Stencil._Enabled = (ctx->Stencil.Enabled &&
-                            ctx->DrawBuffer->Visual.stencilBits > 0);
-
-    ctx->Stencil._TestTwoSide =
-       ctx->Stencil._Enabled &&
-       (ctx->Stencil.Function[0] != ctx->Stencil.Function[face] ||
-	ctx->Stencil.FailFunc[0] != ctx->Stencil.FailFunc[face] ||
-	ctx->Stencil.ZPassFunc[0] != ctx->Stencil.ZPassFunc[face] ||
-	ctx->Stencil.ZFailFunc[0] != ctx->Stencil.ZFailFunc[face] ||
-	ctx->Stencil.Ref[0] != ctx->Stencil.Ref[face] ||
-	ctx->Stencil.ValueMask[0] != ctx->Stencil.ValueMask[face] ||
-	ctx->Stencil.WriteMask[0] != ctx->Stencil.WriteMask[face]);
-}
-
-
-/**
- * Initialize the context stipple state.
- *
- * \param ctx GL context.
- *
- * Initializes __struct gl_contextRec::Stencil attribute group.
- */
-void
-_mesa_init_stencil(struct gl_context *ctx)
-{
-   ctx->Stencil.Enabled = GL_FALSE;
-   ctx->Stencil.TestTwoSide = GL_FALSE;
-   ctx->Stencil.ActiveFace = 0;  /* 0 = GL_FRONT, 2 = GL_BACK */
-   ctx->Stencil.Function[0] = GL_ALWAYS;
-   ctx->Stencil.Function[1] = GL_ALWAYS;
-   ctx->Stencil.Function[2] = GL_ALWAYS;
-   ctx->Stencil.FailFunc[0] = GL_KEEP;
-   ctx->Stencil.FailFunc[1] = GL_KEEP;
-   ctx->Stencil.FailFunc[2] = GL_KEEP;
-   ctx->Stencil.ZPassFunc[0] = GL_KEEP;
-   ctx->Stencil.ZPassFunc[1] = GL_KEEP;
-   ctx->Stencil.ZPassFunc[2] = GL_KEEP;
-   ctx->Stencil.ZFailFunc[0] = GL_KEEP;
-   ctx->Stencil.ZFailFunc[1] = GL_KEEP;
-   ctx->Stencil.ZFailFunc[2] = GL_KEEP;
-   ctx->Stencil.Ref[0] = 0;
-   ctx->Stencil.Ref[1] = 0;
-   ctx->Stencil.Ref[2] = 0;
-   ctx->Stencil.ValueMask[0] = ~0U;
-   ctx->Stencil.ValueMask[1] = ~0U;
-   ctx->Stencil.ValueMask[2] = ~0U;
-   ctx->Stencil.WriteMask[0] = ~0U;
-   ctx->Stencil.WriteMask[1] = ~0U;
-   ctx->Stencil.WriteMask[2] = ~0U;
-   ctx->Stencil.Clear = 0;
-   ctx->Stencil._BackFace = 1;
-}
+/*
+ * Mesa 3-D graphics library
+ * Version:  7.1
+ *
+ * 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"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+/**
+ * \file stencil.c
+ * Stencil operations.
+ *
+ * Note: There's some conflict between GL_EXT_stencil_two_side and
+ * OpenGL 2.0's two-sided stencil feature.
+ *
+ * With GL_EXT_stencil_two_side, calling glStencilOp/Func/Mask() only the
+ * front OR back face state (as set by glActiveStencilFaceEXT) is set.
+ *
+ * But with OpenGL 2.0, calling glStencilOp/Func/Mask() sets BOTH the
+ * front AND back state.
+ *
+ * Also, note that GL_ATI_separate_stencil is different as well:
+ * glStencilFuncSeparateATI(GLenum frontfunc, GLenum backfunc, ...)  vs.
+ * glStencilFuncSeparate(GLenum face, GLenum func, ...).
+ *
+ * This problem is solved by keeping three sets of stencil state:
+ *  state[0] = GL_FRONT state.
+ *  state[1] = OpenGL 2.0 / GL_ATI_separate_stencil GL_BACK state.
+ *  state[2] = GL_EXT_stencil_two_side GL_BACK state.
+ */
+
+
+#include "glheader.h"
+#include "imports.h"
+#include "context.h"
+#include "macros.h"
+#include "stencil.h"
+#include "mtypes.h"
+
+
+static GLboolean
+validate_stencil_op(struct gl_context *ctx, GLenum op)
+{
+   switch (op) {
+   case GL_KEEP:
+   case GL_ZERO:
+   case GL_REPLACE:
+   case GL_INCR:
+   case GL_DECR:
+   case GL_INVERT:
+      return GL_TRUE;
+   case GL_INCR_WRAP_EXT:
+   case GL_DECR_WRAP_EXT:
+      if (ctx->Extensions.EXT_stencil_wrap) {
+         return GL_TRUE;
+      }
+      /* FALL-THROUGH */
+   default:
+      return GL_FALSE;
+   }
+}
+
+
+static GLboolean
+validate_stencil_func(struct gl_context *ctx, GLenum func)
+{
+   switch (func) {
+   case GL_NEVER:
+   case GL_LESS:
+   case GL_LEQUAL:
+   case GL_GREATER:
+   case GL_GEQUAL:
+   case GL_EQUAL:
+   case GL_NOTEQUAL:
+   case GL_ALWAYS:
+      return GL_TRUE;
+   default:
+      return GL_FALSE;
+   }
+}
+
+
+/**
+ * Set the clear value for the stencil buffer.
+ *
+ * \param s clear value.
+ *
+ * \sa glClearStencil().
+ *
+ * Updates gl_stencil_attrib::Clear. On change
+ * flushes the vertices and notifies the driver via
+ * the dd_function_table::ClearStencil callback.
+ */
+void GLAPIENTRY
+_mesa_ClearStencil( GLint s )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (ctx->Stencil.Clear == (GLuint) s)
+      return;
+
+   FLUSH_VERTICES(ctx, _NEW_STENCIL);
+   ctx->Stencil.Clear = (GLuint) s;
+
+   if (ctx->Driver.ClearStencil) {
+      ctx->Driver.ClearStencil( ctx, s );
+   }
+}
+
+
+/**
+ * Set the function and reference value for stencil testing.
+ *
+ * \param frontfunc front test function.
+ * \param backfunc back test function.
+ * \param ref front and back reference value.
+ * \param mask front and back bitmask.
+ *
+ * \sa glStencilFunc().
+ *
+ * Verifies the parameters and updates the respective values in
+ * __struct gl_contextRec::Stencil. On change flushes the vertices and notifies the
+ * driver via the dd_function_table::StencilFunc callback.
+ */
+void GLAPIENTRY
+_mesa_StencilFuncSeparateATI( GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   const GLint stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1;
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glStencilFuncSeparateATI()\n");
+
+   if (!validate_stencil_func(ctx, frontfunc)) {
+      _mesa_error(ctx, GL_INVALID_ENUM,
+                  "glStencilFuncSeparateATI(frontfunc)");
+      return;
+   }
+   if (!validate_stencil_func(ctx, backfunc)) {
+      _mesa_error(ctx, GL_INVALID_ENUM,
+                  "glStencilFuncSeparateATI(backfunc)");
+      return;
+   }
+
+   ref = CLAMP( ref, 0, stencilMax );
+
+   /* set both front and back state */
+   if (ctx->Stencil.Function[0] == frontfunc &&
+       ctx->Stencil.Function[1] == backfunc &&
+       ctx->Stencil.ValueMask[0] == mask &&
+       ctx->Stencil.ValueMask[1] == mask &&
+       ctx->Stencil.Ref[0] == ref &&
+       ctx->Stencil.Ref[1] == ref)
+      return;
+   FLUSH_VERTICES(ctx, _NEW_STENCIL);
+   ctx->Stencil.Function[0]  = frontfunc;
+   ctx->Stencil.Function[1]  = backfunc;
+   ctx->Stencil.Ref[0]       = ctx->Stencil.Ref[1]       = ref;
+   ctx->Stencil.ValueMask[0] = ctx->Stencil.ValueMask[1] = mask;
+   if (ctx->Driver.StencilFuncSeparate) {
+      ctx->Driver.StencilFuncSeparate(ctx, GL_FRONT,
+                                      frontfunc, ref, mask);
+      ctx->Driver.StencilFuncSeparate(ctx, GL_BACK,
+                                      backfunc, ref, mask);
+   }
+}
+
+
+/**
+ * Set the function and reference value for stencil testing.
+ *
+ * \param func test function.
+ * \param ref reference value.
+ * \param mask bitmask.
+ *
+ * \sa glStencilFunc().
+ *
+ * Verifies the parameters and updates the respective values in
+ * __struct gl_contextRec::Stencil. On change flushes the vertices and notifies the
+ * driver via the dd_function_table::StencilFunc callback.
+ */
+void GLAPIENTRY
+_mesa_StencilFunc( GLenum func, GLint ref, GLuint mask )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   const GLint stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1;
+   const GLint face = ctx->Stencil.ActiveFace;
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glStencilFunc()\n");
+
+   if (!validate_stencil_func(ctx, func)) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFunc(func)");
+      return;
+   }
+
+   ref = CLAMP( ref, 0, stencilMax );
+
+   if (face != 0) {
+      if (ctx->Stencil.Function[face] == func &&
+          ctx->Stencil.ValueMask[face] == mask &&
+          ctx->Stencil.Ref[face] == ref)
+         return;
+      FLUSH_VERTICES(ctx, _NEW_STENCIL);
+      ctx->Stencil.Function[face] = func;
+      ctx->Stencil.Ref[face] = ref;
+      ctx->Stencil.ValueMask[face] = mask;
+
+      /* Only propagate the change to the driver if EXT_stencil_two_side
+       * is enabled.
+       */
+      if (ctx->Driver.StencilFuncSeparate && ctx->Stencil.TestTwoSide) {
+         ctx->Driver.StencilFuncSeparate(ctx, GL_BACK, func, ref, mask);
+      }
+   }
+   else {
+      /* set both front and back state */
+      if (ctx->Stencil.Function[0] == func &&
+          ctx->Stencil.Function[1] == func &&
+          ctx->Stencil.ValueMask[0] == mask &&
+          ctx->Stencil.ValueMask[1] == mask &&
+          ctx->Stencil.Ref[0] == ref &&
+          ctx->Stencil.Ref[1] == ref)
+         return;
+      FLUSH_VERTICES(ctx, _NEW_STENCIL);
+      ctx->Stencil.Function[0]  = ctx->Stencil.Function[1]  = func;
+      ctx->Stencil.Ref[0]       = ctx->Stencil.Ref[1]       = ref;
+      ctx->Stencil.ValueMask[0] = ctx->Stencil.ValueMask[1] = mask;
+      if (ctx->Driver.StencilFuncSeparate) {
+         ctx->Driver.StencilFuncSeparate(ctx,
+					 ((ctx->Stencil.TestTwoSide)
+					  ? GL_FRONT : GL_FRONT_AND_BACK),
+                                         func, ref, mask);
+      }
+   }
+}
+
+
+/**
+ * Set the stencil writing mask.
+ *
+ * \param mask bit-mask to enable/disable writing of individual bits in the
+ * stencil planes.
+ *
+ * \sa glStencilMask().
+ *
+ * Updates gl_stencil_attrib::WriteMask. On change flushes the vertices and
+ * notifies the driver via the dd_function_table::StencilMask callback.
+ */
+void GLAPIENTRY
+_mesa_StencilMask( GLuint mask )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   const GLint face = ctx->Stencil.ActiveFace;
+
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glStencilMask()\n");
+
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (face != 0) {
+      /* Only modify the EXT_stencil_two_side back-face state.
+       */
+      if (ctx->Stencil.WriteMask[face] == mask)
+         return;
+      FLUSH_VERTICES(ctx, _NEW_STENCIL);
+      ctx->Stencil.WriteMask[face] = mask;
+
+      /* Only propagate the change to the driver if EXT_stencil_two_side
+       * is enabled.
+       */
+      if (ctx->Driver.StencilMaskSeparate && ctx->Stencil.TestTwoSide) {
+         ctx->Driver.StencilMaskSeparate(ctx, GL_BACK, mask);
+      }
+   }
+   else {
+      /* set both front and back state */
+      if (ctx->Stencil.WriteMask[0] == mask &&
+          ctx->Stencil.WriteMask[1] == mask)
+         return;
+      FLUSH_VERTICES(ctx, _NEW_STENCIL);
+      ctx->Stencil.WriteMask[0] = ctx->Stencil.WriteMask[1] = mask;
+      if (ctx->Driver.StencilMaskSeparate) {
+         ctx->Driver.StencilMaskSeparate(ctx,
+					 ((ctx->Stencil.TestTwoSide)
+					  ? GL_FRONT : GL_FRONT_AND_BACK),
+					  mask);
+      }
+   }
+}
+
+
+/**
+ * Set the stencil test actions.
+ *
+ * \param fail action to take when stencil test fails.
+ * \param zfail action to take when stencil test passes, but depth test fails.
+ * \param zpass action to take when stencil test passes and the depth test
+ * passes (or depth testing is not enabled).
+ * 
+ * \sa glStencilOp().
+ * 
+ * Verifies the parameters and updates the respective fields in
+ * __struct gl_contextRec::Stencil. On change flushes the vertices and notifies the
+ * driver via the dd_function_table::StencilOp callback.
+ */
+void GLAPIENTRY
+_mesa_StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   const GLint face = ctx->Stencil.ActiveFace;
+
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glStencilOp()\n");
+
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (!validate_stencil_op(ctx, fail)) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp(sfail)");
+      return;
+   }
+   if (!validate_stencil_op(ctx, zfail)) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp(zfail)");
+      return;
+   }
+   if (!validate_stencil_op(ctx, zpass)) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp(zpass)");
+      return;
+   }
+
+   if (face != 0) {
+      /* only set active face state */
+      if (ctx->Stencil.ZFailFunc[face] == zfail &&
+          ctx->Stencil.ZPassFunc[face] == zpass &&
+          ctx->Stencil.FailFunc[face] == fail)
+         return;
+      FLUSH_VERTICES(ctx, _NEW_STENCIL);
+      ctx->Stencil.ZFailFunc[face] = zfail;
+      ctx->Stencil.ZPassFunc[face] = zpass;
+      ctx->Stencil.FailFunc[face] = fail;
+
+      /* Only propagate the change to the driver if EXT_stencil_two_side
+       * is enabled.
+       */
+      if (ctx->Driver.StencilOpSeparate && ctx->Stencil.TestTwoSide) {
+         ctx->Driver.StencilOpSeparate(ctx, GL_BACK, fail, zfail, zpass);
+      }
+   }
+   else {
+      /* set both front and back state */
+      if (ctx->Stencil.ZFailFunc[0] == zfail &&
+          ctx->Stencil.ZFailFunc[1] == zfail &&
+          ctx->Stencil.ZPassFunc[0] == zpass &&
+          ctx->Stencil.ZPassFunc[1] == zpass &&
+          ctx->Stencil.FailFunc[0] == fail &&
+          ctx->Stencil.FailFunc[1] == fail)
+         return;
+      FLUSH_VERTICES(ctx, _NEW_STENCIL);
+      ctx->Stencil.ZFailFunc[0] = ctx->Stencil.ZFailFunc[1] = zfail;
+      ctx->Stencil.ZPassFunc[0] = ctx->Stencil.ZPassFunc[1] = zpass;
+      ctx->Stencil.FailFunc[0]  = ctx->Stencil.FailFunc[1]  = fail;
+      if (ctx->Driver.StencilOpSeparate) {
+         ctx->Driver.StencilOpSeparate(ctx,
+				       ((ctx->Stencil.TestTwoSide)
+					? GL_FRONT : GL_FRONT_AND_BACK),
+                                       fail, zfail, zpass);
+      }
+   }
+}
+
+
+
+#if _HAVE_FULL_GL
+/* GL_EXT_stencil_two_side */
+void GLAPIENTRY
+_mesa_ActiveStencilFaceEXT(GLenum face)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glActiveStencilFaceEXT()\n");
+
+   if (!ctx->Extensions.EXT_stencil_two_side) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "glActiveStencilFaceEXT");
+      return;
+   }
+
+   if (face == GL_FRONT || face == GL_BACK) {
+      FLUSH_VERTICES(ctx, _NEW_STENCIL);
+      ctx->Stencil.ActiveFace = (face == GL_FRONT) ? 0 : 2;
+   }
+   else {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glActiveStencilFaceEXT(face)");
+   }
+}
+#endif
+
+
+
+/**
+ * OpenGL 2.0 function.
+ * \todo Make StencilOp() call this function.  And eventually remove the
+ * ctx->Driver.StencilOp function and use ctx->Driver.StencilOpSeparate
+ * instead.
+ */
+void GLAPIENTRY
+_mesa_StencilOpSeparate(GLenum face, GLenum sfail, GLenum zfail, GLenum zpass)
+{
+   GLboolean set = GL_FALSE;
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glStencilOpSeparate()\n");
+
+   if (!validate_stencil_op(ctx, sfail)) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(sfail)");
+      return;
+   }
+   if (!validate_stencil_op(ctx, zfail)) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(zfail)");
+      return;
+   }
+   if (!validate_stencil_op(ctx, zpass)) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(zpass)");
+      return;
+   }
+   if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(face)");
+      return;
+   }
+
+   if (face != GL_BACK) {
+      /* set front */
+      if (ctx->Stencil.ZFailFunc[0] != zfail ||
+          ctx->Stencil.ZPassFunc[0] != zpass ||
+          ctx->Stencil.FailFunc[0] != sfail){
+         FLUSH_VERTICES(ctx, _NEW_STENCIL);
+         ctx->Stencil.ZFailFunc[0] = zfail;
+         ctx->Stencil.ZPassFunc[0] = zpass;
+         ctx->Stencil.FailFunc[0] = sfail;
+         set = GL_TRUE;
+      }
+   }
+   if (face != GL_FRONT) {
+      /* set back */
+      if (ctx->Stencil.ZFailFunc[1] != zfail ||
+          ctx->Stencil.ZPassFunc[1] != zpass ||
+          ctx->Stencil.FailFunc[1] != sfail) {
+         FLUSH_VERTICES(ctx, _NEW_STENCIL);
+         ctx->Stencil.ZFailFunc[1] = zfail;
+         ctx->Stencil.ZPassFunc[1] = zpass;
+         ctx->Stencil.FailFunc[1] = sfail;
+         set = GL_TRUE;
+      }
+   }
+   if (set && ctx->Driver.StencilOpSeparate) {
+      ctx->Driver.StencilOpSeparate(ctx, face, sfail, zfail, zpass);
+   }
+}
+
+
+/* OpenGL 2.0 */
+void GLAPIENTRY
+_mesa_StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   const GLint stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1;
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glStencilFuncSeparate()\n");
+
+   if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFuncSeparate(face)");
+      return;
+   }
+   if (!validate_stencil_func(ctx, func)) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFuncSeparate(func)");
+      return;
+   }
+
+   ref = CLAMP(ref, 0, stencilMax);
+
+   FLUSH_VERTICES(ctx, _NEW_STENCIL);
+
+   if (face != GL_BACK) {
+      /* set front */
+      ctx->Stencil.Function[0] = func;
+      ctx->Stencil.Ref[0] = ref;
+      ctx->Stencil.ValueMask[0] = mask;
+   }
+   if (face != GL_FRONT) {
+      /* set back */
+      ctx->Stencil.Function[1] = func;
+      ctx->Stencil.Ref[1] = ref;
+      ctx->Stencil.ValueMask[1] = mask;
+   }
+   if (ctx->Driver.StencilFuncSeparate) {
+      ctx->Driver.StencilFuncSeparate(ctx, face, func, ref, mask);
+   }
+}
+
+
+/* OpenGL 2.0 */
+void GLAPIENTRY
+_mesa_StencilMaskSeparate(GLenum face, GLuint mask)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glStencilMaskSeparate()\n");
+
+   if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glStencilaMaskSeparate(face)");
+      return;
+   }
+
+   FLUSH_VERTICES(ctx, _NEW_STENCIL);
+
+   if (face != GL_BACK) {
+      ctx->Stencil.WriteMask[0] = mask;
+   }
+   if (face != GL_FRONT) {
+      ctx->Stencil.WriteMask[1] = mask;
+   }
+   if (ctx->Driver.StencilMaskSeparate) {
+      ctx->Driver.StencilMaskSeparate(ctx, face, mask);
+   }
+}
+
+
+/**
+ * Update derived stencil state.
+ */
+void
+_mesa_update_stencil(struct gl_context *ctx)
+{
+   const GLint face = ctx->Stencil._BackFace;
+
+   ctx->Stencil._Enabled = (ctx->Stencil.Enabled &&
+                            ctx->DrawBuffer->Visual.stencilBits > 0);
+
+    ctx->Stencil._TestTwoSide =
+       ctx->Stencil._Enabled &&
+       (ctx->Stencil.Function[0] != ctx->Stencil.Function[face] ||
+	ctx->Stencil.FailFunc[0] != ctx->Stencil.FailFunc[face] ||
+	ctx->Stencil.ZPassFunc[0] != ctx->Stencil.ZPassFunc[face] ||
+	ctx->Stencil.ZFailFunc[0] != ctx->Stencil.ZFailFunc[face] ||
+	ctx->Stencil.Ref[0] != ctx->Stencil.Ref[face] ||
+	ctx->Stencil.ValueMask[0] != ctx->Stencil.ValueMask[face] ||
+	ctx->Stencil.WriteMask[0] != ctx->Stencil.WriteMask[face]);
+}
+
+
+/**
+ * Initialize the context stipple state.
+ *
+ * \param ctx GL context.
+ *
+ * Initializes __struct gl_contextRec::Stencil attribute group.
+ */
+void
+_mesa_init_stencil(struct gl_context *ctx)
+{
+   ctx->Stencil.Enabled = GL_FALSE;
+   ctx->Stencil.TestTwoSide = GL_FALSE;
+   ctx->Stencil.ActiveFace = 0;  /* 0 = GL_FRONT, 2 = GL_BACK */
+   ctx->Stencil.Function[0] = GL_ALWAYS;
+   ctx->Stencil.Function[1] = GL_ALWAYS;
+   ctx->Stencil.Function[2] = GL_ALWAYS;
+   ctx->Stencil.FailFunc[0] = GL_KEEP;
+   ctx->Stencil.FailFunc[1] = GL_KEEP;
+   ctx->Stencil.FailFunc[2] = GL_KEEP;
+   ctx->Stencil.ZPassFunc[0] = GL_KEEP;
+   ctx->Stencil.ZPassFunc[1] = GL_KEEP;
+   ctx->Stencil.ZPassFunc[2] = GL_KEEP;
+   ctx->Stencil.ZFailFunc[0] = GL_KEEP;
+   ctx->Stencil.ZFailFunc[1] = GL_KEEP;
+   ctx->Stencil.ZFailFunc[2] = GL_KEEP;
+   ctx->Stencil.Ref[0] = 0;
+   ctx->Stencil.Ref[1] = 0;
+   ctx->Stencil.Ref[2] = 0;
+   ctx->Stencil.ValueMask[0] = ~0U;
+   ctx->Stencil.ValueMask[1] = ~0U;
+   ctx->Stencil.ValueMask[2] = ~0U;
+   ctx->Stencil.WriteMask[0] = ~0U;
+   ctx->Stencil.WriteMask[1] = ~0U;
+   ctx->Stencil.WriteMask[2] = ~0U;
+   ctx->Stencil.Clear = 0;
+   ctx->Stencil._BackFace = 1;
+}
diff --git a/mesalib/src/mesa/program/ir_to_mesa.cpp b/mesalib/src/mesa/program/ir_to_mesa.cpp
index 3794c0de0..d0ec23fc8 100644
--- a/mesalib/src/mesa/program/ir_to_mesa.cpp
+++ b/mesalib/src/mesa/program/ir_to_mesa.cpp
@@ -2742,13 +2742,46 @@ ir_to_mesa_visitor::copy_propagate(void)
 	 /* Continuing the block, clear any written channels from
 	  * the ACP.
 	  */
-	 if (inst->dst_reg.file == PROGRAM_TEMPORARY) {
-	    if (inst->dst_reg.reladdr) {
-	       memset(acp, 0, sizeof(*acp) * this->next_temp * 4);
-	    } else {
-	       for (int i = 0; i < 4; i++) {
-		  if (inst->dst_reg.writemask & (1 << i)) {
-		     acp[4 * inst->dst_reg.index + i] = NULL;
+	 if (inst->dst_reg.file == PROGRAM_TEMPORARY && inst->dst_reg.reladdr) {
+	    /* Any temporary might be written, so no copy propagation
+	     * across this instruction.
+	     */
+	    memset(acp, 0, sizeof(*acp) * this->next_temp * 4);
+	 } else if (inst->dst_reg.file == PROGRAM_OUTPUT &&
+		    inst->dst_reg.reladdr) {
+	    /* Any output might be written, so no copy propagation
+	     * from outputs across this instruction.
+	     */
+	    for (int r = 0; r < this->next_temp; r++) {
+	       for (int c = 0; c < 4; c++) {
+		  if (acp[4 * r + c]->src_reg[0].file == PROGRAM_OUTPUT)
+		     acp[4 * r + c] = NULL;
+	       }
+	    }
+	 } else if (inst->dst_reg.file == PROGRAM_TEMPORARY ||
+		    inst->dst_reg.file == PROGRAM_OUTPUT) {
+	    /* Clear where it's used as dst. */
+	    if (inst->dst_reg.file == PROGRAM_TEMPORARY) {
+	       for (int c = 0; c < 4; c++) {
+		  if (inst->dst_reg.writemask & (1 << c)) {
+		     acp[4 * inst->dst_reg.index + c] = NULL;
+		  }
+	       }
+	    }
+
+	    /* Clear where it's used as src. */
+	    for (int r = 0; r < this->next_temp; r++) {
+	       for (int c = 0; c < 4; c++) {
+		  if (!acp[4 * r + c])
+		     continue;
+
+		  int src_chan = GET_SWZ(acp[4 * r + c]->src_reg[0].swizzle, c);
+
+		  if (acp[4 * r + c]->src_reg[0].file == inst->dst_reg.file &&
+		      acp[4 * r + c]->src_reg[0].index == inst->dst_reg.index &&
+		      inst->dst_reg.writemask & (1 << src_chan))
+		  {
+		     acp[4 * r + c] = NULL;
 		  }
 	       }
 	    }
diff --git a/mesalib/src/mesa/state_tracker/st_context.c b/mesalib/src/mesa/state_tracker/st_context.c
index 593da8fa6..dccbff3c1 100644
--- a/mesalib/src/mesa/state_tracker/st_context.c
+++ b/mesalib/src/mesa/state_tracker/st_context.c
@@ -1,292 +1,292 @@
-/**************************************************************************
- * 
- * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
- * 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"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
- **************************************************************************/
-
-#include "main/imports.h"
-#include "main/context.h"
-#include "main/shaderobj.h"
-#include "program/prog_cache.h"
-#include "vbo/vbo.h"
-#include "glapi/glapi.h"
-#include "st_context.h"
-#include "st_debug.h"
-#include "st_cb_accum.h"
-#include "st_cb_bitmap.h"
-#include "st_cb_blit.h"
-#include "st_cb_bufferobjects.h"
-#include "st_cb_clear.h"
-#include "st_cb_condrender.h"
-#include "st_cb_drawpixels.h"
-#include "st_cb_rasterpos.h"
-#include "st_cb_drawtex.h"
-#include "st_cb_eglimage.h"
-#include "st_cb_fbo.h"
-#include "st_cb_feedback.h"
-#include "st_cb_program.h"
-#include "st_cb_queryobj.h"
-#include "st_cb_readpixels.h"
-#include "st_cb_texture.h"
-#include "st_cb_xformfb.h"
-#include "st_cb_flush.h"
-#include "st_cb_strings.h"
-#include "st_cb_viewport.h"
-#include "st_atom.h"
-#include "st_draw.h"
-#include "st_extensions.h"
-#include "st_gen_mipmap.h"
-#include "st_program.h"
-#include "pipe/p_context.h"
-#include "util/u_inlines.h"
-#include "cso_cache/cso_context.h"
-
-
-DEBUG_GET_ONCE_BOOL_OPTION(mesa_mvp_dp4, "MESA_MVP_DP4", FALSE)
-
-
-/**
- * Called via ctx->Driver.UpdateState()
- */
-void st_invalidate_state(struct gl_context * ctx, GLuint new_state)
-{
-   struct st_context *st = st_context(ctx);
-
-   st->dirty.mesa |= new_state;
-   st->dirty.st |= ST_NEW_MESA;
-
-   /* This is the only core Mesa module we depend upon.
-    * No longer use swrast, swsetup, tnl.
-    */
-   _vbo_InvalidateState(ctx, new_state);
-}
-
-
-/**
- * Check for multisample env var override.
- */
-int
-st_get_msaa(void)
-{
-   const char *msaa = _mesa_getenv("__GL_FSAA_MODE");
-   if (msaa)
-      return atoi(msaa);
-   return 0;
-}
-
-
-static struct st_context *
-st_create_context_priv( struct gl_context *ctx, struct pipe_context *pipe )
-{
-   uint i;
-   struct st_context *st = ST_CALLOC_STRUCT( st_context );
-   
-   ctx->st = st;
-
-   st->ctx = ctx;
-   st->pipe = pipe;
-
-   /* XXX: this is one-off, per-screen init: */
-   st_debug_init();
-   
-   /* state tracker needs the VBO module */
-   _vbo_CreateContext(ctx);
-
-   st->dirty.mesa = ~0;
-   st->dirty.st = ~0;
-
-   st->cso_context = cso_create_context(pipe);
-
-   st_init_atoms( st );
-   st_init_bitmap(st);
-   st_init_clear(st);
-   st_init_draw( st );
-   st_init_generate_mipmap(st);
-   st_init_blit(st);
-
-   if(pipe->screen->get_param(pipe->screen, PIPE_CAP_NPOT_TEXTURES))
-      st->internal_target = PIPE_TEXTURE_2D;
-   else
-      st->internal_target = PIPE_TEXTURE_RECT;
-
-   for (i = 0; i < PIPE_MAX_SAMPLERS; i++)
-      st->state.sampler_list[i] = &st->state.samplers[i];
-
-   for (i = 0; i < 3; i++) {
-      memset(&st->velems_util_draw[i], 0, sizeof(struct pipe_vertex_element));
-      st->velems_util_draw[i].src_offset = i * 4 * sizeof(float);
-      st->velems_util_draw[i].instance_divisor = 0;
-      st->velems_util_draw[i].vertex_buffer_index = 0;
-      st->velems_util_draw[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
-   }
-
-   /* we want all vertex data to be placed in buffer objects */
-   vbo_use_buffer_objects(ctx);
-
-   /* Need these flags:
-    */
-   st->ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE;
-
-   st->ctx->VertexProgram._MaintainTnlProgram = GL_TRUE;
-
-   st->pixel_xfer.cache = _mesa_new_program_cache();
-
-   st->force_msaa = st_get_msaa();
-
-   /* GL limits and extensions */
-   st_init_limits(st);
-   st_init_extensions(st);
-
-   return st;
-}
-
-
-struct st_context *st_create_context(gl_api api, struct pipe_context *pipe,
-                                     const struct gl_config *visual,
-                                     struct st_context *share)
-{
-   struct gl_context *ctx;
-   struct gl_context *shareCtx = share ? share->ctx : NULL;
-   struct dd_function_table funcs;
-
-   /* Sanity checks */
-   assert(MESA_SHADER_VERTEX == PIPE_SHADER_VERTEX);
-   assert(MESA_SHADER_FRAGMENT == PIPE_SHADER_FRAGMENT);
-   assert(MESA_SHADER_GEOMETRY == PIPE_SHADER_GEOMETRY);
-
-   memset(&funcs, 0, sizeof(funcs));
-   st_init_driver_functions(&funcs);
-
-   ctx = _mesa_create_context_for_api(api, visual, shareCtx, &funcs, NULL);
-
-   /* XXX: need a capability bit in gallium to query if the pipe
-    * driver prefers DP4 or MUL/MAD for vertex transformation.
-    */
-   if (debug_get_option_mesa_mvp_dp4())
-      _mesa_set_mvp_with_dp4( ctx, GL_TRUE );
-
-   return st_create_context_priv(ctx, pipe);
-}
-
-
-static void st_destroy_context_priv( struct st_context *st )
-{
-   uint i;
-
-   st_destroy_atoms( st );
-   st_destroy_draw( st );
-   st_destroy_generate_mipmap(st);
-   st_destroy_blit(st);
-   st_destroy_clear(st);
-   st_destroy_bitmap(st);
-   st_destroy_drawpix(st);
-   st_destroy_drawtex(st);
-
-   for (i = 0; i < Elements(st->state.sampler_views); i++) {
-      pipe_sampler_view_reference(&st->state.sampler_views[i], NULL);
-   }
-
-   if (st->default_texture) {
-      st->ctx->Driver.DeleteTexture(st->ctx, st->default_texture);
-      st->default_texture = NULL;
-   }
-
-   free( st );
-}
-
- 
-void st_destroy_context( struct st_context *st )
-{
-   struct pipe_context *pipe = st->pipe;
-   struct cso_context *cso = st->cso_context;
-   struct gl_context *ctx = st->ctx;
-   GLuint i;
-
-   /* need to unbind and destroy CSO objects before anything else */
-   cso_release_all(st->cso_context);
-
-   st_reference_fragprog(st, &st->fp, NULL);
-   st_reference_vertprog(st, &st->vp, NULL);
-
-   /* release framebuffer surfaces */
-   for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
-      pipe_surface_reference(&st->state.framebuffer.cbufs[i], NULL);
-   }
-   pipe_surface_reference(&st->state.framebuffer.zsbuf, NULL);
-
-   pipe->set_index_buffer(pipe, NULL);
-
-   for (i = 0; i < PIPE_SHADER_TYPES; i++) {
-      pipe->set_constant_buffer(pipe, i, 0, NULL);
-   }
-
-   _mesa_delete_program_cache(st->ctx, st->pixel_xfer.cache);
-
-   _vbo_DestroyContext(st->ctx);
-
-   st_destroy_program_variants(st);
-
-   _mesa_free_context_data(ctx);
-
-   st_destroy_context_priv(st);
-
-   cso_destroy_context(cso);
-
-   pipe->destroy( pipe );
-
-   free(ctx);
-}
-
-
-void st_init_driver_functions(struct dd_function_table *functions)
-{
-   _mesa_init_shader_object_functions(functions);
-
-   st_init_accum_functions(functions);
-   st_init_blit_functions(functions);
-   st_init_bufferobject_functions(functions);
-   st_init_clear_functions(functions);
-   st_init_bitmap_functions(functions);
-   st_init_drawpixels_functions(functions);
-   st_init_rasterpos_functions(functions);
-
-   st_init_drawtex_functions(functions);
-
-   st_init_eglimage_functions(functions);
-
-   st_init_fbo_functions(functions);
-   st_init_feedback_functions(functions);
-   st_init_program_functions(functions);
-   st_init_query_functions(functions);
-   st_init_cond_render_functions(functions);
-   st_init_readpixels_functions(functions);
-   st_init_texture_functions(functions);
-   st_init_flush_functions(functions);
-   st_init_string_functions(functions);
-   st_init_viewport_functions(functions);
-
-   st_init_xformfb_functions(functions);
-
-   functions->UpdateState = st_invalidate_state;
-}
+/**************************************************************************
+ * 
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * 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"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#include "main/imports.h"
+#include "main/context.h"
+#include "main/shaderobj.h"
+#include "program/prog_cache.h"
+#include "vbo/vbo.h"
+#include "glapi/glapi.h"
+#include "st_context.h"
+#include "st_debug.h"
+#include "st_cb_accum.h"
+#include "st_cb_bitmap.h"
+#include "st_cb_blit.h"
+#include "st_cb_bufferobjects.h"
+#include "st_cb_clear.h"
+#include "st_cb_condrender.h"
+#include "st_cb_drawpixels.h"
+#include "st_cb_rasterpos.h"
+#include "st_cb_drawtex.h"
+#include "st_cb_eglimage.h"
+#include "st_cb_fbo.h"
+#include "st_cb_feedback.h"
+#include "st_cb_program.h"
+#include "st_cb_queryobj.h"
+#include "st_cb_readpixels.h"
+#include "st_cb_texture.h"
+#include "st_cb_xformfb.h"
+#include "st_cb_flush.h"
+#include "st_cb_strings.h"
+#include "st_cb_viewport.h"
+#include "st_atom.h"
+#include "st_draw.h"
+#include "st_extensions.h"
+#include "st_gen_mipmap.h"
+#include "st_program.h"
+#include "pipe/p_context.h"
+#include "util/u_inlines.h"
+#include "cso_cache/cso_context.h"
+
+
+DEBUG_GET_ONCE_BOOL_OPTION(mesa_mvp_dp4, "MESA_MVP_DP4", FALSE)
+
+
+/**
+ * Called via ctx->Driver.UpdateState()
+ */
+void st_invalidate_state(struct gl_context * ctx, GLuint new_state)
+{
+   struct st_context *st = st_context(ctx);
+
+   st->dirty.mesa |= new_state;
+   st->dirty.st |= ST_NEW_MESA;
+
+   /* This is the only core Mesa module we depend upon.
+    * No longer use swrast, swsetup, tnl.
+    */
+   _vbo_InvalidateState(ctx, new_state);
+}
+
+
+/**
+ * Check for multisample env var override.
+ */
+int
+st_get_msaa(void)
+{
+   const char *msaa = _mesa_getenv("__GL_FSAA_MODE");
+   if (msaa)
+      return atoi(msaa);
+   return 0;
+}
+
+
+static struct st_context *
+st_create_context_priv( struct gl_context *ctx, struct pipe_context *pipe )
+{
+   uint i;
+   struct st_context *st = ST_CALLOC_STRUCT( st_context );
+   
+   ctx->st = st;
+
+   st->ctx = ctx;
+   st->pipe = pipe;
+
+   /* XXX: this is one-off, per-screen init: */
+   st_debug_init();
+   
+   /* state tracker needs the VBO module */
+   _vbo_CreateContext(ctx);
+
+   st->dirty.mesa = ~0;
+   st->dirty.st = ~0;
+
+   st->cso_context = cso_create_context(pipe);
+
+   st_init_atoms( st );
+   st_init_bitmap(st);
+   st_init_clear(st);
+   st_init_draw( st );
+   st_init_generate_mipmap(st);
+   st_init_blit(st);
+
+   if(pipe->screen->get_param(pipe->screen, PIPE_CAP_NPOT_TEXTURES))
+      st->internal_target = PIPE_TEXTURE_2D;
+   else
+      st->internal_target = PIPE_TEXTURE_RECT;
+
+   for (i = 0; i < PIPE_MAX_SAMPLERS; i++)
+      st->state.sampler_list[i] = &st->state.samplers[i];
+
+   for (i = 0; i < 3; i++) {
+      memset(&st->velems_util_draw[i], 0, sizeof(struct pipe_vertex_element));
+      st->velems_util_draw[i].src_offset = i * 4 * sizeof(float);
+      st->velems_util_draw[i].instance_divisor = 0;
+      st->velems_util_draw[i].vertex_buffer_index = 0;
+      st->velems_util_draw[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+   }
+
+   /* we want all vertex data to be placed in buffer objects */
+   vbo_use_buffer_objects(ctx);
+
+   /* Need these flags:
+    */
+   st->ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE;
+
+   st->ctx->VertexProgram._MaintainTnlProgram = GL_TRUE;
+
+   st->pixel_xfer.cache = _mesa_new_program_cache();
+
+   st->force_msaa = st_get_msaa();
+
+   /* GL limits and extensions */
+   st_init_limits(st);
+   st_init_extensions(st);
+
+   return st;
+}
+
+
+struct st_context *st_create_context(gl_api api, struct pipe_context *pipe,
+                                     const struct gl_config *visual,
+                                     struct st_context *share)
+{
+   struct gl_context *ctx;
+   struct gl_context *shareCtx = share ? share->ctx : NULL;
+   struct dd_function_table funcs;
+
+   /* Sanity checks */
+   assert(MESA_SHADER_VERTEX == PIPE_SHADER_VERTEX);
+   assert(MESA_SHADER_FRAGMENT == PIPE_SHADER_FRAGMENT);
+   assert(MESA_SHADER_GEOMETRY == PIPE_SHADER_GEOMETRY);
+
+   memset(&funcs, 0, sizeof(funcs));
+   st_init_driver_functions(&funcs);
+
+   ctx = _mesa_create_context(api, visual, shareCtx, &funcs, NULL);
+
+   /* XXX: need a capability bit in gallium to query if the pipe
+    * driver prefers DP4 or MUL/MAD for vertex transformation.
+    */
+   if (debug_get_option_mesa_mvp_dp4())
+      _mesa_set_mvp_with_dp4( ctx, GL_TRUE );
+
+   return st_create_context_priv(ctx, pipe);
+}
+
+
+static void st_destroy_context_priv( struct st_context *st )
+{
+   uint i;
+
+   st_destroy_atoms( st );
+   st_destroy_draw( st );
+   st_destroy_generate_mipmap(st);
+   st_destroy_blit(st);
+   st_destroy_clear(st);
+   st_destroy_bitmap(st);
+   st_destroy_drawpix(st);
+   st_destroy_drawtex(st);
+
+   for (i = 0; i < Elements(st->state.sampler_views); i++) {
+      pipe_sampler_view_reference(&st->state.sampler_views[i], NULL);
+   }
+
+   if (st->default_texture) {
+      st->ctx->Driver.DeleteTexture(st->ctx, st->default_texture);
+      st->default_texture = NULL;
+   }
+
+   free( st );
+}
+
+ 
+void st_destroy_context( struct st_context *st )
+{
+   struct pipe_context *pipe = st->pipe;
+   struct cso_context *cso = st->cso_context;
+   struct gl_context *ctx = st->ctx;
+   GLuint i;
+
+   /* need to unbind and destroy CSO objects before anything else */
+   cso_release_all(st->cso_context);
+
+   st_reference_fragprog(st, &st->fp, NULL);
+   st_reference_vertprog(st, &st->vp, NULL);
+
+   /* release framebuffer surfaces */
+   for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
+      pipe_surface_reference(&st->state.framebuffer.cbufs[i], NULL);
+   }
+   pipe_surface_reference(&st->state.framebuffer.zsbuf, NULL);
+
+   pipe->set_index_buffer(pipe, NULL);
+
+   for (i = 0; i < PIPE_SHADER_TYPES; i++) {
+      pipe->set_constant_buffer(pipe, i, 0, NULL);
+   }
+
+   _mesa_delete_program_cache(st->ctx, st->pixel_xfer.cache);
+
+   _vbo_DestroyContext(st->ctx);
+
+   st_destroy_program_variants(st);
+
+   _mesa_free_context_data(ctx);
+
+   st_destroy_context_priv(st);
+
+   cso_destroy_context(cso);
+
+   pipe->destroy( pipe );
+
+   free(ctx);
+}
+
+
+void st_init_driver_functions(struct dd_function_table *functions)
+{
+   _mesa_init_shader_object_functions(functions);
+
+   st_init_accum_functions(functions);
+   st_init_blit_functions(functions);
+   st_init_bufferobject_functions(functions);
+   st_init_clear_functions(functions);
+   st_init_bitmap_functions(functions);
+   st_init_drawpixels_functions(functions);
+   st_init_rasterpos_functions(functions);
+
+   st_init_drawtex_functions(functions);
+
+   st_init_eglimage_functions(functions);
+
+   st_init_fbo_functions(functions);
+   st_init_feedback_functions(functions);
+   st_init_program_functions(functions);
+   st_init_query_functions(functions);
+   st_init_cond_render_functions(functions);
+   st_init_readpixels_functions(functions);
+   st_init_texture_functions(functions);
+   st_init_flush_functions(functions);
+   st_init_string_functions(functions);
+   st_init_viewport_functions(functions);
+
+   st_init_xformfb_functions(functions);
+
+   functions->UpdateState = st_invalidate_state;
+}
diff --git a/mesalib/src/mesa/state_tracker/st_draw_feedback.c b/mesalib/src/mesa/state_tracker/st_draw_feedback.c
index 72ed75e73..c11c7696e 100644
--- a/mesalib/src/mesa/state_tracker/st_draw_feedback.c
+++ b/mesalib/src/mesa/state_tracker/st_draw_feedback.c
@@ -1,278 +1,279 @@
-/**************************************************************************
- * 
- * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
- * 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"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
- **************************************************************************/
-
-#include "main/imports.h"
-#include "main/image.h"
-#include "main/macros.h"
-#include "main/mfeatures.h"
-
-#include "vbo/vbo.h"
-
-#include "st_context.h"
-#include "st_atom.h"
-#include "st_cb_bufferobjects.h"
-#include "st_draw.h"
-#include "st_program.h"
-
-#include "pipe/p_context.h"
-#include "pipe/p_defines.h"
-#include "util/u_inlines.h"
-
-#include "draw/draw_private.h"
-#include "draw/draw_context.h"
-
-
-#if FEATURE_feedback || FEATURE_rastpos
-
-/**
- * Set the (private) draw module's post-transformed vertex format when in
- * GL_SELECT or GL_FEEDBACK mode or for glRasterPos.
- */
-static void
-set_feedback_vertex_format(struct gl_context *ctx)
-{
-#if 0
-   struct st_context *st = st_context(ctx);
-   struct vertex_info vinfo;
-   GLuint i;
-
-   memset(&vinfo, 0, sizeof(vinfo));
-
-   if (ctx->RenderMode == GL_SELECT) {
-      assert(ctx->RenderMode == GL_SELECT);
-      vinfo.num_attribs = 1;
-      vinfo.format[0] = FORMAT_4F;
-      vinfo.interp_mode[0] = INTERP_LINEAR;
-   }
-   else {
-      /* GL_FEEDBACK, or glRasterPos */
-      /* emit all attribs (pos, color, texcoord) as GLfloat[4] */
-      vinfo.num_attribs = st->state.vs->cso->state.num_outputs;
-      for (i = 0; i < vinfo.num_attribs; i++) {
-         vinfo.format[i] = FORMAT_4F;
-         vinfo.interp_mode[i] = INTERP_LINEAR;
-      }
-   }
-
-   draw_set_vertex_info(st->draw, &vinfo);
-#endif
-}
-
-
-/**
- * Called by VBO to draw arrays when in selection or feedback mode and
- * to implement glRasterPos.
- * This is very much like the normal draw_vbo() function above.
- * Look at code refactoring some day.
- * Might move this into the failover module some day.
- */
-void
-st_feedback_draw_vbo(struct gl_context *ctx,
-                     const struct gl_client_array **arrays,
-                     const struct _mesa_prim *prims,
-                     GLuint nr_prims,
-                     const struct _mesa_index_buffer *ib,
-		     GLboolean index_bounds_valid,
-                     GLuint min_index,
-                     GLuint max_index)
-{
-   struct st_context *st = st_context(ctx);
-   struct pipe_context *pipe = st->pipe;
-   struct draw_context *draw = st->draw;
-   const struct st_vertex_program *vp;
-   const struct pipe_shader_state *vs;
-   struct pipe_vertex_buffer vbuffers[PIPE_MAX_SHADER_INPUTS];
-   struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS];
-   struct pipe_index_buffer ibuffer;
-   struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS];
-   struct pipe_transfer *ib_transfer = NULL;
-   GLuint attr, i;
-   const void *mapped_indices = NULL;
-
-   assert(draw);
-
-   st_validate_state(st);
-
-   if (!index_bounds_valid)
-      vbo_get_minmax_index(ctx, prims, ib, &min_index, &max_index);
-
-   /* must get these after state validation! */
-   vp = st->vp;
-   vs = &st->vp_variant->tgsi;
-
-   if (!st->vp_variant->draw_shader) {
-      st->vp_variant->draw_shader = draw_create_vertex_shader(draw, vs);
-   }
-
-   /*
-    * Set up the draw module's state.
-    *
-    * We'd like to do this less frequently, but the normal state-update
-    * code sends state updates to the pipe, not to our private draw module.
-    */
-   assert(draw);
-   draw_set_viewport_state(draw, &st->state.viewport);
-   draw_set_clip_state(draw, &st->state.clip);
-   draw_set_rasterizer_state(draw, &st->state.rasterizer, NULL);
-   draw_bind_vertex_shader(draw, st->vp_variant->draw_shader);
-   set_feedback_vertex_format(ctx);
-
-   /* loop over TGSI shader inputs to determine vertex buffer
-    * and attribute info
-    */
-   for (attr = 0; attr < vp->num_inputs; attr++) {
-      const GLuint mesaAttr = vp->index_to_input[attr];
-      struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj;
-      void *map;
-
-      if (bufobj && bufobj->Name) {
-         /* Attribute data is in a VBO.
-          * Recall that for VBOs, the gl_client_array->Ptr field is
-          * really an offset from the start of the VBO, not a pointer.
-          */
-         struct st_buffer_object *stobj = st_buffer_object(bufobj);
-         assert(stobj->buffer);
-
-         vbuffers[attr].buffer = NULL;
-         pipe_resource_reference(&vbuffers[attr].buffer, stobj->buffer);
-         vbuffers[attr].buffer_offset = pointer_to_offset(arrays[0]->Ptr);
-         velements[attr].src_offset = arrays[mesaAttr]->Ptr - arrays[0]->Ptr;
-      }
-      else {
-         /* attribute data is in user-space memory, not a VBO */
-         uint bytes = (arrays[mesaAttr]->Size
-                       * _mesa_sizeof_type(arrays[mesaAttr]->Type)
-                       * (max_index + 1));
-
-         /* wrap user data */
-         vbuffers[attr].buffer
-            = pipe_user_buffer_create(pipe->screen, (void *) arrays[mesaAttr]->Ptr,
-                                      bytes,
-				      PIPE_BIND_VERTEX_BUFFER);
-         vbuffers[attr].buffer_offset = 0;
-         velements[attr].src_offset = 0;
-      }
-
-      /* common-case setup */
-      vbuffers[attr].stride = arrays[mesaAttr]->StrideB; /* in bytes */
-      vbuffers[attr].max_index = max_index;
-      velements[attr].instance_divisor = 0;
-      velements[attr].vertex_buffer_index = attr;
-      velements[attr].src_format = 
-         st_pipe_vertex_format(arrays[mesaAttr]->Type,
-                               arrays[mesaAttr]->Size,
-                               arrays[mesaAttr]->Format,
-                               arrays[mesaAttr]->Normalized);
-      assert(velements[attr].src_format);
-
-      /* tell draw about this attribute */
-#if 0
-      draw_set_vertex_buffer(draw, attr, &vbuffer[attr]);
-#endif
-
-      /* map the attrib buffer */
-      map = pipe_buffer_map(pipe, vbuffers[attr].buffer,
-                            PIPE_TRANSFER_READ,
-			    &vb_transfer[attr]);
-      draw_set_mapped_vertex_buffer(draw, attr, map);
-   }
-
-   draw_set_vertex_buffers(draw, vp->num_inputs, vbuffers);
-   draw_set_vertex_elements(draw, vp->num_inputs, velements);
-
-   memset(&ibuffer, 0, sizeof(ibuffer));
-   if (ib) {
-      struct gl_buffer_object *bufobj = ib->obj;
-
-      switch (ib->type) {
-      case GL_UNSIGNED_INT:
-         ibuffer.index_size = 4;
-         break;
-      case GL_UNSIGNED_SHORT:
-         ibuffer.index_size = 2;
-         break;
-      case GL_UNSIGNED_BYTE:
-         ibuffer.index_size = 1;
-         break;
-      default:
-         assert(0);
-	 return;
-      }
-
-      if (bufobj && bufobj->Name) {
-         struct st_buffer_object *stobj = st_buffer_object(bufobj);
-
-         pipe_resource_reference(&ibuffer.buffer, stobj->buffer);
-         ibuffer.offset = pointer_to_offset(ib->ptr);
-
-         mapped_indices = pipe_buffer_map(pipe, stobj->buffer,
-                                          PIPE_TRANSFER_READ, &ib_transfer);
-      }
-      else {
-         /* skip setting ibuffer.buffer as the draw module does not use it */
-         mapped_indices = ib->ptr;
-      }
-
-      draw_set_index_buffer(draw, &ibuffer);
-      draw_set_mapped_index_buffer(draw, mapped_indices);
-   }
-
-   /* set the constant buffer */
-   draw_set_mapped_constant_buffer(st->draw, PIPE_SHADER_VERTEX, 0,
-                                   st->state.constants[PIPE_SHADER_VERTEX].ptr,
-                                   st->state.constants[PIPE_SHADER_VERTEX].size);
-
-
-   /* draw here */
-   for (i = 0; i < nr_prims; i++) {
-      draw_arrays(draw, prims[i].mode, prims[i].start, prims[i].count);
-   }
-
-
-   /*
-    * unmap vertex/index buffers
-    */
-   for (i = 0; i < PIPE_MAX_ATTRIBS; i++) {
-      if (draw->pt.vertex_buffer[i].buffer) {
-         pipe_buffer_unmap(pipe, vb_transfer[i]);
-         pipe_resource_reference(&draw->pt.vertex_buffer[i].buffer, NULL);
-         draw_set_mapped_vertex_buffer(draw, i, NULL);
-      }
-   }
-
-   if (ib) {
-      draw_set_mapped_index_buffer(draw, NULL);
-      draw_set_index_buffer(draw, NULL);
-
-      if (ib_transfer)
-         pipe_buffer_unmap(pipe, ib_transfer);
-      pipe_resource_reference(&ibuffer.buffer, NULL);
-   }
-}
-
-#endif /* FEATURE_feedback || FEATURE_rastpos */
-
+/**************************************************************************
+ * 
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * 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"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#include "main/imports.h"
+#include "main/image.h"
+#include "main/macros.h"
+#include "main/mfeatures.h"
+
+#include "vbo/vbo.h"
+
+#include "st_context.h"
+#include "st_atom.h"
+#include "st_cb_bufferobjects.h"
+#include "st_draw.h"
+#include "st_program.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "util/u_inlines.h"
+
+#include "draw/draw_private.h"
+#include "draw/draw_context.h"
+
+
+#if FEATURE_feedback || FEATURE_rastpos
+
+/**
+ * Set the (private) draw module's post-transformed vertex format when in
+ * GL_SELECT or GL_FEEDBACK mode or for glRasterPos.
+ */
+static void
+set_feedback_vertex_format(struct gl_context *ctx)
+{
+#if 0
+   struct st_context *st = st_context(ctx);
+   struct vertex_info vinfo;
+   GLuint i;
+
+   memset(&vinfo, 0, sizeof(vinfo));
+
+   if (ctx->RenderMode == GL_SELECT) {
+      assert(ctx->RenderMode == GL_SELECT);
+      vinfo.num_attribs = 1;
+      vinfo.format[0] = FORMAT_4F;
+      vinfo.interp_mode[0] = INTERP_LINEAR;
+   }
+   else {
+      /* GL_FEEDBACK, or glRasterPos */
+      /* emit all attribs (pos, color, texcoord) as GLfloat[4] */
+      vinfo.num_attribs = st->state.vs->cso->state.num_outputs;
+      for (i = 0; i < vinfo.num_attribs; i++) {
+         vinfo.format[i] = FORMAT_4F;
+         vinfo.interp_mode[i] = INTERP_LINEAR;
+      }
+   }
+
+   draw_set_vertex_info(st->draw, &vinfo);
+#endif
+}
+
+
+/**
+ * Called by VBO to draw arrays when in selection or feedback mode and
+ * to implement glRasterPos.
+ * This is very much like the normal draw_vbo() function above.
+ * Look at code refactoring some day.
+ * Might move this into the failover module some day.
+ */
+void
+st_feedback_draw_vbo(struct gl_context *ctx,
+                     const struct gl_client_array **arrays,
+                     const struct _mesa_prim *prims,
+                     GLuint nr_prims,
+                     const struct _mesa_index_buffer *ib,
+		     GLboolean index_bounds_valid,
+                     GLuint min_index,
+                     GLuint max_index)
+{
+   struct st_context *st = st_context(ctx);
+   struct pipe_context *pipe = st->pipe;
+   struct draw_context *draw = st->draw;
+   const struct st_vertex_program *vp;
+   const struct pipe_shader_state *vs;
+   struct pipe_vertex_buffer vbuffers[PIPE_MAX_SHADER_INPUTS];
+   struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS];
+   struct pipe_index_buffer ibuffer;
+   struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS];
+   struct pipe_transfer *ib_transfer = NULL;
+   GLuint attr, i;
+   const void *mapped_indices = NULL;
+
+   assert(draw);
+
+   st_validate_state(st);
+
+   if (!index_bounds_valid)
+      vbo_get_minmax_index(ctx, prims, ib, &min_index, &max_index);
+
+   /* must get these after state validation! */
+   vp = st->vp;
+   vs = &st->vp_variant->tgsi;
+
+   if (!st->vp_variant->draw_shader) {
+      st->vp_variant->draw_shader = draw_create_vertex_shader(draw, vs);
+   }
+
+   /*
+    * Set up the draw module's state.
+    *
+    * We'd like to do this less frequently, but the normal state-update
+    * code sends state updates to the pipe, not to our private draw module.
+    */
+   assert(draw);
+   draw_set_viewport_state(draw, &st->state.viewport);
+   draw_set_clip_state(draw, &st->state.clip);
+   draw_set_rasterizer_state(draw, &st->state.rasterizer, NULL);
+   draw_bind_vertex_shader(draw, st->vp_variant->draw_shader);
+   set_feedback_vertex_format(ctx);
+
+   /* loop over TGSI shader inputs to determine vertex buffer
+    * and attribute info
+    */
+   for (attr = 0; attr < vp->num_inputs; attr++) {
+      const GLuint mesaAttr = vp->index_to_input[attr];
+      struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj;
+      void *map;
+
+      if (bufobj && bufobj->Name) {
+         /* Attribute data is in a VBO.
+          * Recall that for VBOs, the gl_client_array->Ptr field is
+          * really an offset from the start of the VBO, not a pointer.
+          */
+         struct st_buffer_object *stobj = st_buffer_object(bufobj);
+         assert(stobj->buffer);
+
+         vbuffers[attr].buffer = NULL;
+         pipe_resource_reference(&vbuffers[attr].buffer, stobj->buffer);
+         vbuffers[attr].buffer_offset = pointer_to_offset(arrays[0]->Ptr);
+         velements[attr].src_offset = arrays[mesaAttr]->Ptr - arrays[0]->Ptr;
+      }
+      else {
+         /* attribute data is in user-space memory, not a VBO */
+         uint bytes = (arrays[mesaAttr]->Size
+                       * _mesa_sizeof_type(arrays[mesaAttr]->Type)
+                       * (max_index + 1));
+
+         /* wrap user data */
+         vbuffers[attr].buffer
+            = pipe_user_buffer_create(pipe->screen, (void *) arrays[mesaAttr]->Ptr,
+                                      bytes,
+				      PIPE_BIND_VERTEX_BUFFER);
+         vbuffers[attr].buffer_offset = 0;
+         velements[attr].src_offset = 0;
+      }
+
+      /* common-case setup */
+      vbuffers[attr].stride = arrays[mesaAttr]->StrideB; /* in bytes */
+      vbuffers[attr].max_index = max_index;
+      velements[attr].instance_divisor = 0;
+      velements[attr].vertex_buffer_index = attr;
+      velements[attr].src_format = 
+         st_pipe_vertex_format(arrays[mesaAttr]->Type,
+                               arrays[mesaAttr]->Size,
+                               arrays[mesaAttr]->Format,
+                               arrays[mesaAttr]->Normalized);
+      assert(velements[attr].src_format);
+
+      /* tell draw about this attribute */
+#if 0
+      draw_set_vertex_buffer(draw, attr, &vbuffer[attr]);
+#endif
+
+      /* map the attrib buffer */
+      map = pipe_buffer_map(pipe, vbuffers[attr].buffer,
+                            PIPE_TRANSFER_READ,
+			    &vb_transfer[attr]);
+      draw_set_mapped_vertex_buffer(draw, attr, map);
+   }
+
+   draw_set_vertex_buffers(draw, vp->num_inputs, vbuffers);
+   draw_set_vertex_elements(draw, vp->num_inputs, velements);
+
+   memset(&ibuffer, 0, sizeof(ibuffer));
+   if (ib) {
+      struct gl_buffer_object *bufobj = ib->obj;
+
+      switch (ib->type) {
+      case GL_UNSIGNED_INT:
+         ibuffer.index_size = 4;
+         break;
+      case GL_UNSIGNED_SHORT:
+         ibuffer.index_size = 2;
+         break;
+      case GL_UNSIGNED_BYTE:
+         ibuffer.index_size = 1;
+         break;
+      default:
+         assert(0);
+	 return;
+      }
+
+      if (bufobj && bufobj->Name) {
+         struct st_buffer_object *stobj = st_buffer_object(bufobj);
+
+         pipe_resource_reference(&ibuffer.buffer, stobj->buffer);
+         ibuffer.offset = pointer_to_offset(ib->ptr);
+
+         mapped_indices = pipe_buffer_map(pipe, stobj->buffer,
+                                          PIPE_TRANSFER_READ, &ib_transfer);
+      }
+      else {
+         /* skip setting ibuffer.buffer as the draw module does not use it */
+         mapped_indices = ib->ptr;
+      }
+
+      draw_set_index_buffer(draw, &ibuffer);
+      draw_set_mapped_index_buffer(draw, mapped_indices);
+   }
+
+   /* set the constant buffer */
+   draw_set_mapped_constant_buffer(st->draw, PIPE_SHADER_VERTEX, 0,
+                                   st->state.constants[PIPE_SHADER_VERTEX].ptr,
+                                   st->state.constants[PIPE_SHADER_VERTEX].size);
+
+
+   /* draw here */
+   for (i = 0; i < nr_prims; i++) {
+      draw_arrays(draw, prims[i].mode, prims[i].start, prims[i].count);
+   }
+
+
+   /*
+    * unmap vertex/index buffers
+    */
+   for (i = 0; i < PIPE_MAX_ATTRIBS; i++) {
+      if (draw->pt.vertex_buffer[i].buffer) {
+         pipe_buffer_unmap(pipe, vb_transfer[i]);
+         pipe_resource_reference(&draw->pt.vertex_buffer[i].buffer, NULL);
+         draw_set_mapped_vertex_buffer(draw, i, NULL);
+         pipe_resource_reference(&vbuffers[i].buffer, NULL);
+      }
+   }
+
+   if (ib) {
+      draw_set_mapped_index_buffer(draw, NULL);
+      draw_set_index_buffer(draw, NULL);
+
+      if (ib_transfer)
+         pipe_buffer_unmap(pipe, ib_transfer);
+      pipe_resource_reference(&ibuffer.buffer, NULL);
+   }
+}
+
+#endif /* FEATURE_feedback || FEATURE_rastpos */
+
diff --git a/mesalib/src/mesa/state_tracker/st_program.c b/mesalib/src/mesa/state_tracker/st_program.c
index f70e5005f..fc1dfb3ef 100644
--- a/mesalib/src/mesa/state_tracker/st_program.c
+++ b/mesalib/src/mesa/state_tracker/st_program.c
@@ -1,1154 +1,1165 @@
-/**************************************************************************
- * 
- * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
- * 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"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
- **************************************************************************/
- /*
-  * Authors:
-  *   Keith Whitwell <keith@tungstengraphics.com>
-  *   Brian Paul
-  */
-
-
-#include "main/imports.h"
-#include "main/hash.h"
-#include "main/mfeatures.h"
-#include "main/mtypes.h"
-#include "program/prog_parameter.h"
-#include "program/prog_print.h"
-#include "program/programopt.h"
-
-#include "pipe/p_context.h"
-#include "pipe/p_defines.h"
-#include "pipe/p_shader_tokens.h"
-#include "draw/draw_context.h"
-#include "tgsi/tgsi_dump.h"
-#include "tgsi/tgsi_ureg.h"
-
-#include "st_debug.h"
-#include "st_cb_bitmap.h"
-#include "st_cb_drawpixels.h"
-#include "st_context.h"
-#include "st_program.h"
-#include "st_mesa_to_tgsi.h"
-#include "cso_cache/cso_context.h"
-
-
-
-/**
- * Delete a vertex program variant.  Note the caller must unlink
- * the variant from the linked list.
- */
-static void
-delete_vp_variant(struct st_context *st, struct st_vp_variant *vpv)
-{
-   if (vpv->driver_shader) 
-      cso_delete_vertex_shader(st->cso_context, vpv->driver_shader);
-      
-#if FEATURE_feedback || FEATURE_rastpos
-   if (vpv->draw_shader)
-      draw_delete_vertex_shader( st->draw, vpv->draw_shader );
-#endif
-      
-   if (vpv->tgsi.tokens)
-      st_free_tokens(vpv->tgsi.tokens);
-      
-   FREE( vpv );
-}
-
-
-
-/**
- * Clean out any old compilations:
- */
-void
-st_release_vp_variants( struct st_context *st,
-                        struct st_vertex_program *stvp )
-{
-   struct st_vp_variant *vpv;
-
-   for (vpv = stvp->variants; vpv; ) {
-      struct st_vp_variant *next = vpv->next;
-      delete_vp_variant(st, vpv);
-      vpv = next;
-   }
-
-   stvp->variants = NULL;
-}
-
-
-
-/**
- * Delete a fragment program variant.  Note the caller must unlink
- * the variant from the linked list.
- */
-static void
-delete_fp_variant(struct st_context *st, struct st_fp_variant *fpv)
-{
-   if (fpv->driver_shader) 
-      cso_delete_fragment_shader(st->cso_context, fpv->driver_shader);
-      
-   FREE(fpv);
-}
-
-
-/**
- * Free all variants of a fragment program.
- */
-void
-st_release_fp_variants(struct st_context *st, struct st_fragment_program *stfp)
-{
-   struct st_fp_variant *fpv;
-
-   for (fpv = stfp->variants; fpv; ) {
-      struct st_fp_variant *next = fpv->next;
-      delete_fp_variant(st, fpv);
-      fpv = next;
-   }
-
-   stfp->variants = NULL;
-}
-
-
-/**
- * Delete a geometry program variant.  Note the caller must unlink
- * the variant from the linked list.
- */
-static void
-delete_gp_variant(struct st_context *st, struct st_gp_variant *gpv)
-{
-   if (gpv->driver_shader) 
-      cso_delete_geometry_shader(st->cso_context, gpv->driver_shader);
-      
-   FREE(gpv);
-}
-
-
-/**
- * Free all variants of a geometry program.
- */
-void
-st_release_gp_variants(struct st_context *st, struct st_geometry_program *stgp)
-{
-   struct st_gp_variant *gpv;
-
-   for (gpv = stgp->variants; gpv; ) {
-      struct st_gp_variant *next = gpv->next;
-      delete_gp_variant(st, gpv);
-      gpv = next;
-   }
-
-   stgp->variants = NULL;
-}
-
-
-
-
-/**
- * Translate a Mesa vertex shader into a TGSI shader.
- * \param outputMapping  to map vertex program output registers (VERT_RESULT_x)
- *       to TGSI output slots
- * \param tokensOut  destination for TGSI tokens
- * \return  pointer to cached pipe_shader object.
- */
-static void
-st_prepare_vertex_program(struct st_context *st,
-                            struct st_vertex_program *stvp)
-{
-   GLuint attr;
-
-   stvp->num_inputs = 0;
-   stvp->num_outputs = 0;
-
-   if (stvp->Base.IsPositionInvariant)
-      _mesa_insert_mvp_code(st->ctx, &stvp->Base);
-
-   assert(stvp->Base.Base.NumInstructions > 1);
-
-   /*
-    * Determine number of inputs, the mappings between VERT_ATTRIB_x
-    * and TGSI generic input indexes, plus input attrib semantic info.
-    */
-   for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
-      if (stvp->Base.Base.InputsRead & (1 << attr)) {
-         stvp->input_to_index[attr] = stvp->num_inputs;
-         stvp->index_to_input[stvp->num_inputs] = attr;
-         stvp->num_inputs++;
-      }
-   }
-   /* bit of a hack, presetup potentially unused edgeflag input */
-   stvp->input_to_index[VERT_ATTRIB_EDGEFLAG] = stvp->num_inputs;
-   stvp->index_to_input[stvp->num_inputs] = VERT_ATTRIB_EDGEFLAG;
-
-   /* Compute mapping of vertex program outputs to slots.
-    */
-   for (attr = 0; attr < VERT_RESULT_MAX; attr++) {
-      if ((stvp->Base.Base.OutputsWritten & BITFIELD64_BIT(attr)) == 0) {
-         stvp->result_to_output[attr] = ~0;
-      }
-      else {
-         unsigned slot = stvp->num_outputs++;
-
-         stvp->result_to_output[attr] = slot;
-
-         switch (attr) {
-         case VERT_RESULT_HPOS:
-            stvp->output_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
-            stvp->output_semantic_index[slot] = 0;
-            break;
-         case VERT_RESULT_COL0:
-            stvp->output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
-            stvp->output_semantic_index[slot] = 0;
-            break;
-         case VERT_RESULT_COL1:
-            stvp->output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
-            stvp->output_semantic_index[slot] = 1;
-            break;
-         case VERT_RESULT_BFC0:
-            stvp->output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
-            stvp->output_semantic_index[slot] = 0;
-            break;
-         case VERT_RESULT_BFC1:
-            stvp->output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
-            stvp->output_semantic_index[slot] = 1;
-            break;
-         case VERT_RESULT_FOGC:
-            stvp->output_semantic_name[slot] = TGSI_SEMANTIC_FOG;
-            stvp->output_semantic_index[slot] = 0;
-            break;
-         case VERT_RESULT_PSIZ:
-            stvp->output_semantic_name[slot] = TGSI_SEMANTIC_PSIZE;
-            stvp->output_semantic_index[slot] = 0;
-            break;
-         case VERT_RESULT_EDGE:
-            assert(0);
-            break;
-
-         case VERT_RESULT_TEX0:
-         case VERT_RESULT_TEX1:
-         case VERT_RESULT_TEX2:
-         case VERT_RESULT_TEX3:
-         case VERT_RESULT_TEX4:
-         case VERT_RESULT_TEX5:
-         case VERT_RESULT_TEX6:
-         case VERT_RESULT_TEX7:
-            stvp->output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
-            stvp->output_semantic_index[slot] = attr - VERT_RESULT_TEX0;
-            break;
-
-         case VERT_RESULT_VAR0:
-         default:
-            assert(attr < VERT_RESULT_MAX);
-            stvp->output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
-            stvp->output_semantic_index[slot] = (FRAG_ATTRIB_VAR0 - 
-                                                FRAG_ATTRIB_TEX0 +
-                                                attr - 
-                                                VERT_RESULT_VAR0);
-            break;
-         }
-      }
-   }
-   /* similar hack to above, presetup potentially unused edgeflag output */
-   stvp->result_to_output[VERT_RESULT_EDGE] = stvp->num_outputs;
-   stvp->output_semantic_name[stvp->num_outputs] = TGSI_SEMANTIC_EDGEFLAG;
-   stvp->output_semantic_index[stvp->num_outputs] = 0;
-}
-
-
-/**
- * Translate a vertex program to create a new variant.
- */
-static struct st_vp_variant *
-st_translate_vertex_program(struct st_context *st,
-                            struct st_vertex_program *stvp,
-                            const struct st_vp_variant_key *key)
-{
-   struct st_vp_variant *vpv = CALLOC_STRUCT(st_vp_variant);
-   struct pipe_context *pipe = st->pipe;
-   struct ureg_program *ureg;
-   enum pipe_error error;
-   unsigned num_outputs;
-
-   st_prepare_vertex_program( st, stvp );
-
-   _mesa_remove_output_reads(&stvp->Base.Base, PROGRAM_OUTPUT);
-   _mesa_remove_output_reads(&stvp->Base.Base, PROGRAM_VARYING);
-
-   ureg = ureg_create( TGSI_PROCESSOR_VERTEX );
-   if (ureg == NULL) {
-      FREE(vpv);
-      return NULL;
-   }
-
-   vpv->key = *key;
-
-   vpv->num_inputs = stvp->num_inputs;
-   num_outputs = stvp->num_outputs;
-   if (key->passthrough_edgeflags) {
-      vpv->num_inputs++;
-      num_outputs++;
-   }
-
-   if (ST_DEBUG & DEBUG_MESA) {
-      _mesa_print_program(&stvp->Base.Base);
-      _mesa_print_program_parameters(st->ctx, &stvp->Base.Base);
-      debug_printf("\n");
-   }
-
-   error = st_translate_mesa_program(st->ctx,
-                                     TGSI_PROCESSOR_VERTEX,
-                                     ureg,
-                                     &stvp->Base.Base,
-                                     /* inputs */
-                                     vpv->num_inputs,
-                                     stvp->input_to_index,
-                                     NULL, /* input semantic name */
-                                     NULL, /* input semantic index */
-                                     NULL,
-                                     /* outputs */
-                                     num_outputs,
-                                     stvp->result_to_output,
-                                     stvp->output_semantic_name,
-                                     stvp->output_semantic_index,
-                                     key->passthrough_edgeflags );
-
-   if (error)
-      goto fail;
-
-   vpv->tgsi.tokens = ureg_get_tokens( ureg, NULL );
-   if (!vpv->tgsi.tokens)
-      goto fail;
-
-   ureg_destroy( ureg );
-
-   vpv->driver_shader = pipe->create_vs_state(pipe, &vpv->tgsi);
-
-   if (ST_DEBUG & DEBUG_TGSI) {
-      tgsi_dump( vpv->tgsi.tokens, 0 );
-      debug_printf("\n");
-   }
-
-   return vpv;
-
-fail:
-   debug_printf("%s: failed to translate Mesa program:\n", __FUNCTION__);
-   _mesa_print_program(&stvp->Base.Base);
-   debug_assert(0);
-
-   ureg_destroy( ureg );
-   return NULL;
-}
-
-
-/**
- * Find/create a vertex program variant.
- */
-struct st_vp_variant *
-st_get_vp_variant(struct st_context *st,
-                  struct st_vertex_program *stvp,
-                  const struct st_vp_variant_key *key)
-{
-   struct st_vp_variant *vpv;
-
-   /* Search for existing variant */
-   for (vpv = stvp->variants; vpv; vpv = vpv->next) {
-      if (memcmp(&vpv->key, key, sizeof(*key)) == 0) {
-         break;
-      }
-   }
-
-   if (!vpv) {
-      /* create now */
-      vpv = st_translate_vertex_program(st, stvp, key);
-      if (vpv) {
-         /* insert into list */
-         vpv->next = stvp->variants;
-         stvp->variants = vpv;
-      }
-   }
-
-   return vpv;
-}
-
-
-/**
- * Translate a Mesa fragment shader into a TGSI shader using extra info in
- * the key.
- * \return  new fragment program variant
- */
-static struct st_fp_variant *
-st_translate_fragment_program(struct st_context *st,
-                              struct st_fragment_program *stfp,
-                              const struct st_fp_variant_key *key)
-{
-   struct pipe_context *pipe = st->pipe;
-   struct st_fp_variant *variant = CALLOC_STRUCT(st_fp_variant);
-
-   if (!variant)
-      return NULL;
-
-   assert(!(key->bitmap && key->drawpixels));
-
-#if FEATURE_drawpix
-   if (key->bitmap) {
-      /* glBitmap drawing */
-      struct gl_fragment_program *fp;
-
-      st_make_bitmap_fragment_program(st, &stfp->Base,
-                                      &fp, &variant->bitmap_sampler);
-
-      variant->parameters = _mesa_clone_parameter_list(fp->Base.Parameters);
-      stfp = st_fragment_program(fp);
-   }
-   else if (key->drawpixels) {
-      /* glDrawPixels drawing */
-      struct gl_fragment_program *fp;
-
-      if (key->drawpixels_z || key->drawpixels_stencil) {
-         fp = st_make_drawpix_z_stencil_program(st, key->drawpixels_z,
-                                                key->drawpixels_stencil);
-      }
-      else {
-         /* RGBA */
-         st_make_drawpix_fragment_program(st, &stfp->Base, &fp);
-         variant->parameters = _mesa_clone_parameter_list(fp->Base.Parameters);
-      }
-      stfp = st_fragment_program(fp);
-   }
-#endif
-
-   if (!stfp->tgsi.tokens) {
-      /* need to translate Mesa instructions to TGSI now */
-      GLuint outputMapping[FRAG_RESULT_MAX];
-      GLuint inputMapping[FRAG_ATTRIB_MAX];
-      GLuint interpMode[PIPE_MAX_SHADER_INPUTS];  /* XXX size? */
-      GLuint attr;
-      enum pipe_error error;
-      const GLbitfield inputsRead = stfp->Base.Base.InputsRead;
-      struct ureg_program *ureg;
-      GLboolean write_all = GL_FALSE;
-
-      ubyte input_semantic_name[PIPE_MAX_SHADER_INPUTS];
-      ubyte input_semantic_index[PIPE_MAX_SHADER_INPUTS];
-      uint fs_num_inputs = 0;
-
-      ubyte fs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS];
-      ubyte fs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS];
-      uint fs_num_outputs = 0;
-
-
-      _mesa_remove_output_reads(&stfp->Base.Base, PROGRAM_OUTPUT);
-
-      /*
-       * Convert Mesa program inputs to TGSI input register semantics.
-       */
-      for (attr = 0; attr < FRAG_ATTRIB_MAX; attr++) {
-         if (inputsRead & (1 << attr)) {
-            const GLuint slot = fs_num_inputs++;
-
-            inputMapping[attr] = slot;
-
-            switch (attr) {
-            case FRAG_ATTRIB_WPOS:
-               input_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
-               input_semantic_index[slot] = 0;
-               interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
-               break;
-            case FRAG_ATTRIB_COL0:
-               input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
-               input_semantic_index[slot] = 0;
-               interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
-               break;
-            case FRAG_ATTRIB_COL1:
-               input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
-               input_semantic_index[slot] = 1;
-               interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
-               break;
-            case FRAG_ATTRIB_FOGC:
-               input_semantic_name[slot] = TGSI_SEMANTIC_FOG;
-               input_semantic_index[slot] = 0;
-               interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
-               break;
-            case FRAG_ATTRIB_FACE:
-               input_semantic_name[slot] = TGSI_SEMANTIC_FACE;
-               input_semantic_index[slot] = 0;
-               interpMode[slot] = TGSI_INTERPOLATE_CONSTANT;
-               break;
-               /* In most cases, there is nothing special about these
-                * inputs, so adopt a convention to use the generic
-                * semantic name and the mesa FRAG_ATTRIB_ number as the
-                * index. 
-                * 
-                * All that is required is that the vertex shader labels
-                * its own outputs similarly, and that the vertex shader
-                * generates at least every output required by the
-                * fragment shader plus fixed-function hardware (such as
-                * BFC).
-                * 
-                * There is no requirement that semantic indexes start at
-                * zero or be restricted to a particular range -- nobody
-                * should be building tables based on semantic index.
-                */
-            case FRAG_ATTRIB_PNTC:
-            case FRAG_ATTRIB_TEX0:
-            case FRAG_ATTRIB_TEX1:
-            case FRAG_ATTRIB_TEX2:
-            case FRAG_ATTRIB_TEX3:
-            case FRAG_ATTRIB_TEX4:
-            case FRAG_ATTRIB_TEX5:
-            case FRAG_ATTRIB_TEX6:
-            case FRAG_ATTRIB_TEX7:
-            case FRAG_ATTRIB_VAR0:
-            default:
-               /* Actually, let's try and zero-base this just for
-                * readability of the generated TGSI.
-                */
-               assert(attr >= FRAG_ATTRIB_TEX0);
-               input_semantic_index[slot] = (attr - FRAG_ATTRIB_TEX0);
-               input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
-               if (attr == FRAG_ATTRIB_PNTC)
-                  interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
-               else
-                  interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
-               break;
-            }
-         }
-         else {
-            inputMapping[attr] = -1;
-         }
-      }
-
-      /*
-       * Semantics and mapping for outputs
-       */
-      {
-         uint numColors = 0;
-         GLbitfield64 outputsWritten = stfp->Base.Base.OutputsWritten;
-
-         /* if z is written, emit that first */
-         if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) {
-            fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_POSITION;
-            fs_output_semantic_index[fs_num_outputs] = 0;
-            outputMapping[FRAG_RESULT_DEPTH] = fs_num_outputs;
-            fs_num_outputs++;
-            outputsWritten &= ~(1 << FRAG_RESULT_DEPTH);
-         }
-
-         if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_STENCIL)) {
-            fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_STENCIL;
-            fs_output_semantic_index[fs_num_outputs] = 0;
-            outputMapping[FRAG_RESULT_STENCIL] = fs_num_outputs;
-            fs_num_outputs++;
-            outputsWritten &= ~(1 << FRAG_RESULT_STENCIL);
-         }
-
-         /* handle remaning outputs (color) */
-         for (attr = 0; attr < FRAG_RESULT_MAX; attr++) {
-            if (outputsWritten & BITFIELD64_BIT(attr)) {
-               switch (attr) {
-               case FRAG_RESULT_DEPTH:
-               case FRAG_RESULT_STENCIL:
-                  /* handled above */
-                  assert(0);
-                  break;
-               case FRAG_RESULT_COLOR:
-                  write_all = GL_TRUE; /* fallthrough */
-               default:
-                  assert(attr == FRAG_RESULT_COLOR ||
-                         (FRAG_RESULT_DATA0 <= attr && attr < FRAG_RESULT_MAX));
-                  fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_COLOR;
-                  fs_output_semantic_index[fs_num_outputs] = numColors;
-                  outputMapping[attr] = fs_num_outputs;
-                  numColors++;
-                  break;
-               }
-
-               fs_num_outputs++;
-            }
-         }
-      }
-
-      ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
-      if (ureg == NULL)
-         return NULL;
-
-      if (ST_DEBUG & DEBUG_MESA) {
-         _mesa_print_program(&stfp->Base.Base);
-         _mesa_print_program_parameters(st->ctx, &stfp->Base.Base);
-         debug_printf("\n");
-      }
-      if (write_all == GL_TRUE)
-         ureg_property_fs_color0_writes_all_cbufs(ureg, 1);
-
-      error = st_translate_mesa_program(st->ctx,
-                                        TGSI_PROCESSOR_FRAGMENT,
-                                        ureg,
-                                        &stfp->Base.Base,
-                                        /* inputs */
-                                        fs_num_inputs,
-                                        inputMapping,
-                                        input_semantic_name,
-                                        input_semantic_index,
-                                        interpMode,
-                                        /* outputs */
-                                        fs_num_outputs,
-                                        outputMapping,
-                                        fs_output_semantic_name,
-                                        fs_output_semantic_index, FALSE );
-
-      stfp->tgsi.tokens = ureg_get_tokens( ureg, NULL );
-      ureg_destroy( ureg );
-   }
-
-   /* fill in variant */
-   variant->driver_shader = pipe->create_fs_state(pipe, &stfp->tgsi);
-   variant->key = *key;
-
-   if (ST_DEBUG & DEBUG_TGSI) {
-      tgsi_dump( stfp->tgsi.tokens, 0/*TGSI_DUMP_VERBOSE*/ );
-      debug_printf("\n");
-   }
-
-   return variant;
-}
-
-
-/**
- * Translate fragment program if needed.
- */
-struct st_fp_variant *
-st_get_fp_variant(struct st_context *st,
-                  struct st_fragment_program *stfp,
-                  const struct st_fp_variant_key *key)
-{
-   struct st_fp_variant *fpv;
-
-   /* Search for existing variant */
-   for (fpv = stfp->variants; fpv; fpv = fpv->next) {
-      if (memcmp(&fpv->key, key, sizeof(*key)) == 0) {
-         break;
-      }
-   }
-
-   if (!fpv) {
-      /* create new */
-      fpv = st_translate_fragment_program(st, stfp, key);
-      if (fpv) {
-         /* insert into list */
-         fpv->next = stfp->variants;
-         stfp->variants = fpv;
-      }
-   }
-
-   return fpv;
-}
-
-
-/**
- * Translate a geometry program to create a new variant.
- */
-static struct st_gp_variant *
-st_translate_geometry_program(struct st_context *st,
-                              struct st_geometry_program *stgp,
-                              const struct st_gp_variant_key *key)
-{
-   GLuint inputMapping[GEOM_ATTRIB_MAX];
-   GLuint outputMapping[GEOM_RESULT_MAX];
-   struct pipe_context *pipe = st->pipe;
-   enum pipe_error error;
-   GLuint attr;
-   const GLbitfield inputsRead = stgp->Base.Base.InputsRead;
-   GLuint vslot = 0;
-   GLuint num_generic = 0;
-
-   uint gs_num_inputs = 0;
-   uint gs_builtin_inputs = 0;
-   uint gs_array_offset = 0;
-
-   ubyte gs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS];
-   ubyte gs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS];
-   uint gs_num_outputs = 0;
-
-   GLint i;
-   GLuint maxSlot = 0;
-   struct ureg_program *ureg;
-
-   struct st_gp_variant *gpv;
-
-   gpv = CALLOC_STRUCT(st_gp_variant);
-   if (!gpv)
-      return NULL;
-
-   _mesa_remove_output_reads(&stgp->Base.Base, PROGRAM_OUTPUT);
-   _mesa_remove_output_reads(&stgp->Base.Base, PROGRAM_VARYING);
-
-   ureg = ureg_create( TGSI_PROCESSOR_GEOMETRY );
-   if (ureg == NULL) {
-      FREE(gpv);
-      return NULL;
-   }
-
-   /* which vertex output goes to the first geometry input */
-   vslot = 0;
-
-   memset(inputMapping, 0, sizeof(inputMapping));
-   memset(outputMapping, 0, sizeof(outputMapping));
-
-   /*
-    * Convert Mesa program inputs to TGSI input register semantics.
-    */
-   for (attr = 0; attr < GEOM_ATTRIB_MAX; attr++) {
-      if (inputsRead & (1 << attr)) {
-         const GLuint slot = gs_num_inputs;
-
-         gs_num_inputs++;
-
-         inputMapping[attr] = slot;
-
-         stgp->input_map[slot + gs_array_offset] = vslot - gs_builtin_inputs;
-         stgp->input_to_index[attr] = vslot;
-         stgp->index_to_input[vslot] = attr;
-         ++vslot;
-
-         if (attr != GEOM_ATTRIB_PRIMITIVE_ID) {
-            gs_array_offset += 2;
-         } else
-            ++gs_builtin_inputs;
-
-#if 0
-         debug_printf("input map at %d = %d\n",
-                      slot + gs_array_offset, stgp->input_map[slot + gs_array_offset]);
-#endif
-
-         switch (attr) {
-         case GEOM_ATTRIB_PRIMITIVE_ID:
-            stgp->input_semantic_name[slot] = TGSI_SEMANTIC_PRIMID;
-            stgp->input_semantic_index[slot] = 0;
-            break;
-         case GEOM_ATTRIB_POSITION:
-            stgp->input_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
-            stgp->input_semantic_index[slot] = 0;
-            break;
-         case GEOM_ATTRIB_COLOR0:
-            stgp->input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
-            stgp->input_semantic_index[slot] = 0;
-            break;
-         case GEOM_ATTRIB_COLOR1:
-            stgp->input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
-            stgp->input_semantic_index[slot] = 1;
-            break;
-         case GEOM_ATTRIB_FOG_FRAG_COORD:
-            stgp->input_semantic_name[slot] = TGSI_SEMANTIC_FOG;
-            stgp->input_semantic_index[slot] = 0;
-            break;
-         case GEOM_ATTRIB_TEX_COORD:
-            stgp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
-            stgp->input_semantic_index[slot] = num_generic++;
-            break;
-         case GEOM_ATTRIB_VAR0:
-            /* fall-through */
-         default:
-            stgp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
-            stgp->input_semantic_index[slot] = num_generic++;
-         }
-      }
-   }
-
-   /* initialize output semantics to defaults */
-   for (i = 0; i < PIPE_MAX_SHADER_OUTPUTS; i++) {
-      gs_output_semantic_name[i] = TGSI_SEMANTIC_GENERIC;
-      gs_output_semantic_index[i] = 0;
-   }
-
-   num_generic = 0;
-   /*
-    * Determine number of outputs, the (default) output register
-    * mapping and the semantic information for each output.
-    */
-   for (attr = 0; attr < GEOM_RESULT_MAX; attr++) {
-      if (stgp->Base.Base.OutputsWritten & (1 << attr)) {
-         GLuint slot;
-
-         slot = gs_num_outputs;
-         gs_num_outputs++;
-         outputMapping[attr] = slot;
-
-         switch (attr) {
-         case GEOM_RESULT_POS:
-            assert(slot == 0);
-            gs_output_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
-            gs_output_semantic_index[slot] = 0;
-            break;
-         case GEOM_RESULT_COL0:
-            gs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
-            gs_output_semantic_index[slot] = 0;
-            break;
-         case GEOM_RESULT_COL1:
-            gs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
-            gs_output_semantic_index[slot] = 1;
-            break;
-         case GEOM_RESULT_SCOL0:
-            gs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
-            gs_output_semantic_index[slot] = 0;
-            break;
-         case GEOM_RESULT_SCOL1:
-            gs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
-            gs_output_semantic_index[slot] = 1;
-            break;
-         case GEOM_RESULT_FOGC:
-            gs_output_semantic_name[slot] = TGSI_SEMANTIC_FOG;
-            gs_output_semantic_index[slot] = 0;
-            break;
-         case GEOM_RESULT_PSIZ:
-            gs_output_semantic_name[slot] = TGSI_SEMANTIC_PSIZE;
-            gs_output_semantic_index[slot] = 0;
-            break;
-         case GEOM_RESULT_TEX0:
-         case GEOM_RESULT_TEX1:
-         case GEOM_RESULT_TEX2:
-         case GEOM_RESULT_TEX3:
-         case GEOM_RESULT_TEX4:
-         case GEOM_RESULT_TEX5:
-         case GEOM_RESULT_TEX6:
-         case GEOM_RESULT_TEX7:
-            /* fall-through */
-         case GEOM_RESULT_VAR0:
-            /* fall-through */
-         default:
-            assert(slot < Elements(gs_output_semantic_name));
-            /* use default semantic info */
-            gs_output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
-            gs_output_semantic_index[slot] = num_generic++;
-         }
-      }
-   }
-
-   assert(gs_output_semantic_name[0] == TGSI_SEMANTIC_POSITION);
-
-   /* find max output slot referenced to compute gs_num_outputs */
-   for (attr = 0; attr < GEOM_RESULT_MAX; attr++) {
-      if (outputMapping[attr] != ~0 && outputMapping[attr] > maxSlot)
-         maxSlot = outputMapping[attr];
-   }
-   gs_num_outputs = maxSlot + 1;
-
-#if 0 /* debug */
-   {
-      GLuint i;
-      printf("outputMapping? %d\n", outputMapping ? 1 : 0);
-      if (outputMapping) {
-         printf("attr -> slot\n");
-         for (i = 0; i < 16;  i++) {
-            printf(" %2d       %3d\n", i, outputMapping[i]);
-         }
-      }
-      printf("slot    sem_name  sem_index\n");
-      for (i = 0; i < gs_num_outputs; i++) {
-         printf(" %2d         %d         %d\n",
-                i,
-                gs_output_semantic_name[i],
-                gs_output_semantic_index[i]);
-      }
-   }
-#endif
-
-   /* free old shader state, if any */
-   if (stgp->tgsi.tokens) {
-      st_free_tokens(stgp->tgsi.tokens);
-      stgp->tgsi.tokens = NULL;
-   }
-
-   ureg_property_gs_input_prim(ureg, stgp->Base.InputType);
-   ureg_property_gs_output_prim(ureg, stgp->Base.OutputType);
-   ureg_property_gs_max_vertices(ureg, stgp->Base.VerticesOut);
-
-   error = st_translate_mesa_program(st->ctx,
-                                     TGSI_PROCESSOR_GEOMETRY,
-                                     ureg,
-                                     &stgp->Base.Base,
-                                     /* inputs */
-                                     gs_num_inputs,
-                                     inputMapping,
-                                     stgp->input_semantic_name,
-                                     stgp->input_semantic_index,
-                                     NULL,
-                                     /* outputs */
-                                     gs_num_outputs,
-                                     outputMapping,
-                                     gs_output_semantic_name,
-                                     gs_output_semantic_index,
-                                     FALSE);
-
-   stgp->num_inputs = gs_num_inputs;
-   stgp->tgsi.tokens = ureg_get_tokens( ureg, NULL );
-   ureg_destroy( ureg );
-
-   /* fill in new variant */
-   gpv->driver_shader = pipe->create_gs_state(pipe, &stgp->tgsi);
-   gpv->key = *key;
-
-   if ((ST_DEBUG & DEBUG_TGSI) && (ST_DEBUG & DEBUG_MESA)) {
-      _mesa_print_program(&stgp->Base.Base);
-      debug_printf("\n");
-   }
-
-   if (ST_DEBUG & DEBUG_TGSI) {
-      tgsi_dump(stgp->tgsi.tokens, 0);
-      debug_printf("\n");
-   }
-
-   return gpv;
-}
-
-
-/**
- * Get/create geometry program variant.
- */
-struct st_gp_variant *
-st_get_gp_variant(struct st_context *st,
-                  struct st_geometry_program *stgp,
-                  const struct st_gp_variant_key *key)
-{
-   struct st_gp_variant *gpv;
-
-   /* Search for existing variant */
-   for (gpv = stgp->variants; gpv; gpv = gpv->next) {
-      if (memcmp(&gpv->key, key, sizeof(*key)) == 0) {
-         break;
-      }
-   }
-
-   if (!gpv) {
-      /* create new */
-      gpv = st_translate_geometry_program(st, stgp, key);
-      if (gpv) {
-         /* insert into list */
-         gpv->next = stgp->variants;
-         stgp->variants = gpv;
-      }
-   }
-
-   return gpv;
-}
-
-
-
-
-/**
- * Debug- print current shader text
- */
-void
-st_print_shaders(struct gl_context *ctx)
-{
-   struct gl_shader_program *shProg[3] = {
-      ctx->Shader.CurrentVertexProgram,
-      ctx->Shader.CurrentGeometryProgram,
-      ctx->Shader.CurrentFragmentProgram,
-   };
-   unsigned j;
-
-   for (j = 0; j < 3; j++) {
-      unsigned i;
-
-      if (shProg[j] == NULL)
-	 continue;
-
-      for (i = 0; i < shProg[j]->NumShaders; i++) {
-	 struct gl_shader *sh;
-
-	 switch (shProg[j]->Shaders[i]->Type) {
-	 case GL_VERTEX_SHADER:
-	    sh = (i != 0) ? NULL : shProg[j]->Shaders[i];
-	    break;
-	 case GL_GEOMETRY_SHADER_ARB:
-	    sh = (i != 1) ? NULL : shProg[j]->Shaders[i];
-	    break;
-	 case GL_FRAGMENT_SHADER:
-	    sh = (i != 2) ? NULL : shProg[j]->Shaders[i];
-	    break;
-	 default:
-	    assert(0);
-	    sh = NULL;
-	    break;
-	 }
-
-	 if (sh != NULL) {
-	    printf("GLSL shader %u of %u:\n", i, shProg[j]->NumShaders);
-	    printf("%s\n", sh->Source);
-	 }
-      }
-   }
-}
-
-
-/**
- * Vert/Geom/Frag programs have per-context variants.  Free all the
- * variants attached to the given program which match the given context.
- */
-static void
-destroy_program_variants(struct st_context *st, struct gl_program *program)
-{
-   if (!program)
-      return;
-
-   switch (program->Target) {
-   case GL_VERTEX_PROGRAM_ARB:
-      {
-         struct st_vertex_program *stvp = (struct st_vertex_program *) program;
-         struct st_vp_variant *vpv, **prevPtr = &stvp->variants;
-
-         for (vpv = stvp->variants; vpv; ) {
-            struct st_vp_variant *next = vpv->next;
-            if (vpv->key.st == st) {
-               /* unlink from list */
-               *prevPtr = next;
-               /* destroy this variant */
-               delete_vp_variant(st, vpv);
-            }
-            else {
-               prevPtr = &vpv->next;
-            }
-            vpv = next;
-         }
-      }
-      break;
-   case GL_FRAGMENT_PROGRAM_ARB:
-      {
-         struct st_fragment_program *stfp =
-            (struct st_fragment_program *) program;
-         struct st_fp_variant *fpv, **prevPtr = &stfp->variants;
-
-         for (fpv = stfp->variants; fpv; ) {
-            struct st_fp_variant *next = fpv->next;
-            if (fpv->key.st == st) {
-               /* unlink from list */
-               *prevPtr = next;
-               /* destroy this variant */
-               delete_fp_variant(st, fpv);
-            }
-            else {
-               prevPtr = &fpv->next;
-            }
-            fpv = next;
-         }
-      }
-      break;
-   case MESA_GEOMETRY_PROGRAM:
-      {
-         struct st_geometry_program *stgp =
-            (struct st_geometry_program *) program;
-         struct st_gp_variant *gpv, **prevPtr = &stgp->variants;
-
-         for (gpv = stgp->variants; gpv; ) {
-            struct st_gp_variant *next = gpv->next;
-            if (gpv->key.st == st) {
-               /* unlink from list */
-               *prevPtr = next;
-               /* destroy this variant */
-               delete_gp_variant(st, gpv);
-            }
-            else {
-               prevPtr = &gpv->next;
-            }
-            gpv = next;
-         }
-      }
-      break;
-   default:
-      _mesa_problem(NULL, "Unexpected program target in "
-                    "destroy_program_variants_cb()");
-   }
-}
-
-
-/**
- * Callback for _mesa_HashWalk.  Free all the shader's program variants
- * which match the given context.
- */
-static void
-destroy_shader_program_variants_cb(GLuint key, void *data, void *userData)
-{
-   struct st_context *st = (struct st_context *) userData;
-   struct gl_shader *shader = (struct gl_shader *) data;
-
-   switch (shader->Type) {
-   case GL_SHADER_PROGRAM_MESA:
-      {
-         struct gl_shader_program *shProg = (struct gl_shader_program *) data;
-         GLuint i;
-
-         for (i = 0; i < shProg->NumShaders; i++) {
-            destroy_program_variants(st, shProg->Shaders[i]->Program);
-         }
-
-         destroy_program_variants(st, (struct gl_program *)
-                                  shProg->VertexProgram);
-         destroy_program_variants(st, (struct gl_program *)
-                                  shProg->FragmentProgram);
-         destroy_program_variants(st, (struct gl_program *)
-                                  shProg->GeometryProgram);
-      }
-      break;
-   case GL_VERTEX_SHADER:
-   case GL_FRAGMENT_SHADER:
-   case GL_GEOMETRY_SHADER:
-      {
-         destroy_program_variants(st, shader->Program);
-      }
-      break;
-   default:
-      assert(0);
-   }
-}
-
-
-/**
- * Callback for _mesa_HashWalk.  Free all the program variants which match
- * the given context.
- */
-static void
-destroy_program_variants_cb(GLuint key, void *data, void *userData)
-{
-   struct st_context *st = (struct st_context *) userData;
-   struct gl_program *program = (struct gl_program *) data;
-   destroy_program_variants(st, program);
-}
-
-
-/**
- * Walk over all shaders and programs to delete any variants which
- * belong to the given context.
- * This is called during context tear-down.
- */
-void
-st_destroy_program_variants(struct st_context *st)
-{
-   /* ARB vert/frag program */
-   _mesa_HashWalk(st->ctx->Shared->Programs,
-                  destroy_program_variants_cb, st);
-
-   /* GLSL vert/frag/geom shaders */
-   _mesa_HashWalk(st->ctx->Shared->ShaderObjects,
-                  destroy_shader_program_variants_cb, st);
-}
+/**************************************************************************
+ * 
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * 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"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+ /*
+  * Authors:
+  *   Keith Whitwell <keith@tungstengraphics.com>
+  *   Brian Paul
+  */
+
+
+#include "main/imports.h"
+#include "main/hash.h"
+#include "main/mfeatures.h"
+#include "main/mtypes.h"
+#include "program/prog_parameter.h"
+#include "program/prog_print.h"
+#include "program/programopt.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_shader_tokens.h"
+#include "draw/draw_context.h"
+#include "tgsi/tgsi_dump.h"
+#include "tgsi/tgsi_ureg.h"
+
+#include "st_debug.h"
+#include "st_cb_bitmap.h"
+#include "st_cb_drawpixels.h"
+#include "st_context.h"
+#include "st_program.h"
+#include "st_mesa_to_tgsi.h"
+#include "cso_cache/cso_context.h"
+
+
+
+/**
+ * Delete a vertex program variant.  Note the caller must unlink
+ * the variant from the linked list.
+ */
+static void
+delete_vp_variant(struct st_context *st, struct st_vp_variant *vpv)
+{
+   if (vpv->driver_shader) 
+      cso_delete_vertex_shader(st->cso_context, vpv->driver_shader);
+      
+#if FEATURE_feedback || FEATURE_rastpos
+   if (vpv->draw_shader)
+      draw_delete_vertex_shader( st->draw, vpv->draw_shader );
+#endif
+      
+   if (vpv->tgsi.tokens)
+      st_free_tokens(vpv->tgsi.tokens);
+      
+   FREE( vpv );
+}
+
+
+
+/**
+ * Clean out any old compilations:
+ */
+void
+st_release_vp_variants( struct st_context *st,
+                        struct st_vertex_program *stvp )
+{
+   struct st_vp_variant *vpv;
+
+   for (vpv = stvp->variants; vpv; ) {
+      struct st_vp_variant *next = vpv->next;
+      delete_vp_variant(st, vpv);
+      vpv = next;
+   }
+
+   stvp->variants = NULL;
+}
+
+
+
+/**
+ * Delete a fragment program variant.  Note the caller must unlink
+ * the variant from the linked list.
+ */
+static void
+delete_fp_variant(struct st_context *st, struct st_fp_variant *fpv)
+{
+   if (fpv->driver_shader) 
+      cso_delete_fragment_shader(st->cso_context, fpv->driver_shader);
+   if (fpv->parameters)
+      _mesa_free_parameter_list(fpv->parameters);
+      
+   FREE(fpv);
+}
+
+
+/**
+ * Free all variants of a fragment program.
+ */
+void
+st_release_fp_variants(struct st_context *st, struct st_fragment_program *stfp)
+{
+   struct st_fp_variant *fpv;
+
+   for (fpv = stfp->variants; fpv; ) {
+      struct st_fp_variant *next = fpv->next;
+      delete_fp_variant(st, fpv);
+      fpv = next;
+   }
+
+   stfp->variants = NULL;
+}
+
+
+/**
+ * Delete a geometry program variant.  Note the caller must unlink
+ * the variant from the linked list.
+ */
+static void
+delete_gp_variant(struct st_context *st, struct st_gp_variant *gpv)
+{
+   if (gpv->driver_shader) 
+      cso_delete_geometry_shader(st->cso_context, gpv->driver_shader);
+      
+   FREE(gpv);
+}
+
+
+/**
+ * Free all variants of a geometry program.
+ */
+void
+st_release_gp_variants(struct st_context *st, struct st_geometry_program *stgp)
+{
+   struct st_gp_variant *gpv;
+
+   for (gpv = stgp->variants; gpv; ) {
+      struct st_gp_variant *next = gpv->next;
+      delete_gp_variant(st, gpv);
+      gpv = next;
+   }
+
+   stgp->variants = NULL;
+}
+
+
+
+
+/**
+ * Translate a Mesa vertex shader into a TGSI shader.
+ * \param outputMapping  to map vertex program output registers (VERT_RESULT_x)
+ *       to TGSI output slots
+ * \param tokensOut  destination for TGSI tokens
+ * \return  pointer to cached pipe_shader object.
+ */
+static void
+st_prepare_vertex_program(struct st_context *st,
+                            struct st_vertex_program *stvp)
+{
+   GLuint attr;
+
+   stvp->num_inputs = 0;
+   stvp->num_outputs = 0;
+
+   if (stvp->Base.IsPositionInvariant)
+      _mesa_insert_mvp_code(st->ctx, &stvp->Base);
+
+   assert(stvp->Base.Base.NumInstructions > 1);
+
+   /*
+    * Determine number of inputs, the mappings between VERT_ATTRIB_x
+    * and TGSI generic input indexes, plus input attrib semantic info.
+    */
+   for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
+      if (stvp->Base.Base.InputsRead & (1 << attr)) {
+         stvp->input_to_index[attr] = stvp->num_inputs;
+         stvp->index_to_input[stvp->num_inputs] = attr;
+         stvp->num_inputs++;
+      }
+   }
+   /* bit of a hack, presetup potentially unused edgeflag input */
+   stvp->input_to_index[VERT_ATTRIB_EDGEFLAG] = stvp->num_inputs;
+   stvp->index_to_input[stvp->num_inputs] = VERT_ATTRIB_EDGEFLAG;
+
+   /* Compute mapping of vertex program outputs to slots.
+    */
+   for (attr = 0; attr < VERT_RESULT_MAX; attr++) {
+      if ((stvp->Base.Base.OutputsWritten & BITFIELD64_BIT(attr)) == 0) {
+         stvp->result_to_output[attr] = ~0;
+      }
+      else {
+         unsigned slot = stvp->num_outputs++;
+
+         stvp->result_to_output[attr] = slot;
+
+         switch (attr) {
+         case VERT_RESULT_HPOS:
+            stvp->output_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
+            stvp->output_semantic_index[slot] = 0;
+            break;
+         case VERT_RESULT_COL0:
+            stvp->output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
+            stvp->output_semantic_index[slot] = 0;
+            break;
+         case VERT_RESULT_COL1:
+            stvp->output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
+            stvp->output_semantic_index[slot] = 1;
+            break;
+         case VERT_RESULT_BFC0:
+            stvp->output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
+            stvp->output_semantic_index[slot] = 0;
+            break;
+         case VERT_RESULT_BFC1:
+            stvp->output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
+            stvp->output_semantic_index[slot] = 1;
+            break;
+         case VERT_RESULT_FOGC:
+            stvp->output_semantic_name[slot] = TGSI_SEMANTIC_FOG;
+            stvp->output_semantic_index[slot] = 0;
+            break;
+         case VERT_RESULT_PSIZ:
+            stvp->output_semantic_name[slot] = TGSI_SEMANTIC_PSIZE;
+            stvp->output_semantic_index[slot] = 0;
+            break;
+         case VERT_RESULT_EDGE:
+            assert(0);
+            break;
+
+         case VERT_RESULT_TEX0:
+         case VERT_RESULT_TEX1:
+         case VERT_RESULT_TEX2:
+         case VERT_RESULT_TEX3:
+         case VERT_RESULT_TEX4:
+         case VERT_RESULT_TEX5:
+         case VERT_RESULT_TEX6:
+         case VERT_RESULT_TEX7:
+            stvp->output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+            stvp->output_semantic_index[slot] = attr - VERT_RESULT_TEX0;
+            break;
+
+         case VERT_RESULT_VAR0:
+         default:
+            assert(attr < VERT_RESULT_MAX);
+            stvp->output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+            stvp->output_semantic_index[slot] = (FRAG_ATTRIB_VAR0 - 
+                                                FRAG_ATTRIB_TEX0 +
+                                                attr - 
+                                                VERT_RESULT_VAR0);
+            break;
+         }
+      }
+   }
+   /* similar hack to above, presetup potentially unused edgeflag output */
+   stvp->result_to_output[VERT_RESULT_EDGE] = stvp->num_outputs;
+   stvp->output_semantic_name[stvp->num_outputs] = TGSI_SEMANTIC_EDGEFLAG;
+   stvp->output_semantic_index[stvp->num_outputs] = 0;
+}
+
+
+/**
+ * Translate a vertex program to create a new variant.
+ */
+static struct st_vp_variant *
+st_translate_vertex_program(struct st_context *st,
+                            struct st_vertex_program *stvp,
+                            const struct st_vp_variant_key *key)
+{
+   struct st_vp_variant *vpv = CALLOC_STRUCT(st_vp_variant);
+   struct pipe_context *pipe = st->pipe;
+   struct ureg_program *ureg;
+   enum pipe_error error;
+   unsigned num_outputs;
+
+   st_prepare_vertex_program( st, stvp );
+
+   _mesa_remove_output_reads(&stvp->Base.Base, PROGRAM_OUTPUT);
+   _mesa_remove_output_reads(&stvp->Base.Base, PROGRAM_VARYING);
+
+   ureg = ureg_create( TGSI_PROCESSOR_VERTEX );
+   if (ureg == NULL) {
+      FREE(vpv);
+      return NULL;
+   }
+
+   vpv->key = *key;
+
+   vpv->num_inputs = stvp->num_inputs;
+   num_outputs = stvp->num_outputs;
+   if (key->passthrough_edgeflags) {
+      vpv->num_inputs++;
+      num_outputs++;
+   }
+
+   if (ST_DEBUG & DEBUG_MESA) {
+      _mesa_print_program(&stvp->Base.Base);
+      _mesa_print_program_parameters(st->ctx, &stvp->Base.Base);
+      debug_printf("\n");
+   }
+
+   error = st_translate_mesa_program(st->ctx,
+                                     TGSI_PROCESSOR_VERTEX,
+                                     ureg,
+                                     &stvp->Base.Base,
+                                     /* inputs */
+                                     vpv->num_inputs,
+                                     stvp->input_to_index,
+                                     NULL, /* input semantic name */
+                                     NULL, /* input semantic index */
+                                     NULL,
+                                     /* outputs */
+                                     num_outputs,
+                                     stvp->result_to_output,
+                                     stvp->output_semantic_name,
+                                     stvp->output_semantic_index,
+                                     key->passthrough_edgeflags );
+
+   if (error)
+      goto fail;
+
+   vpv->tgsi.tokens = ureg_get_tokens( ureg, NULL );
+   if (!vpv->tgsi.tokens)
+      goto fail;
+
+   ureg_destroy( ureg );
+
+   vpv->driver_shader = pipe->create_vs_state(pipe, &vpv->tgsi);
+
+   if (ST_DEBUG & DEBUG_TGSI) {
+      tgsi_dump( vpv->tgsi.tokens, 0 );
+      debug_printf("\n");
+   }
+
+   return vpv;
+
+fail:
+   debug_printf("%s: failed to translate Mesa program:\n", __FUNCTION__);
+   _mesa_print_program(&stvp->Base.Base);
+   debug_assert(0);
+
+   ureg_destroy( ureg );
+   return NULL;
+}
+
+
+/**
+ * Find/create a vertex program variant.
+ */
+struct st_vp_variant *
+st_get_vp_variant(struct st_context *st,
+                  struct st_vertex_program *stvp,
+                  const struct st_vp_variant_key *key)
+{
+   struct st_vp_variant *vpv;
+
+   /* Search for existing variant */
+   for (vpv = stvp->variants; vpv; vpv = vpv->next) {
+      if (memcmp(&vpv->key, key, sizeof(*key)) == 0) {
+         break;
+      }
+   }
+
+   if (!vpv) {
+      /* create now */
+      vpv = st_translate_vertex_program(st, stvp, key);
+      if (vpv) {
+         /* insert into list */
+         vpv->next = stvp->variants;
+         stvp->variants = vpv;
+      }
+   }
+
+   return vpv;
+}
+
+
+/**
+ * Translate a Mesa fragment shader into a TGSI shader using extra info in
+ * the key.
+ * \return  new fragment program variant
+ */
+static struct st_fp_variant *
+st_translate_fragment_program(struct st_context *st,
+                              struct st_fragment_program *stfp,
+                              const struct st_fp_variant_key *key)
+{
+   struct pipe_context *pipe = st->pipe;
+   struct st_fp_variant *variant = CALLOC_STRUCT(st_fp_variant);
+   GLboolean deleteFP = GL_FALSE;
+
+   if (!variant)
+      return NULL;
+
+   assert(!(key->bitmap && key->drawpixels));
+
+#if FEATURE_drawpix
+   if (key->bitmap) {
+      /* glBitmap drawing */
+      struct gl_fragment_program *fp; /* we free this temp program below */
+
+      st_make_bitmap_fragment_program(st, &stfp->Base,
+                                      &fp, &variant->bitmap_sampler);
+
+      variant->parameters = _mesa_clone_parameter_list(fp->Base.Parameters);
+      stfp = st_fragment_program(fp);
+      deleteFP = GL_TRUE;
+   }
+   else if (key->drawpixels) {
+      /* glDrawPixels drawing */
+      struct gl_fragment_program *fp; /* we free this temp program below */
+
+      if (key->drawpixels_z || key->drawpixels_stencil) {
+         fp = st_make_drawpix_z_stencil_program(st, key->drawpixels_z,
+                                                key->drawpixels_stencil);
+      }
+      else {
+         /* RGBA */
+         st_make_drawpix_fragment_program(st, &stfp->Base, &fp);
+         variant->parameters = _mesa_clone_parameter_list(fp->Base.Parameters);
+         deleteFP = GL_TRUE;
+      }
+      stfp = st_fragment_program(fp);
+   }
+#endif
+
+   if (!stfp->tgsi.tokens) {
+      /* need to translate Mesa instructions to TGSI now */
+      GLuint outputMapping[FRAG_RESULT_MAX];
+      GLuint inputMapping[FRAG_ATTRIB_MAX];
+      GLuint interpMode[PIPE_MAX_SHADER_INPUTS];  /* XXX size? */
+      GLuint attr;
+      enum pipe_error error;
+      const GLbitfield inputsRead = stfp->Base.Base.InputsRead;
+      struct ureg_program *ureg;
+      GLboolean write_all = GL_FALSE;
+
+      ubyte input_semantic_name[PIPE_MAX_SHADER_INPUTS];
+      ubyte input_semantic_index[PIPE_MAX_SHADER_INPUTS];
+      uint fs_num_inputs = 0;
+
+      ubyte fs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS];
+      ubyte fs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS];
+      uint fs_num_outputs = 0;
+
+
+      _mesa_remove_output_reads(&stfp->Base.Base, PROGRAM_OUTPUT);
+
+      /*
+       * Convert Mesa program inputs to TGSI input register semantics.
+       */
+      for (attr = 0; attr < FRAG_ATTRIB_MAX; attr++) {
+         if (inputsRead & (1 << attr)) {
+            const GLuint slot = fs_num_inputs++;
+
+            inputMapping[attr] = slot;
+
+            switch (attr) {
+            case FRAG_ATTRIB_WPOS:
+               input_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
+               input_semantic_index[slot] = 0;
+               interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
+               break;
+            case FRAG_ATTRIB_COL0:
+               input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
+               input_semantic_index[slot] = 0;
+               interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
+               break;
+            case FRAG_ATTRIB_COL1:
+               input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
+               input_semantic_index[slot] = 1;
+               interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
+               break;
+            case FRAG_ATTRIB_FOGC:
+               input_semantic_name[slot] = TGSI_SEMANTIC_FOG;
+               input_semantic_index[slot] = 0;
+               interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
+               break;
+            case FRAG_ATTRIB_FACE:
+               input_semantic_name[slot] = TGSI_SEMANTIC_FACE;
+               input_semantic_index[slot] = 0;
+               interpMode[slot] = TGSI_INTERPOLATE_CONSTANT;
+               break;
+               /* In most cases, there is nothing special about these
+                * inputs, so adopt a convention to use the generic
+                * semantic name and the mesa FRAG_ATTRIB_ number as the
+                * index. 
+                * 
+                * All that is required is that the vertex shader labels
+                * its own outputs similarly, and that the vertex shader
+                * generates at least every output required by the
+                * fragment shader plus fixed-function hardware (such as
+                * BFC).
+                * 
+                * There is no requirement that semantic indexes start at
+                * zero or be restricted to a particular range -- nobody
+                * should be building tables based on semantic index.
+                */
+            case FRAG_ATTRIB_PNTC:
+            case FRAG_ATTRIB_TEX0:
+            case FRAG_ATTRIB_TEX1:
+            case FRAG_ATTRIB_TEX2:
+            case FRAG_ATTRIB_TEX3:
+            case FRAG_ATTRIB_TEX4:
+            case FRAG_ATTRIB_TEX5:
+            case FRAG_ATTRIB_TEX6:
+            case FRAG_ATTRIB_TEX7:
+            case FRAG_ATTRIB_VAR0:
+            default:
+               /* Actually, let's try and zero-base this just for
+                * readability of the generated TGSI.
+                */
+               assert(attr >= FRAG_ATTRIB_TEX0);
+               input_semantic_index[slot] = (attr - FRAG_ATTRIB_TEX0);
+               input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+               if (attr == FRAG_ATTRIB_PNTC)
+                  interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
+               else
+                  interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
+               break;
+            }
+         }
+         else {
+            inputMapping[attr] = -1;
+         }
+      }
+
+      /*
+       * Semantics and mapping for outputs
+       */
+      {
+         uint numColors = 0;
+         GLbitfield64 outputsWritten = stfp->Base.Base.OutputsWritten;
+
+         /* if z is written, emit that first */
+         if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) {
+            fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_POSITION;
+            fs_output_semantic_index[fs_num_outputs] = 0;
+            outputMapping[FRAG_RESULT_DEPTH] = fs_num_outputs;
+            fs_num_outputs++;
+            outputsWritten &= ~(1 << FRAG_RESULT_DEPTH);
+         }
+
+         if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_STENCIL)) {
+            fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_STENCIL;
+            fs_output_semantic_index[fs_num_outputs] = 0;
+            outputMapping[FRAG_RESULT_STENCIL] = fs_num_outputs;
+            fs_num_outputs++;
+            outputsWritten &= ~(1 << FRAG_RESULT_STENCIL);
+         }
+
+         /* handle remaning outputs (color) */
+         for (attr = 0; attr < FRAG_RESULT_MAX; attr++) {
+            if (outputsWritten & BITFIELD64_BIT(attr)) {
+               switch (attr) {
+               case FRAG_RESULT_DEPTH:
+               case FRAG_RESULT_STENCIL:
+                  /* handled above */
+                  assert(0);
+                  break;
+               case FRAG_RESULT_COLOR:
+                  write_all = GL_TRUE; /* fallthrough */
+               default:
+                  assert(attr == FRAG_RESULT_COLOR ||
+                         (FRAG_RESULT_DATA0 <= attr && attr < FRAG_RESULT_MAX));
+                  fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_COLOR;
+                  fs_output_semantic_index[fs_num_outputs] = numColors;
+                  outputMapping[attr] = fs_num_outputs;
+                  numColors++;
+                  break;
+               }
+
+               fs_num_outputs++;
+            }
+         }
+      }
+
+      ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
+      if (ureg == NULL)
+         return NULL;
+
+      if (ST_DEBUG & DEBUG_MESA) {
+         _mesa_print_program(&stfp->Base.Base);
+         _mesa_print_program_parameters(st->ctx, &stfp->Base.Base);
+         debug_printf("\n");
+      }
+      if (write_all == GL_TRUE)
+         ureg_property_fs_color0_writes_all_cbufs(ureg, 1);
+
+      error = st_translate_mesa_program(st->ctx,
+                                        TGSI_PROCESSOR_FRAGMENT,
+                                        ureg,
+                                        &stfp->Base.Base,
+                                        /* inputs */
+                                        fs_num_inputs,
+                                        inputMapping,
+                                        input_semantic_name,
+                                        input_semantic_index,
+                                        interpMode,
+                                        /* outputs */
+                                        fs_num_outputs,
+                                        outputMapping,
+                                        fs_output_semantic_name,
+                                        fs_output_semantic_index, FALSE );
+
+      stfp->tgsi.tokens = ureg_get_tokens( ureg, NULL );
+      ureg_destroy( ureg );
+   }
+
+   /* fill in variant */
+   variant->driver_shader = pipe->create_fs_state(pipe, &stfp->tgsi);
+   variant->key = *key;
+
+   if (ST_DEBUG & DEBUG_TGSI) {
+      tgsi_dump( stfp->tgsi.tokens, 0/*TGSI_DUMP_VERBOSE*/ );
+      debug_printf("\n");
+   }
+
+   if (deleteFP) {
+      /* Free the temporary program made above */
+      struct gl_fragment_program *fp = &stfp->Base;
+      _mesa_reference_fragprog(st->ctx, &fp, NULL);
+   }
+
+   return variant;
+}
+
+
+/**
+ * Translate fragment program if needed.
+ */
+struct st_fp_variant *
+st_get_fp_variant(struct st_context *st,
+                  struct st_fragment_program *stfp,
+                  const struct st_fp_variant_key *key)
+{
+   struct st_fp_variant *fpv;
+
+   /* Search for existing variant */
+   for (fpv = stfp->variants; fpv; fpv = fpv->next) {
+      if (memcmp(&fpv->key, key, sizeof(*key)) == 0) {
+         break;
+      }
+   }
+
+   if (!fpv) {
+      /* create new */
+      fpv = st_translate_fragment_program(st, stfp, key);
+      if (fpv) {
+         /* insert into list */
+         fpv->next = stfp->variants;
+         stfp->variants = fpv;
+      }
+   }
+
+   return fpv;
+}
+
+
+/**
+ * Translate a geometry program to create a new variant.
+ */
+static struct st_gp_variant *
+st_translate_geometry_program(struct st_context *st,
+                              struct st_geometry_program *stgp,
+                              const struct st_gp_variant_key *key)
+{
+   GLuint inputMapping[GEOM_ATTRIB_MAX];
+   GLuint outputMapping[GEOM_RESULT_MAX];
+   struct pipe_context *pipe = st->pipe;
+   enum pipe_error error;
+   GLuint attr;
+   const GLbitfield inputsRead = stgp->Base.Base.InputsRead;
+   GLuint vslot = 0;
+   GLuint num_generic = 0;
+
+   uint gs_num_inputs = 0;
+   uint gs_builtin_inputs = 0;
+   uint gs_array_offset = 0;
+
+   ubyte gs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS];
+   ubyte gs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS];
+   uint gs_num_outputs = 0;
+
+   GLint i;
+   GLuint maxSlot = 0;
+   struct ureg_program *ureg;
+
+   struct st_gp_variant *gpv;
+
+   gpv = CALLOC_STRUCT(st_gp_variant);
+   if (!gpv)
+      return NULL;
+
+   _mesa_remove_output_reads(&stgp->Base.Base, PROGRAM_OUTPUT);
+   _mesa_remove_output_reads(&stgp->Base.Base, PROGRAM_VARYING);
+
+   ureg = ureg_create( TGSI_PROCESSOR_GEOMETRY );
+   if (ureg == NULL) {
+      FREE(gpv);
+      return NULL;
+   }
+
+   /* which vertex output goes to the first geometry input */
+   vslot = 0;
+
+   memset(inputMapping, 0, sizeof(inputMapping));
+   memset(outputMapping, 0, sizeof(outputMapping));
+
+   /*
+    * Convert Mesa program inputs to TGSI input register semantics.
+    */
+   for (attr = 0; attr < GEOM_ATTRIB_MAX; attr++) {
+      if (inputsRead & (1 << attr)) {
+         const GLuint slot = gs_num_inputs;
+
+         gs_num_inputs++;
+
+         inputMapping[attr] = slot;
+
+         stgp->input_map[slot + gs_array_offset] = vslot - gs_builtin_inputs;
+         stgp->input_to_index[attr] = vslot;
+         stgp->index_to_input[vslot] = attr;
+         ++vslot;
+
+         if (attr != GEOM_ATTRIB_PRIMITIVE_ID) {
+            gs_array_offset += 2;
+         } else
+            ++gs_builtin_inputs;
+
+#if 0
+         debug_printf("input map at %d = %d\n",
+                      slot + gs_array_offset, stgp->input_map[slot + gs_array_offset]);
+#endif
+
+         switch (attr) {
+         case GEOM_ATTRIB_PRIMITIVE_ID:
+            stgp->input_semantic_name[slot] = TGSI_SEMANTIC_PRIMID;
+            stgp->input_semantic_index[slot] = 0;
+            break;
+         case GEOM_ATTRIB_POSITION:
+            stgp->input_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
+            stgp->input_semantic_index[slot] = 0;
+            break;
+         case GEOM_ATTRIB_COLOR0:
+            stgp->input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
+            stgp->input_semantic_index[slot] = 0;
+            break;
+         case GEOM_ATTRIB_COLOR1:
+            stgp->input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
+            stgp->input_semantic_index[slot] = 1;
+            break;
+         case GEOM_ATTRIB_FOG_FRAG_COORD:
+            stgp->input_semantic_name[slot] = TGSI_SEMANTIC_FOG;
+            stgp->input_semantic_index[slot] = 0;
+            break;
+         case GEOM_ATTRIB_TEX_COORD:
+            stgp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+            stgp->input_semantic_index[slot] = num_generic++;
+            break;
+         case GEOM_ATTRIB_VAR0:
+            /* fall-through */
+         default:
+            stgp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+            stgp->input_semantic_index[slot] = num_generic++;
+         }
+      }
+   }
+
+   /* initialize output semantics to defaults */
+   for (i = 0; i < PIPE_MAX_SHADER_OUTPUTS; i++) {
+      gs_output_semantic_name[i] = TGSI_SEMANTIC_GENERIC;
+      gs_output_semantic_index[i] = 0;
+   }
+
+   num_generic = 0;
+   /*
+    * Determine number of outputs, the (default) output register
+    * mapping and the semantic information for each output.
+    */
+   for (attr = 0; attr < GEOM_RESULT_MAX; attr++) {
+      if (stgp->Base.Base.OutputsWritten & (1 << attr)) {
+         GLuint slot;
+
+         slot = gs_num_outputs;
+         gs_num_outputs++;
+         outputMapping[attr] = slot;
+
+         switch (attr) {
+         case GEOM_RESULT_POS:
+            assert(slot == 0);
+            gs_output_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
+            gs_output_semantic_index[slot] = 0;
+            break;
+         case GEOM_RESULT_COL0:
+            gs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
+            gs_output_semantic_index[slot] = 0;
+            break;
+         case GEOM_RESULT_COL1:
+            gs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
+            gs_output_semantic_index[slot] = 1;
+            break;
+         case GEOM_RESULT_SCOL0:
+            gs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
+            gs_output_semantic_index[slot] = 0;
+            break;
+         case GEOM_RESULT_SCOL1:
+            gs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
+            gs_output_semantic_index[slot] = 1;
+            break;
+         case GEOM_RESULT_FOGC:
+            gs_output_semantic_name[slot] = TGSI_SEMANTIC_FOG;
+            gs_output_semantic_index[slot] = 0;
+            break;
+         case GEOM_RESULT_PSIZ:
+            gs_output_semantic_name[slot] = TGSI_SEMANTIC_PSIZE;
+            gs_output_semantic_index[slot] = 0;
+            break;
+         case GEOM_RESULT_TEX0:
+         case GEOM_RESULT_TEX1:
+         case GEOM_RESULT_TEX2:
+         case GEOM_RESULT_TEX3:
+         case GEOM_RESULT_TEX4:
+         case GEOM_RESULT_TEX5:
+         case GEOM_RESULT_TEX6:
+         case GEOM_RESULT_TEX7:
+            /* fall-through */
+         case GEOM_RESULT_VAR0:
+            /* fall-through */
+         default:
+            assert(slot < Elements(gs_output_semantic_name));
+            /* use default semantic info */
+            gs_output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+            gs_output_semantic_index[slot] = num_generic++;
+         }
+      }
+   }
+
+   assert(gs_output_semantic_name[0] == TGSI_SEMANTIC_POSITION);
+
+   /* find max output slot referenced to compute gs_num_outputs */
+   for (attr = 0; attr < GEOM_RESULT_MAX; attr++) {
+      if (outputMapping[attr] != ~0 && outputMapping[attr] > maxSlot)
+         maxSlot = outputMapping[attr];
+   }
+   gs_num_outputs = maxSlot + 1;
+
+#if 0 /* debug */
+   {
+      GLuint i;
+      printf("outputMapping? %d\n", outputMapping ? 1 : 0);
+      if (outputMapping) {
+         printf("attr -> slot\n");
+         for (i = 0; i < 16;  i++) {
+            printf(" %2d       %3d\n", i, outputMapping[i]);
+         }
+      }
+      printf("slot    sem_name  sem_index\n");
+      for (i = 0; i < gs_num_outputs; i++) {
+         printf(" %2d         %d         %d\n",
+                i,
+                gs_output_semantic_name[i],
+                gs_output_semantic_index[i]);
+      }
+   }
+#endif
+
+   /* free old shader state, if any */
+   if (stgp->tgsi.tokens) {
+      st_free_tokens(stgp->tgsi.tokens);
+      stgp->tgsi.tokens = NULL;
+   }
+
+   ureg_property_gs_input_prim(ureg, stgp->Base.InputType);
+   ureg_property_gs_output_prim(ureg, stgp->Base.OutputType);
+   ureg_property_gs_max_vertices(ureg, stgp->Base.VerticesOut);
+
+   error = st_translate_mesa_program(st->ctx,
+                                     TGSI_PROCESSOR_GEOMETRY,
+                                     ureg,
+                                     &stgp->Base.Base,
+                                     /* inputs */
+                                     gs_num_inputs,
+                                     inputMapping,
+                                     stgp->input_semantic_name,
+                                     stgp->input_semantic_index,
+                                     NULL,
+                                     /* outputs */
+                                     gs_num_outputs,
+                                     outputMapping,
+                                     gs_output_semantic_name,
+                                     gs_output_semantic_index,
+                                     FALSE);
+
+   stgp->num_inputs = gs_num_inputs;
+   stgp->tgsi.tokens = ureg_get_tokens( ureg, NULL );
+   ureg_destroy( ureg );
+
+   /* fill in new variant */
+   gpv->driver_shader = pipe->create_gs_state(pipe, &stgp->tgsi);
+   gpv->key = *key;
+
+   if ((ST_DEBUG & DEBUG_TGSI) && (ST_DEBUG & DEBUG_MESA)) {
+      _mesa_print_program(&stgp->Base.Base);
+      debug_printf("\n");
+   }
+
+   if (ST_DEBUG & DEBUG_TGSI) {
+      tgsi_dump(stgp->tgsi.tokens, 0);
+      debug_printf("\n");
+   }
+
+   return gpv;
+}
+
+
+/**
+ * Get/create geometry program variant.
+ */
+struct st_gp_variant *
+st_get_gp_variant(struct st_context *st,
+                  struct st_geometry_program *stgp,
+                  const struct st_gp_variant_key *key)
+{
+   struct st_gp_variant *gpv;
+
+   /* Search for existing variant */
+   for (gpv = stgp->variants; gpv; gpv = gpv->next) {
+      if (memcmp(&gpv->key, key, sizeof(*key)) == 0) {
+         break;
+      }
+   }
+
+   if (!gpv) {
+      /* create new */
+      gpv = st_translate_geometry_program(st, stgp, key);
+      if (gpv) {
+         /* insert into list */
+         gpv->next = stgp->variants;
+         stgp->variants = gpv;
+      }
+   }
+
+   return gpv;
+}
+
+
+
+
+/**
+ * Debug- print current shader text
+ */
+void
+st_print_shaders(struct gl_context *ctx)
+{
+   struct gl_shader_program *shProg[3] = {
+      ctx->Shader.CurrentVertexProgram,
+      ctx->Shader.CurrentGeometryProgram,
+      ctx->Shader.CurrentFragmentProgram,
+   };
+   unsigned j;
+
+   for (j = 0; j < 3; j++) {
+      unsigned i;
+
+      if (shProg[j] == NULL)
+	 continue;
+
+      for (i = 0; i < shProg[j]->NumShaders; i++) {
+	 struct gl_shader *sh;
+
+	 switch (shProg[j]->Shaders[i]->Type) {
+	 case GL_VERTEX_SHADER:
+	    sh = (i != 0) ? NULL : shProg[j]->Shaders[i];
+	    break;
+	 case GL_GEOMETRY_SHADER_ARB:
+	    sh = (i != 1) ? NULL : shProg[j]->Shaders[i];
+	    break;
+	 case GL_FRAGMENT_SHADER:
+	    sh = (i != 2) ? NULL : shProg[j]->Shaders[i];
+	    break;
+	 default:
+	    assert(0);
+	    sh = NULL;
+	    break;
+	 }
+
+	 if (sh != NULL) {
+	    printf("GLSL shader %u of %u:\n", i, shProg[j]->NumShaders);
+	    printf("%s\n", sh->Source);
+	 }
+      }
+   }
+}
+
+
+/**
+ * Vert/Geom/Frag programs have per-context variants.  Free all the
+ * variants attached to the given program which match the given context.
+ */
+static void
+destroy_program_variants(struct st_context *st, struct gl_program *program)
+{
+   if (!program)
+      return;
+
+   switch (program->Target) {
+   case GL_VERTEX_PROGRAM_ARB:
+      {
+         struct st_vertex_program *stvp = (struct st_vertex_program *) program;
+         struct st_vp_variant *vpv, **prevPtr = &stvp->variants;
+
+         for (vpv = stvp->variants; vpv; ) {
+            struct st_vp_variant *next = vpv->next;
+            if (vpv->key.st == st) {
+               /* unlink from list */
+               *prevPtr = next;
+               /* destroy this variant */
+               delete_vp_variant(st, vpv);
+            }
+            else {
+               prevPtr = &vpv->next;
+            }
+            vpv = next;
+         }
+      }
+      break;
+   case GL_FRAGMENT_PROGRAM_ARB:
+      {
+         struct st_fragment_program *stfp =
+            (struct st_fragment_program *) program;
+         struct st_fp_variant *fpv, **prevPtr = &stfp->variants;
+
+         for (fpv = stfp->variants; fpv; ) {
+            struct st_fp_variant *next = fpv->next;
+            if (fpv->key.st == st) {
+               /* unlink from list */
+               *prevPtr = next;
+               /* destroy this variant */
+               delete_fp_variant(st, fpv);
+            }
+            else {
+               prevPtr = &fpv->next;
+            }
+            fpv = next;
+         }
+      }
+      break;
+   case MESA_GEOMETRY_PROGRAM:
+      {
+         struct st_geometry_program *stgp =
+            (struct st_geometry_program *) program;
+         struct st_gp_variant *gpv, **prevPtr = &stgp->variants;
+
+         for (gpv = stgp->variants; gpv; ) {
+            struct st_gp_variant *next = gpv->next;
+            if (gpv->key.st == st) {
+               /* unlink from list */
+               *prevPtr = next;
+               /* destroy this variant */
+               delete_gp_variant(st, gpv);
+            }
+            else {
+               prevPtr = &gpv->next;
+            }
+            gpv = next;
+         }
+      }
+      break;
+   default:
+      _mesa_problem(NULL, "Unexpected program target in "
+                    "destroy_program_variants_cb()");
+   }
+}
+
+
+/**
+ * Callback for _mesa_HashWalk.  Free all the shader's program variants
+ * which match the given context.
+ */
+static void
+destroy_shader_program_variants_cb(GLuint key, void *data, void *userData)
+{
+   struct st_context *st = (struct st_context *) userData;
+   struct gl_shader *shader = (struct gl_shader *) data;
+
+   switch (shader->Type) {
+   case GL_SHADER_PROGRAM_MESA:
+      {
+         struct gl_shader_program *shProg = (struct gl_shader_program *) data;
+         GLuint i;
+
+         for (i = 0; i < shProg->NumShaders; i++) {
+            destroy_program_variants(st, shProg->Shaders[i]->Program);
+         }
+
+         destroy_program_variants(st, (struct gl_program *)
+                                  shProg->VertexProgram);
+         destroy_program_variants(st, (struct gl_program *)
+                                  shProg->FragmentProgram);
+         destroy_program_variants(st, (struct gl_program *)
+                                  shProg->GeometryProgram);
+      }
+      break;
+   case GL_VERTEX_SHADER:
+   case GL_FRAGMENT_SHADER:
+   case GL_GEOMETRY_SHADER:
+      {
+         destroy_program_variants(st, shader->Program);
+      }
+      break;
+   default:
+      assert(0);
+   }
+}
+
+
+/**
+ * Callback for _mesa_HashWalk.  Free all the program variants which match
+ * the given context.
+ */
+static void
+destroy_program_variants_cb(GLuint key, void *data, void *userData)
+{
+   struct st_context *st = (struct st_context *) userData;
+   struct gl_program *program = (struct gl_program *) data;
+   destroy_program_variants(st, program);
+}
+
+
+/**
+ * Walk over all shaders and programs to delete any variants which
+ * belong to the given context.
+ * This is called during context tear-down.
+ */
+void
+st_destroy_program_variants(struct st_context *st)
+{
+   /* ARB vert/frag program */
+   _mesa_HashWalk(st->ctx->Shared->Programs,
+                  destroy_program_variants_cb, st);
+
+   /* GLSL vert/frag/geom shaders */
+   _mesa_HashWalk(st->ctx->Shared->ShaderObjects,
+                  destroy_shader_program_variants_cb, st);
+}
-- 
cgit v1.2.3