Merge commit 'origin/gallium-0.2' into gallium-master-merge
[mesa.git] / src / mesa / drivers / dri / r200 / r200_context.c
index de373ecc864caade5819cd0531c82ae1cbbe4c9f..c06751516eb47f72aff9be99629284d92ecaab53 100644 (file)
@@ -1,4 +1,3 @@
-/* $XFree86: xc/lib/GL/mesa/src/drv/r200/r200_context.c,v 1.3 2003/05/06 23:52:08 daenzer Exp $ */
 /*
 Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
 
@@ -33,18 +32,19 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  *   Keith Whitwell <keith@tungstengraphics.com>
  */
 
-#include "glheader.h"
-#include "api_arrayelt.h"
-#include "context.h"
-#include "simple_list.h"
-#include "imports.h"
-#include "matrix.h"
-#include "extensions.h"
-#include "state.h"
+#include "main/glheader.h"
+#include "main/api_arrayelt.h"
+#include "main/context.h"
+#include "main/simple_list.h"
+#include "main/imports.h"
+#include "main/matrix.h"
+#include "main/extensions.h"
+#include "main/framebuffer.h"
+#include "main/state.h"
 
 #include "swrast/swrast.h"
 #include "swrast_setup/swrast_setup.h"
-#include "array_cache/acache.h"
+#include "vbo/vbo.h"
 
 #include "tnl/tnl.h"
 #include "tnl/t_pipeline.h"
@@ -59,10 +59,21 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "r200_tex.h"
 #include "r200_swtcl.h"
 #include "r200_tcl.h"
-#include "r200_vtxfmt.h"
 #include "r200_maos.h"
+#include "r200_vertprog.h"
 
-#define DRIVER_DATE    "20041207"
+#define need_GL_ARB_vertex_program
+#define need_GL_ATI_fragment_shader
+#define need_GL_EXT_blend_minmax
+#define need_GL_EXT_fog_coord
+#define need_GL_EXT_secondary_color
+#define need_GL_EXT_blend_equation_separate
+#define need_GL_EXT_blend_func_separate
+#define need_GL_NV_vertex_program
+#define need_GL_ARB_point_parameters
+#include "extension_helper.h"
+
+#define DRIVER_DATE    "20060602"
 
 #include "vblank.h"
 #include "utils.h"
@@ -71,21 +82,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 int R200_DEBUG = (0);
 #endif
 
-
-/* Return the width and height of the given buffer.
- */
-static void r200GetBufferSize( GLframebuffer *buffer,
-                              GLuint *width, GLuint *height )
-{
-   GET_CURRENT_CONTEXT(ctx);
-   r200ContextPtr rmesa = R200_CONTEXT(ctx);
-
-   LOCK_HARDWARE( rmesa );
-   *width  = rmesa->dri.drawable->w;
-   *height = rmesa->dri.drawable->h;
-   UNLOCK_HARDWARE( rmesa );
-}
-
 /* Return various strings for glGetString().
  */
 static const GLubyte *r200GetString( GLcontext *ctx, GLenum name )
@@ -93,7 +89,7 @@ static const GLubyte *r200GetString( GLcontext *ctx, GLenum name )
    r200ContextPtr rmesa = R200_CONTEXT(ctx);
    static char buffer[128];
    unsigned   offset;
-   GLuint agp_mode = rmesa->r200Screen->IsPCI ? 0 :
+   GLuint agp_mode = (rmesa->r200Screen->card_type == RADEON_CARD_PCI)? 0 :
       rmesa->r200Screen->AGPMode;
 
    switch ( name ) {
@@ -118,35 +114,57 @@ static const GLubyte *r200GetString( GLcontext *ctx, GLenum name )
 
 /* Extension strings exported by the R200 driver.
  */
-static const char * const card_extensions[] =
+const struct dri_extension card_extensions[] =
 {
-    "GL_ARB_multisample",
-    "GL_ARB_multitexture",
-    "GL_ARB_texture_border_clamp",
-    "GL_ARB_texture_compression",
-    "GL_ARB_texture_env_add",
-    "GL_ARB_texture_env_combine",
-    "GL_ARB_texture_env_dot3",
-    "GL_ARB_texture_mirrored_repeat",
-    "GL_ARB_vertex_buffer_object",
-    "GL_EXT_blend_minmax",
-    "GL_EXT_blend_subtract",
-    "GL_EXT_fog_coord",
-    "GL_EXT_secondary_color",
-    "GL_EXT_stencil_wrap",
-    "GL_EXT_texture_edge_clamp",
-    "GL_EXT_texture_env_combine",
-    "GL_EXT_texture_env_dot3",
-    "GL_EXT_texture_filter_anisotropic",
-    "GL_EXT_texture_lod_bias",
-    "GL_EXT_texture_mirror_clamp",
-    "GL_EXT_texture_rectangle",
-    "GL_ATI_texture_env_combine3",
-    "GL_ATI_texture_mirror_once",
-    "GL_MESA_pack_invert",
-    "GL_NV_blend_square",
-    "GL_SGIS_generate_mipmap",
-    NULL
+    { "GL_ARB_multitexture",               NULL },
+    { "GL_ARB_texture_border_clamp",       NULL },
+    { "GL_ARB_texture_env_add",            NULL },
+    { "GL_ARB_texture_env_combine",        NULL },
+    { "GL_ARB_texture_env_dot3",           NULL },
+    { "GL_ARB_texture_env_crossbar",       NULL },
+    { "GL_ARB_texture_mirrored_repeat",    NULL },
+    { "GL_EXT_blend_minmax",               GL_EXT_blend_minmax_functions },
+    { "GL_EXT_blend_subtract",             NULL },
+    { "GL_EXT_fog_coord",                  GL_EXT_fog_coord_functions },
+    { "GL_EXT_secondary_color",            GL_EXT_secondary_color_functions },
+    { "GL_EXT_stencil_wrap",               NULL },
+    { "GL_EXT_texture_edge_clamp",         NULL },
+    { "GL_EXT_texture_env_combine",        NULL },
+    { "GL_EXT_texture_env_dot3",           NULL },
+    { "GL_EXT_texture_filter_anisotropic", NULL },
+    { "GL_EXT_texture_lod_bias",           NULL },
+    { "GL_EXT_texture_mirror_clamp",       NULL },
+    { "GL_EXT_texture_rectangle",          NULL },
+    { "GL_ATI_texture_env_combine3",       NULL },
+    { "GL_ATI_texture_mirror_once",        NULL },
+    { "GL_MESA_pack_invert",               NULL },
+    { "GL_NV_blend_square",                NULL },
+    { "GL_SGIS_generate_mipmap",           NULL },
+    { NULL,                                NULL }
+};
+
+const struct dri_extension blend_extensions[] = {
+    { "GL_EXT_blend_equation_separate",    GL_EXT_blend_equation_separate_functions },
+    { "GL_EXT_blend_func_separate",        GL_EXT_blend_func_separate_functions },
+    { NULL,                                NULL }
+};
+
+const struct dri_extension ARB_vp_extension[] = {
+    { "GL_ARB_vertex_program",             GL_ARB_vertex_program_functions }
+};
+
+const struct dri_extension NV_vp_extension[] = {
+    { "GL_NV_vertex_program",              GL_NV_vertex_program_functions }
+};
+
+const struct dri_extension ATI_fs_extension[] = {
+    { "GL_ATI_fragment_shader",            GL_ATI_fragment_shader_functions }
+};
+
+const struct dri_extension point_extensions[] = {
+    { "GL_ARB_point_sprite",               NULL },
+    { "GL_ARB_point_parameters",           GL_ARB_point_parameters_functions },
+    { NULL,                                NULL }
 };
 
 extern const struct tnl_pipeline_stage _r200_render_stage;
@@ -166,8 +184,8 @@ static const struct tnl_pipeline_stage *r200_pipeline[] = {
    &_tnl_fog_coordinate_stage,
    &_tnl_texgen_stage,
    &_tnl_texture_transform_stage,
+   &_tnl_point_attenuation_stage,
    &_tnl_vertex_program_stage,
-
    /* Try again to go to tcl? 
     *     - no good for asymmetric-twoside (do with multipass)
     *     - no good for asymmetric-unfilled (do with multipass)
@@ -191,13 +209,8 @@ static const struct tnl_pipeline_stage *r200_pipeline[] = {
  */
 static void r200InitDriverFuncs( struct dd_function_table *functions )
 {
-    functions->GetBufferSize           = r200GetBufferSize;
-    functions->ResizeBuffers           = _swrast_alloc_buffers;
+    functions->GetBufferSize           = NULL; /* OBSOLETE */
     functions->GetString               = r200GetString;
-
-    functions->Error                   = NULL;
-    functions->DrawPixels              = NULL;
-    functions->Bitmap                  = NULL;
 }
 
 static const struct dri_debug_control debug_control[] =
@@ -222,14 +235,6 @@ static const struct dri_debug_control debug_control[] =
 };
 
 
-static int
-get_ust_nop( int64_t * ust )
-{
-   *ust = 1;
-   return 0;
-}
-
-
 /* Create the device specific rendering context.
  */
 GLboolean r200CreateContext( const __GLcontextModes *glVisual,
@@ -237,7 +242,7 @@ GLboolean r200CreateContext( const __GLcontextModes *glVisual,
                             void *sharedContextPrivate)
 {
    __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
-   r200ScreenPtr screen = (r200ScreenPtr)(sPriv->private);
+   radeonScreenPtr screen = (radeonScreenPtr)(sPriv->private);
    struct dd_function_table functions;
    r200ContextPtr rmesa;
    GLcontext *ctx, *shareCtx;
@@ -266,14 +271,14 @@ GLboolean r200CreateContext( const __GLcontextModes *glVisual,
                                                  "def_max_anisotropy");
 
    if ( driQueryOptionb( &rmesa->optionCache, "hyperz" ) ) {
-      if ( sPriv->drmMinor < 13 )
+      if ( sPriv->drm_version.minor < 13 )
         fprintf( stderr, "DRM version 1.%d too old to support HyperZ, "
-                         "disabling.\n",sPriv->drmMinor );
+                         "disabling.\n", sPriv->drm_version.minor );
       else
         rmesa->using_hyperz = GL_TRUE;
    }
  
-   if ( sPriv->drmMinor >= 15 )
+   if ( sPriv->drm_version.minor >= 15 )
       rmesa->texmicrotile = GL_TRUE;
 
    /* Init default driver functions then plug in our R200-specific functions
@@ -284,6 +289,7 @@ GLboolean r200CreateContext( const __GLcontextModes *glVisual,
    r200InitIoctlFuncs(&functions);
    r200InitStateFuncs(&functions);
    r200InitTextureFuncs(&functions);
+   r200InitShaderFuncs(&functions); 
 
    /* Allocate and initialize the Mesa context */
    if (sharedContextPrivate)
@@ -305,7 +311,7 @@ GLboolean r200CreateContext( const __GLcontextModes *glVisual,
    rmesa->dri.hwContext = driContextPriv->hHWContext;
    rmesa->dri.hwLock = &sPriv->pSAREA->lock;
    rmesa->dri.fd = sPriv->fd;
-   rmesa->dri.drmMinor = sPriv->drmMinor;
+   rmesa->dri.drmMinor = sPriv->drm_version.minor;
 
    rmesa->r200Screen = screen;
    rmesa->sarea = (drm_radeon_sarea_t *)((GLubyte *)sPriv->pSAREA +
@@ -318,7 +324,7 @@ GLboolean r200CreateContext( const __GLcontextModes *glVisual,
    make_empty_list( & rmesa->swapped );
 
    rmesa->nr_heaps = 1 /* screen->numTexHeaps */ ;
-   assert(rmesa->nr_heaps < R200_NR_TEX_HEAPS);
+   assert(rmesa->nr_heaps < RADEON_NR_TEX_HEAPS);
    for ( i = 0 ; i < rmesa->nr_heaps ; i++ ) {
       rmesa->texture_heaps[i] = driCreateTextureHeap( i, rmesa,
            screen->texSize[i],
@@ -340,8 +346,9 @@ GLboolean r200CreateContext( const __GLcontextModes *glVisual,
    rmesa->hw.all_dirty = 1;
 
    /* Set the maximum texture size small enough that we can guarentee that
-    * all texture units can bind a maximal texture and have them both in
-    * texturable memory at once.
+    * all texture units can bind a maximal texture and have all of them in
+    * texturable memory at once. Depending on the allow_large_textures driconf
+    * setting allow larger textures.
     */
 
    ctx = rmesa->glCtx;
@@ -350,6 +357,8 @@ GLboolean r200CreateContext( const __GLcontextModes *glVisual,
    ctx->Const.MaxTextureImageUnits = ctx->Const.MaxTextureUnits;
    ctx->Const.MaxTextureCoordUnits = ctx->Const.MaxTextureUnits;
 
+   i = driQueryOptioni( &rmesa->optionCache, "allow_large_textures");
+
    driCalculateMaxTextureLevels( rmesa->texture_heaps,
                                 rmesa->nr_heaps,
                                 & ctx->Const,
@@ -363,23 +372,24 @@ GLboolean r200CreateContext( const __GLcontextModes *glVisual,
                                 11, /* max cube texture size is 2048x2048 */
                                 11, /* max texture rectangle size is 2048x2048 */
                                 12,
-                                GL_FALSE );
-
-   /* adjust max texture size a bit. Hack, but I really want to use larger textures
-      which will work just fine in 99.999999% of all cases, especially with texture compression... */
-   if (driQueryOptionb( &rmesa->optionCache, "texture_level_hack" ))
-   {
-     if (ctx->Const.MaxTextureLevels < 12) ctx->Const.MaxTextureLevels += 1;
-   }
+                                GL_FALSE,
+                                i );
 
    ctx->Const.MaxTextureMaxAnisotropy = 16.0;
 
-   /* No wide points.
+   /* No wide AA points.
     */
    ctx->Const.MinPointSize = 1.0;
    ctx->Const.MinPointSizeAA = 1.0;
-   ctx->Const.MaxPointSize = 1.0;
    ctx->Const.MaxPointSizeAA = 1.0;
+   ctx->Const.PointSizeGranularity = 0.0625;
+   if (rmesa->r200Screen->drmSupportsPointSprites)
+      ctx->Const.MaxPointSize = 2047.0;
+   else
+      ctx->Const.MaxPointSize = 1.0;
+
+   /* mesa initialization problem - _mesa_init_point was already called */
+   ctx->Point.MaxSize = ctx->Const.MaxPointSize;
 
    ctx->Const.MinLineWidth = 1.0;
    ctx->Const.MinLineWidthAA = 1.0;
@@ -387,10 +397,18 @@ GLboolean r200CreateContext( const __GLcontextModes *glVisual,
    ctx->Const.MaxLineWidthAA = 10.0;
    ctx->Const.LineWidthGranularity = 0.0625;
 
+   ctx->Const.VertexProgram.MaxNativeInstructions = R200_VSF_MAX_INST;
+   ctx->Const.VertexProgram.MaxNativeAttribs = 12;
+   ctx->Const.VertexProgram.MaxNativeTemps = R200_VSF_MAX_TEMPS;
+   ctx->Const.VertexProgram.MaxNativeParameters = R200_VSF_MAX_PARAM;
+   ctx->Const.VertexProgram.MaxNativeAddressRegs = 1;
+
+   ctx->Const.MaxDrawBuffers = 1;
+
    /* Initialize the software rasterizer and helper modules.
     */
    _swrast_CreateContext( ctx );
-   _ac_CreateContext( ctx );
+   _vbo_CreateContext( ctx );
    _tnl_CreateContext( ctx );
    _swsetup_CreateContext( ctx );
    _ae_create_context( ctx );
@@ -399,11 +417,10 @@ GLboolean r200CreateContext( const __GLcontextModes *glVisual,
     */
    _tnl_destroy_pipeline( ctx );
    _tnl_install_pipeline( ctx, r200_pipeline );
-   ctx->Driver.FlushVertices = r200FlushVertices;
 
    /* Try and keep materials and vertices separate:
     */
-   _tnl_isolate_materials( ctx, GL_TRUE );
+/*    _tnl_isolate_materials( ctx, GL_TRUE ); */
 
 
    /* Configure swrast and TNL to match hardware characteristics:
@@ -422,7 +439,7 @@ GLboolean r200CreateContext( const __GLcontextModes *glVisual,
    _math_matrix_set_identity( &rmesa->tmpmat );
 
    driInitExtensions( ctx, card_extensions, GL_TRUE );
-   if (!(rmesa->r200Screen->chipset & R200_CHIPSET_YCBCR_BROKEN)) {
+   if (!(rmesa->r200Screen->chip_flags & R200_CHIPSET_YCBCR_BROKEN)) {
      /* yuv textures don't work with some chips - R200 / rv280 okay so far
        others get the bit ordering right but don't actually do YUV-RGB conversion */
       _mesa_enable_extension( ctx, "GL_MESA_ycbcr_texture" );
@@ -435,17 +452,20 @@ GLboolean r200CreateContext( const __GLcontextModes *glVisual,
       _mesa_enable_extension( ctx, "GL_EXT_texture_compression_s3tc" );
    }
 
-   if (rmesa->r200Screen->drmSupportsCubeMaps)
+   if (rmesa->r200Screen->drmSupportsCubeMapsR200)
       _mesa_enable_extension( ctx, "GL_ARB_texture_cube_map" );
    if (rmesa->r200Screen->drmSupportsBlendColor) {
-      _mesa_enable_extension( ctx, "GL_EXT_blend_equation_separate" );
-      _mesa_enable_extension( ctx, "GL_EXT_blend_func_separate" );
+       driInitExtensions( ctx, blend_extensions, GL_FALSE );
    }
-   if(driQueryOptionb(&rmesa->optionCache, "arb_vertex_program"))
-      _mesa_enable_extension( ctx, "GL_ARB_vertex_program");
+   if(rmesa->r200Screen->drmSupportsVertexProgram)
+      driInitSingleExtension( ctx, ARB_vp_extension );
    if(driQueryOptionb(&rmesa->optionCache, "nv_vertex_program"))
-      _mesa_enable_extension( ctx, "GL_NV_vertex_program");
+      driInitSingleExtension( ctx, NV_vp_extension );
 
+   if ((ctx->Const.MaxTextureUnits == 6) && rmesa->r200Screen->drmSupportsFragShader)
+      driInitSingleExtension( ctx, ATI_fs_extension );
+   if (rmesa->r200Screen->drmSupportsPointSprites)
+      driInitExtensions( ctx, point_extensions, GL_FALSE );
 #if 0
    r200InitDriverFuncs( ctx );
    r200InitIoctlFuncs( ctx );
@@ -463,31 +483,22 @@ GLboolean r200CreateContext( const __GLcontextModes *glVisual,
    fthrottle_mode = driQueryOptioni(&rmesa->optionCache, "fthrottle_mode");
    rmesa->iw.irq_seq = -1;
    rmesa->irqsEmitted = 0;
-   rmesa->do_irqs = (rmesa->dri.drmMinor >= 6 && 
-                    fthrottle_mode == DRI_CONF_FTHROTTLE_IRQS &&
+   rmesa->do_irqs = (fthrottle_mode == DRI_CONF_FTHROTTLE_IRQS &&
                     rmesa->r200Screen->irq);
 
    rmesa->do_usleeps = (fthrottle_mode == DRI_CONF_FTHROTTLE_USLEEPS);
 
    if (!rmesa->do_irqs)
       fprintf(stderr,
-             "IRQ's not enabled, falling back to %s: %d %d %d\n",
+             "IRQ's not enabled, falling back to %s: %d %d\n",
              rmesa->do_usleeps ? "usleeps" : "busy waits",
-             rmesa->dri.drmMinor,
              fthrottle_mode,
              rmesa->r200Screen->irq);
 
-   rmesa->vblank_flags = (rmesa->r200Screen->irq != 0)
-       ? driGetDefaultVBlankFlags(&rmesa->optionCache) : VBLANK_FLAG_NO_IRQ;
-
    rmesa->prefer_gart_client_texturing = 
       (getenv("R200_GART_CLIENT_TEXTURES") != 0);
 
-   rmesa->get_ust = (PFNGLXGETUSTPROC) glXGetProcAddress( (const GLubyte *) "__glXGetUST" );
-   if ( rmesa->get_ust == NULL ) {
-      rmesa->get_ust = get_ust_nop;
-   }
-   (*rmesa->get_ust)( & rmesa->swap_ust );
+   (*sPriv->systemTime->getUST)( & rmesa->swap_ust );
 
 
 #if DO_DEBUG
@@ -503,19 +514,14 @@ GLboolean r200CreateContext( const __GLcontextModes *glVisual,
       FALLBACK(rmesa, R200_FALLBACK_DISABLE, 1);
    }
    else if (tcl_mode == DRI_CONF_TCL_SW || getenv("R200_NO_TCL") ||
-           !(rmesa->r200Screen->chipset & R200_CHIPSET_TCL)) {
-      if (rmesa->r200Screen->chipset & R200_CHIPSET_TCL) {
-        rmesa->r200Screen->chipset &= ~R200_CHIPSET_TCL;
+           !(rmesa->r200Screen->chip_flags & RADEON_CHIPSET_TCL)) {
+      if (rmesa->r200Screen->chip_flags & RADEON_CHIPSET_TCL) {
+        rmesa->r200Screen->chip_flags &= ~RADEON_CHIPSET_TCL;
         fprintf(stderr, "Disabling HW TCL support\n");
       }
       TCL_FALLBACK(rmesa->glCtx, R200_TCL_FALLBACK_TCL_DISABLE, 1);
    }
-   if (rmesa->r200Screen->chipset & R200_CHIPSET_TCL) {
-      if (tcl_mode >= DRI_CONF_TCL_VTXFMT && !getenv("R200_NO_VTXFMT")) {
-        r200VtxfmtInit( ctx, tcl_mode >= DRI_CONF_TCL_CODEGEN );
-      }
-      _tnl_need_dlist_norm_lengths( ctx, GL_FALSE );
-   }
+
    return GL_TRUE;
 }
 
@@ -533,7 +539,7 @@ void r200DestroyContext( __DRIcontextPrivate *driContextPriv )
    /* check if we're deleting the currently bound context */
    if (rmesa == current) {
       R200_FIREVERTICES( rmesa );
-      _mesa_make_current2(NULL, NULL, NULL);
+      _mesa_make_current(NULL, NULL, NULL);
    }
 
    /* Free r200 context resources */
@@ -545,7 +551,7 @@ void r200DestroyContext( __DRIcontextPrivate *driContextPriv )
       release_texture_heaps = (rmesa->glCtx->Shared->RefCount == 1);
       _swsetup_DestroyContext( rmesa->glCtx );
       _tnl_DestroyContext( rmesa->glCtx );
-      _ac_DestroyContext( rmesa->glCtx );
+      _vbo_DestroyContext( rmesa->glCtx );
       _swrast_DestroyContext( rmesa->glCtx );
 
       r200DestroySwtcl( rmesa->glCtx );
@@ -556,16 +562,6 @@ void r200DestroyContext( __DRIcontextPrivate *driContextPriv )
         r200FlushCmdBuf( rmesa, __FUNCTION__ );
       }
 
-      if (!(rmesa->TclFallback & R200_TCL_FALLBACK_TCL_DISABLE)) {
-        int tcl_mode = driQueryOptioni(&rmesa->optionCache, "tcl_mode");
-        if (tcl_mode >= DRI_CONF_TCL_VTXFMT)
-           r200VtxfmtDestroy( rmesa->glCtx );
-      }
-
-      /* free the Mesa context */
-      rmesa->glCtx->DriverCtx = NULL;
-      _mesa_destroy_context( rmesa->glCtx );
-
       if (rmesa->state.scissor.pClipRects) {
         FREE(rmesa->state.scissor.pClipRects);
         rmesa->state.scissor.pClipRects = NULL;
@@ -585,6 +581,10 @@ void r200DestroyContext( __DRIcontextPrivate *driContextPriv )
         assert( is_empty_list( & rmesa->swapped ) );
       }
 
+      /* free the Mesa context */
+      rmesa->glCtx->DriverCtx = NULL;
+      _mesa_destroy_context( rmesa->glCtx );
+
       /* free the option cache */
       driDestroyOptionCache (&rmesa->optionCache);
 
@@ -609,7 +609,7 @@ r200SwapBuffers( __DRIdrawablePrivate *dPriv )
             r200PageFlip( dPriv );
          }
          else {
-            r200CopyBuffer( dPriv );
+            r200CopyBuffer( dPriv, NULL );
          }
       }
    }
@@ -619,6 +619,30 @@ r200SwapBuffers( __DRIdrawablePrivate *dPriv )
    }
 }
 
+void
+r200CopySubBuffer( __DRIdrawablePrivate *dPriv,
+                  int x, int y, int w, int h )
+{
+   if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
+      r200ContextPtr rmesa;
+      GLcontext *ctx;
+      rmesa = (r200ContextPtr) dPriv->driContextPriv->driverPrivate;
+      ctx = rmesa->glCtx;
+      if (ctx->Visual.doubleBufferMode) {
+        drm_clip_rect_t rect;
+        rect.x1 = x + dPriv->x;
+        rect.y1 = (dPriv->h - y - h) + dPriv->y;
+        rect.x2 = rect.x1 + w;
+        rect.y2 = rect.y1 + h;
+         _mesa_notifySwapBuffers( ctx );  /* flush pending rendering comands */
+        r200CopyBuffer( dPriv, &rect );
+      }
+   }
+   else {
+      /* XXX this shouldn't be an error but we can't handle it for now */
+      _mesa_problem(NULL, "%s: drawable has no context!", __FUNCTION__);
+   }
+}
 
 /* Force the context `c' to be the current context and associate with it
  * buffer `b'.
@@ -635,19 +659,27 @@ r200MakeCurrent( __DRIcontextPrivate *driContextPriv,
       if (R200_DEBUG & DEBUG_DRI)
         fprintf(stderr, "%s ctx %p\n", __FUNCTION__, (void *)newCtx->glCtx);
 
-      if ( newCtx->dri.drawable != driDrawPriv ) {
-        driDrawableInitVBlank( driDrawPriv, newCtx->vblank_flags );
+      newCtx->dri.readable = driReadPriv;
+
+      if ( newCtx->dri.drawable != driDrawPriv ||
+           newCtx->lastStamp != driDrawPriv->lastStamp ) {
+        if (driDrawPriv->swap_interval == (unsigned)-1) {
+           driDrawPriv->vblFlags = (newCtx->r200Screen->irq != 0)
+              ? driGetDefaultVBlankFlags(&newCtx->optionCache)
+              : VBLANK_FLAG_NO_IRQ;
+
+           driDrawableInitVBlank( driDrawPriv );
+        }
+
         newCtx->dri.drawable = driDrawPriv;
-        r200UpdateWindow( newCtx->glCtx );
+
+        r200SetCliprects(newCtx);
         r200UpdateViewportOffset( newCtx->glCtx );
       }
 
-      _mesa_make_current2( newCtx->glCtx,
-                          (GLframebuffer *) driDrawPriv->driverPrivate,
-                          (GLframebuffer *) driReadPriv->driverPrivate );
-
-      if (newCtx->vb.enabled)
-        r200VtxfmtMakeCurrent( newCtx->glCtx );
+      _mesa_make_current( newCtx->glCtx,
+                         (GLframebuffer *) driDrawPriv->driverPrivate,
+                         (GLframebuffer *) driReadPriv->driverPrivate );
 
       _mesa_update_state( newCtx->glCtx );
       r200ValidateState( newCtx->glCtx );
@@ -655,7 +687,7 @@ r200MakeCurrent( __DRIcontextPrivate *driContextPriv,
    } else {
       if (R200_DEBUG & DEBUG_DRI)
         fprintf(stderr, "%s ctx is null\n", __FUNCTION__);
-      _mesa_make_current( NULL, NULL );
+      _mesa_make_current( NULL, NULL, NULL );
    }
 
    if (R200_DEBUG & DEBUG_DRI)
@@ -673,6 +705,5 @@ r200UnbindContext( __DRIcontextPrivate *driContextPriv )
    if (R200_DEBUG & DEBUG_DRI)
       fprintf(stderr, "%s ctx %p\n", __FUNCTION__, (void *)rmesa->glCtx);
 
-   r200VtxfmtUnbindContext( rmesa->glCtx );
    return GL_TRUE;
 }