Merge remote branch 'origin/master' into radeon-rewrite
[mesa.git] / src / mesa / drivers / dri / r300 / r300_context.c
index 3604b1181e8b2164c64f0f30fd5c586cd92eeefe..6d68309d3f038ba5f89cded1660dfa377db09bbc 100644 (file)
@@ -27,87 +27,133 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 **************************************************************************/
 
-/*
- * Authors:
- *   Keith Whitwell <keith@tungstengraphics.com>
- *   Nicolai Haehnle <prefect_@gmx.net>
+/**
+ * \file
+ *
+ * \author Keith Whitwell <keith@tungstengraphics.com>
+ *
+ * \author Nicolai Haehnle <prefect_@gmx.net>
  */
 
-#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/state.h"
+#include "main/bufferobj.h"
+#include "main/texobj.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"
+#include "tnl/t_vp_build.h"
 
 #include "drivers/common/driverfuncs.h"
 
-#include "radeon_ioctl.h"
-#include "radeon_span.h"
 #include "r300_context.h"
+#include "radeon_context.h"
+#include "radeon_span.h"
 #include "r300_cmdbuf.h"
 #include "r300_state.h"
 #include "r300_ioctl.h"
+#include "r300_tex.h"
+#include "r300_emit.h"
+#include "r300_swtcl.h"
+#include "radeon_bocs_wrapper.h"
+
 
 #include "vblank.h"
 #include "utils.h"
 #include "xmlpool.h"           /* for symbolic values of enum-type options */
 
+/* hw_tcl_on derives from future_hw_tcl_on when its safe to change it. */
+int future_hw_tcl_on = 1;
+int hw_tcl_on = 1;
+
+#define need_GL_VERSION_2_0
+#define need_GL_ARB_point_parameters
+#define need_GL_ARB_vertex_program
+#define need_GL_EXT_blend_equation_separate
+#define need_GL_EXT_blend_func_separate
+#define need_GL_EXT_blend_minmax
+//#define need_GL_EXT_fog_coord
+#define need_GL_EXT_gpu_program_parameters
+#define need_GL_EXT_secondary_color
+#define need_GL_EXT_stencil_two_side
+#define need_GL_ATI_separate_stencil
+#define need_GL_NV_vertex_program
+#include "extension_helper.h"
+
+const struct dri_extension card_extensions[] = {
+  /* *INDENT-OFF* */
+  {"GL_ARB_depth_texture",             NULL},
+  {"GL_ARB_fragment_program",          NULL},
+  {"GL_ARB_multitexture",              NULL},
+  {"GL_ARB_point_parameters",          GL_ARB_point_parameters_functions},
+  {"GL_ARB_shadow",                    NULL},
+  {"GL_ARB_shadow_ambient",            NULL},
+  {"GL_ARB_texture_border_clamp",      NULL},
+  {"GL_ARB_texture_cube_map",          NULL},
+  {"GL_ARB_texture_env_add",           NULL},
+  {"GL_ARB_texture_env_combine",       NULL},
+  {"GL_ARB_texture_env_crossbar",      NULL},
+  {"GL_ARB_texture_env_dot3",          NULL},
+  {"GL_ARB_texture_mirrored_repeat",   NULL},
+  {"GL_ARB_vertex_program",            GL_ARB_vertex_program_functions},
+  {"GL_EXT_blend_equation_separate",   GL_EXT_blend_equation_separate_functions},
+  {"GL_EXT_blend_func_separate",       GL_EXT_blend_func_separate_functions},
+  {"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_gpu_program_parameters",     GL_EXT_gpu_program_parameters_functions},
+  {"GL_EXT_secondary_color",           GL_EXT_secondary_color_functions},
+  {"GL_EXT_shadow_funcs",              NULL},
+  {"GL_EXT_stencil_two_side",          GL_EXT_stencil_two_side_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_separate_stencil",          GL_ATI_separate_stencil_functions},
+  {"GL_ATI_texture_env_combine3",      NULL},
+  {"GL_ATI_texture_mirror_once",       NULL},
+  {"GL_MESA_pack_invert",              NULL},
+  {"GL_MESA_ycbcr_texture",            NULL},
+  {"GL_MESAX_texture_float",           NULL},
+  {"GL_NV_blend_square",               NULL},
+  {"GL_NV_vertex_program",             GL_NV_vertex_program_functions},
+  {"GL_SGIS_generate_mipmap",          NULL},
+  {NULL,                               NULL}
+  /* *INDENT-ON* */
+};
+
 
-/* Extension strings exported by the R300 driver.
+/**
+ * The GL 2.0 functions are needed to make display lists work with
+ * functions added by GL_ATI_separate_stencil.
  */
-static const char *const card_extensions[] = {
-       "GL_ARB_multisample",
-       "GL_ARB_multitexture",
-       "GL_ARB_texture_border_clamp",
-       "GL_ARB_texture_compression",
-       "GL_ARB_texture_cube_map",
-       "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_ARB_vertex_program",
-       "GL_EXT_blend_equation_separate",
-       "GL_EXT_blend_func_separate",
-       "GL_EXT_blend_minmax",
-       "GL_EXT_blend_subtract",
-       "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_MESA_ycbcr_texture",
-       "GL_NV_blend_square",
-       "GL_NV_vertex_program",
-       "GL_SGIS_generate_mipmap",
-       NULL
+const struct dri_extension gl_20_extension[] = {
+  {"GL_VERSION_2_0",                   GL_VERSION_2_0_functions },
 };
 
-//extern const struct tnl_pipeline_stage _r300_render_stage;
-//extern const struct tnl_pipeline_stage _r300_tcl_stage;
+
+extern struct tnl_pipeline_stage _r300_render_stage;
+extern const struct tnl_pipeline_stage _r300_tcl_stage;
 
 static const struct tnl_pipeline_stage *r300_pipeline[] = {
 
        /* Try and go straight to t&l
         */
-       //&_r200_tcl_stage,
+       &_r300_tcl_stage,
 
        /* Catch any t&l fallbacks
         */
@@ -131,11 +177,83 @@ static const struct tnl_pipeline_stage *r300_pipeline[] = {
 
        /* Else do them here.
         */
-       //&_r300_render_stage,
+       &_r300_render_stage,
        &_tnl_render_stage,     /* FALLBACK  */
        0,
 };
 
+static void r300RunPipeline(GLcontext * ctx)
+{
+    _mesa_lock_context_textures(ctx);
+
+    if (ctx->NewState)
+        _mesa_update_state_locked(ctx);
+    
+    _tnl_run_pipeline(ctx);
+    _mesa_unlock_context_textures(ctx);
+}
+
+static void r300_get_lock(radeonContextPtr rmesa)
+{
+       drm_radeon_sarea_t *sarea = rmesa->sarea;
+
+       if (sarea->ctx_owner != rmesa->dri.hwContext) {
+               sarea->ctx_owner = rmesa->dri.hwContext;
+               if (!rmesa->radeonScreen->kernel_mm)
+                       radeon_bo_legacy_texture_age(rmesa->radeonScreen->bom);
+       }
+}                
+
+static void r300_vtbl_emit_cs_header(struct radeon_cs *cs, radeonContextPtr rmesa)
+{
+    /* please flush pipe do all pending work */
+    radeon_cs_write_dword(cs, cmdpacket0(rmesa->radeonScreen,
+                                  R300_SC_SCREENDOOR, 1));
+    radeon_cs_write_dword(cs, 0x0);
+    radeon_cs_write_dword(cs, cmdpacket0(rmesa->radeonScreen,
+                                  R300_SC_SCREENDOOR, 1));
+    radeon_cs_write_dword(cs, 0x00FFFFFF);
+    radeon_cs_write_dword(cs, cmdpacket0(rmesa->radeonScreen,
+                                  R300_SC_HYPERZ, 1));
+    radeon_cs_write_dword(cs, 0x0);
+    radeon_cs_write_dword(cs, cmdpacket0(rmesa->radeonScreen,
+                                  R300_US_CONFIG, 1));
+    radeon_cs_write_dword(cs, 0x0);
+    radeon_cs_write_dword(cs, cmdpacket0(rmesa->radeonScreen,
+                                  R300_ZB_CNTL, 1));
+    radeon_cs_write_dword(cs, 0x0);
+    radeon_cs_write_dword(cs, cmdwait(rmesa->radeonScreen, R300_WAIT_3D));
+    radeon_cs_write_dword(cs, cmdpacket0(rmesa->radeonScreen,
+                                  R300_RB3D_DSTCACHE_CTLSTAT, 1));
+    radeon_cs_write_dword(cs, R300_RB3D_DSTCACHE_CTLSTAT_DC_FLUSH_FLUSH_DIRTY_3D);
+    radeon_cs_write_dword(cs, cmdpacket0(rmesa->radeonScreen,
+                                  R300_ZB_ZCACHE_CTLSTAT, 1));
+    radeon_cs_write_dword(cs, R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_FLUSH_AND_FREE);
+    radeon_cs_write_dword(cs, cmdwait(rmesa->radeonScreen,
+                               R300_WAIT_3D | R300_WAIT_3D_CLEAN));
+}
+
+static void r300_vtbl_pre_emit_atoms(radeonContextPtr radeon)
+{
+   BATCH_LOCALS(radeon);
+   cp_wait(radeon, R300_WAIT_3D | R300_WAIT_3D_CLEAN);
+   BEGIN_BATCH_NO_AUTOSTATE(2);
+   OUT_BATCH(cmdpacket0(radeon->radeonScreen, R300_TX_INVALTAGS, 1));
+   OUT_BATCH(R300_TX_FLUSH);
+   END_BATCH();
+   end_3d(radeon);
+}
+
+static void r300_init_vtbl(radeonContextPtr radeon)
+{
+   radeon->vtbl.get_lock = r300_get_lock;
+   radeon->vtbl.update_viewport_offset = r300UpdateViewportOffset;
+   radeon->vtbl.update_draw_buffer = r300UpdateDrawBuffer;
+   radeon->vtbl.emit_cs_header = r300_vtbl_emit_cs_header;
+   radeon->vtbl.swtcl_flush = r300_swtcl_flush;
+   radeon->vtbl.pre_emit_atoms = r300_vtbl_pre_emit_atoms;
+}
+
 
 /* Create the device specific rendering context.
  */
@@ -148,7 +266,6 @@ GLboolean r300CreateContext(const __GLcontextModes * glVisual,
        struct dd_function_table functions;
        r300ContextPtr r300;
        GLcontext *ctx;
-       int i;
        int tcl_mode;
 
        assert(glVisual);
@@ -160,28 +277,41 @@ GLboolean r300CreateContext(const __GLcontextModes * glVisual,
        if (!r300)
                return GL_FALSE;
 
+       if (!(screen->chip_flags & RADEON_CHIPSET_TCL))
+               hw_tcl_on = future_hw_tcl_on = 0;
+
+       r300_init_vtbl(&r300->radeon);
        /* Parse configuration files.
         * Do this here so that initialMaxAnisotropy is set before we create
         * the default textures.
         */
        driParseConfigFiles(&r300->radeon.optionCache, &screen->optionCache,
                            screen->driScreen->myNum, "r300");
+       r300->radeon.initialMaxAnisotropy = driQueryOptionf(&r300->radeon.optionCache,
+                                                    "def_max_anisotropy");
 
        /* Init default driver functions then plug in our R300-specific functions
         * (the texture functions are especially important)
         */
        _mesa_init_driver_functions(&functions);
        r300InitIoctlFuncs(&functions);
-       //r200InitStateFuncs(&functions);
-       //r200InitTextureFuncs(&functions);
+       r300InitStateFuncs(&functions);
+       r300InitTextureFuncs(&functions);
+       r300InitShaderFuncs(&functions);
 
        if (!radeonInitContext(&r300->radeon, &functions,
-                              glVisual, driContextPriv, sharedContextPrivate)) {
+                              glVisual, driContextPriv,
+                              sharedContextPrivate)) {
                FREE(r300);
                return GL_FALSE;
        }
 
        /* Init r300 context data */
+       r300->radeon.texture_depth = driQueryOptioni(&r300->radeon.optionCache,
+                                             "texture_depth");
+       if (r300->radeon.texture_depth == DRI_CONF_TEXTURE_DEPTH_FB)
+               r300->radeon.texture_depth = (screen->cpp == 4) ?
+                   DRI_CONF_TEXTURE_DEPTH_32 : DRI_CONF_TEXTURE_DEPTH_16;
 
        /* 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
@@ -189,45 +319,57 @@ GLboolean r300CreateContext(const __GLcontextModes * glVisual,
         */
 
        ctx = r300->radeon.glCtx;
-       ctx->Const.MaxTextureImageUnits = driQueryOptioni(&r300->radeon.optionCache,
-                                                    "texture_image_units");
-       ctx->Const.MaxTextureCoordUnits = driQueryOptioni(&r300->radeon.optionCache,
-                                                    "texture_coord_units");
-       ctx->Const.MaxTextureUnits = MIN2(ctx->Const.MaxTextureImageUnits,
-                                         ctx->Const.MaxTextureCoordUnits);
+
+       ctx->Const.MaxTextureImageUnits =
+           driQueryOptioni(&r300->radeon.optionCache, "texture_image_units");
+       ctx->Const.MaxTextureCoordUnits =
+           driQueryOptioni(&r300->radeon.optionCache, "texture_coord_units");
+       ctx->Const.MaxTextureUnits =
+           MIN2(ctx->Const.MaxTextureImageUnits,
+                ctx->Const.MaxTextureCoordUnits);
        ctx->Const.MaxTextureMaxAnisotropy = 16.0;
+       ctx->Const.MaxTextureLodBias = 16.0;
+
+       if (screen->chip_family >= CHIP_FAMILY_RV515) {
+           ctx->Const.MaxTextureLevels = 13;
+           ctx->Const.MaxTextureRectSize = 4096;
+       }
 
-       /* No wide points.
-        */
        ctx->Const.MinPointSize = 1.0;
        ctx->Const.MinPointSizeAA = 1.0;
-       ctx->Const.MaxPointSize = 1.0;
-       ctx->Const.MaxPointSizeAA = 1.0;
+       ctx->Const.MaxPointSize = R300_POINTSIZE_MAX;
+       ctx->Const.MaxPointSizeAA = R300_POINTSIZE_MAX;
 
        ctx->Const.MinLineWidth = 1.0;
        ctx->Const.MinLineWidthAA = 1.0;
-       ctx->Const.MaxLineWidth = 1.0;
-       ctx->Const.MaxLineWidthAA = 1.0;
+       ctx->Const.MaxLineWidth = R300_LINESIZE_MAX;
+       ctx->Const.MaxLineWidthAA = R300_LINESIZE_MAX;
+
+       /* Needs further modifications */
+#if 0
+       ctx->Const.MaxArrayLockSize =
+           ( /*512 */ RADEON_BUFFER_SIZE * 16 * 1024) / (4 * 4);
+#endif
+
+       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);
+       _swsetup_Wakeup(ctx);
        _ae_create_context(ctx);
 
-#if 0
        /* Install the customized pipeline:
         */
        _tnl_destroy_pipeline(ctx);
-       _tnl_install_pipeline(ctx, r200_pipeline);
-       ctx->Driver.FlushVertices = r200FlushVertices;
-#endif
+       _tnl_install_pipeline(ctx, r300_pipeline);
 
        /* 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:
         */
@@ -236,33 +378,76 @@ GLboolean r300CreateContext(const __GLcontextModes * glVisual,
        _tnl_allow_pixel_fog(ctx, GL_FALSE);
        _tnl_allow_vertex_fog(ctx, GL_TRUE);
 
+       /* currently bogus data */
+       if (screen->chip_flags & RADEON_CHIPSET_TCL) {
+               ctx->Const.VertexProgram.MaxInstructions = VSF_MAX_FRAGMENT_LENGTH / 4;
+               ctx->Const.VertexProgram.MaxNativeInstructions =
+                 VSF_MAX_FRAGMENT_LENGTH / 4;
+               ctx->Const.VertexProgram.MaxNativeAttribs = 16; /* r420 */
+               ctx->Const.VertexProgram.MaxTemps = 32;
+               ctx->Const.VertexProgram.MaxNativeTemps =
+                 /*VSF_MAX_FRAGMENT_TEMPS */ 32;
+               ctx->Const.VertexProgram.MaxNativeParameters = 256;     /* r420 */
+               ctx->Const.VertexProgram.MaxNativeAddressRegs = 1;
+       }
+
+       ctx->Const.FragmentProgram.MaxNativeTemps = PFS_NUM_TEMP_REGS;
+       ctx->Const.FragmentProgram.MaxNativeAttribs = 11;       /* copy i915... */
+       ctx->Const.FragmentProgram.MaxNativeParameters = PFS_NUM_CONST_REGS;
+       ctx->Const.FragmentProgram.MaxNativeAluInstructions = PFS_MAX_ALU_INST;
+       ctx->Const.FragmentProgram.MaxNativeTexInstructions = PFS_MAX_TEX_INST;
+       ctx->Const.FragmentProgram.MaxNativeInstructions =
+           PFS_MAX_ALU_INST + PFS_MAX_TEX_INST;
+       ctx->Const.FragmentProgram.MaxNativeTexIndirections =
+           PFS_MAX_TEX_INDIRECT;
+       ctx->Const.FragmentProgram.MaxNativeAddressRegs = 0;    /* and these are?? */
+       ctx->VertexProgram._MaintainTnlProgram = GL_TRUE;
+       ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE;
+
        driInitExtensions(ctx, card_extensions, GL_TRUE);
 
-       radeonInitSpanFuncs(ctx);
+       if (driQueryOptionb
+           (&r300->radeon.optionCache, "disable_stencil_two_side"))
+               _mesa_disable_extension(ctx, "GL_EXT_stencil_two_side");
+
+       if (r300->radeon.glCtx->Mesa_DXTn
+           && !driQueryOptionb(&r300->radeon.optionCache, "disable_s3tc")) {
+               _mesa_enable_extension(ctx, "GL_EXT_texture_compression_s3tc");
+               _mesa_enable_extension(ctx, "GL_S3_s3tc");
+       } else
+           if (driQueryOptionb(&r300->radeon.optionCache, "force_s3tc_enable"))
+       {
+               _mesa_enable_extension(ctx, "GL_EXT_texture_compression_s3tc");
+       }
+
+       r300->disable_lowimpact_fallback =
+           driQueryOptionb(&r300->radeon.optionCache,
+                           "disable_lowimpact_fallback");
+
+       radeonInitSpanFuncs( ctx );
        r300InitCmdBuf(r300);
        r300InitState(r300);
-#if 0
-       /* plug in a few more device driver functions */
-       /* XXX these should really go right after _mesa_init_driver_functions() */
-       r200InitPixelFuncs(ctx);
-       r200InitTnlFuncs(ctx);
-       r200InitSwtcl(ctx);
-#endif
-       TNL_CONTEXT(ctx)->Driver.RunPipeline = _tnl_run_pipeline;
+       if (!(screen->chip_flags & RADEON_CHIPSET_TCL))
+               r300InitSwtcl(ctx);
+
+       TNL_CONTEXT(ctx)->Driver.RunPipeline = r300RunPipeline;
 
        tcl_mode = driQueryOptioni(&r300->radeon.optionCache, "tcl_mode");
-       if (1 ||
-           driQueryOptionb(&r300->radeon.optionCache, "no_rast")) {
+       if (driQueryOptionb(&r300->radeon.optionCache, "no_rast")) {
                fprintf(stderr, "disabling 3D acceleration\n");
+#if R200_MERGED
                FALLBACK(&r300->radeon, RADEON_FALLBACK_DISABLE, 1);
+#endif
        }
        if (tcl_mode == DRI_CONF_TCL_SW ||
-           !(r300->radeon.radeonScreen->chipset & RADEON_CHIPSET_TCL)) {
-               if (r300->radeon.radeonScreen->chipset & RADEON_CHIPSET_TCL) {
-                       r300->radeon.radeonScreen->chipset &= ~RADEON_CHIPSET_TCL;
+           !(r300->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL)) {
+               if (r300->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL) {
+                       r300->radeon.radeonScreen->chip_flags &=
+                           ~RADEON_CHIPSET_TCL;
                        fprintf(stderr, "Disabling HW TCL support\n");
                }
-               TCL_FALLBACK(r300->radeon.glCtx, RADEON_TCL_FALLBACK_TCL_DISABLE, 1);
+               TCL_FALLBACK(r300->radeon.glCtx,
+                            RADEON_TCL_FALLBACK_TCL_DISABLE, 1);
        }
 
        return GL_TRUE;
@@ -274,34 +459,44 @@ void r300DestroyContext(__DRIcontextPrivate * driContextPriv)
 {
        GET_CURRENT_CONTEXT(ctx);
        r300ContextPtr r300 = (r300ContextPtr) driContextPriv->driverPrivate;
+       radeonContextPtr radeon = (radeonContextPtr) r300;
        radeonContextPtr current = ctx ? RADEON_CONTEXT(ctx) : NULL;
 
+       if (RADEON_DEBUG & DEBUG_DRI) {
+               fprintf(stderr, "Destroying context !\n");
+       }
+
        /* check if we're deleting the currently bound context */
        if (&r300->radeon == current) {
                radeonFlush(r300->radeon.glCtx);
-               _mesa_make_current2(NULL, NULL, NULL);
+               _mesa_make_current(NULL, NULL, NULL);
        }
 
        /* Free r300 context resources */
        assert(r300);           /* should never be null */
 
        if (r300) {
-               GLboolean release_texture_heaps;
-
-               release_texture_heaps = (r300->radeon.glCtx->Shared->RefCount == 1);
                _swsetup_DestroyContext(r300->radeon.glCtx);
                _tnl_DestroyContext(r300->radeon.glCtx);
-               _ac_DestroyContext(r300->radeon.glCtx);
+               _vbo_DestroyContext(r300->radeon.glCtx);
                _swrast_DestroyContext(r300->radeon.glCtx);
 
+               rcommonFlushCmdBuf(&r300->radeon, __FUNCTION__);
+
+               if (radeon->state.scissor.pClipRects) {
+                       FREE(radeon->state.scissor.pClipRects);
+                       radeon->state.scissor.pClipRects = NULL;
+               }
+
                r300DestroyCmdBuf(r300);
 
-               /* free the Mesa context */
-               r300->radeon.glCtx->DriverCtx = NULL;
-               _mesa_destroy_context(r300->radeon.glCtx);
+               radeonCleanupContext(&r300->radeon);
+
+
+               /* the memory manager might be accessed when Mesa frees the shared
+                * state, so don't destroy it earlier
+                */
 
-               /* free the option cache */
-               driDestroyOptionCache(&r300->radeon.optionCache);
 
                FREE(r300);
        }