r200_context.c revision 53116910b10e3b8a05f42970eff311c21808699f
1/*
2Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
3
4The Weather Channel (TM) funded Tungsten Graphics to develop the
5initial release of the Radeon 8500 driver under the XFree86 license.
6This notice must be preserved.
7
8Permission is hereby granted, free of charge, to any person obtaining
9a copy of this software and associated documentation files (the
10"Software"), to deal in the Software without restriction, including
11without limitation the rights to use, copy, modify, merge, publish,
12distribute, sublicense, and/or sell copies of the Software, and to
13permit persons to whom the Software is furnished to do so, subject to
14the following conditions:
15
16The above copyright notice and this permission notice (including the
17next paragraph) shall be included in all copies or substantial
18portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
24LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
28**************************************************************************/
29
30/*
31 * Authors:
32 *   Keith Whitwell <keith@tungstengraphics.com>
33 */
34
35#include "main/glheader.h"
36#include "main/api_arrayelt.h"
37#include "main/context.h"
38#include "main/simple_list.h"
39#include "main/imports.h"
40#include "main/matrix.h"
41#include "main/extensions.h"
42#include "main/framebuffer.h"
43#include "main/state.h"
44
45#include "swrast/swrast.h"
46#include "swrast_setup/swrast_setup.h"
47#include "vbo/vbo.h"
48
49#include "tnl/tnl.h"
50#include "tnl/t_pipeline.h"
51
52#include "drivers/common/driverfuncs.h"
53
54#include "r200_context.h"
55#include "r200_ioctl.h"
56#include "r200_state.h"
57#include "r200_pixel.h"
58#include "r200_tex.h"
59#include "r200_swtcl.h"
60#include "r200_tcl.h"
61#include "r200_maos.h"
62#include "r200_vertprog.h"
63
64#include "radeon_span.h"
65
66#define need_GL_ARB_vertex_program
67#define need_GL_ATI_fragment_shader
68#define need_GL_EXT_blend_minmax
69#define need_GL_EXT_fog_coord
70#define need_GL_EXT_secondary_color
71#define need_GL_EXT_blend_equation_separate
72#define need_GL_EXT_blend_func_separate
73#define need_GL_NV_vertex_program
74#define need_GL_ARB_point_parameters
75#include "extension_helper.h"
76
77#define DRIVER_DATE	"20060602"
78
79#include "vblank.h"
80#include "utils.h"
81#include "xmlpool.h" /* for symbolic values of enum-type options */
82
83/* Return various strings for glGetString().
84 */
85static const GLubyte *r200GetString( GLcontext *ctx, GLenum name )
86{
87   r200ContextPtr rmesa = R200_CONTEXT(ctx);
88   static char buffer[128];
89   unsigned   offset;
90   GLuint agp_mode = (rmesa->radeon.radeonScreen->card_type == RADEON_CARD_PCI)? 0 :
91      rmesa->radeon.radeonScreen->AGPMode;
92
93   switch ( name ) {
94   case GL_VENDOR:
95      return (GLubyte *)"Tungsten Graphics, Inc.";
96
97   case GL_RENDERER:
98      offset = driGetRendererString( buffer, "R200", DRIVER_DATE,
99				     agp_mode );
100
101      sprintf( & buffer[ offset ], " %sTCL",
102	       !(rmesa->radeon.TclFallback & R200_TCL_FALLBACK_TCL_DISABLE)
103	       ? "" : "NO-" );
104
105      return (GLubyte *)buffer;
106
107   default:
108      return NULL;
109   }
110}
111
112
113/* Extension strings exported by the R200 driver.
114 */
115const struct dri_extension card_extensions[] =
116{
117    { "GL_ARB_multitexture",               NULL },
118    { "GL_ARB_texture_border_clamp",       NULL },
119    { "GL_ARB_texture_env_add",            NULL },
120    { "GL_ARB_texture_env_combine",        NULL },
121    { "GL_ARB_texture_env_dot3",           NULL },
122    { "GL_ARB_texture_env_crossbar",       NULL },
123    { "GL_ARB_texture_mirrored_repeat",    NULL },
124    { "GL_EXT_blend_minmax",               GL_EXT_blend_minmax_functions },
125    { "GL_EXT_blend_subtract",             NULL },
126    { "GL_EXT_fog_coord",                  GL_EXT_fog_coord_functions },
127    { "GL_EXT_secondary_color",            GL_EXT_secondary_color_functions },
128    { "GL_EXT_stencil_wrap",               NULL },
129    { "GL_EXT_texture_edge_clamp",         NULL },
130    { "GL_EXT_texture_env_combine",        NULL },
131    { "GL_EXT_texture_env_dot3",           NULL },
132    { "GL_EXT_texture_filter_anisotropic", NULL },
133    { "GL_EXT_texture_lod_bias",           NULL },
134    { "GL_EXT_texture_mirror_clamp",       NULL },
135    { "GL_EXT_texture_rectangle",          NULL },
136    { "GL_ATI_texture_env_combine3",       NULL },
137    { "GL_ATI_texture_mirror_once",        NULL },
138    { "GL_MESA_pack_invert",               NULL },
139    { "GL_NV_blend_square",                NULL },
140    { "GL_SGIS_generate_mipmap",           NULL },
141    { NULL,                                NULL }
142};
143
144const struct dri_extension blend_extensions[] = {
145    { "GL_EXT_blend_equation_separate",    GL_EXT_blend_equation_separate_functions },
146    { "GL_EXT_blend_func_separate",        GL_EXT_blend_func_separate_functions },
147    { NULL,                                NULL }
148};
149
150const struct dri_extension ARB_vp_extension[] = {
151    { "GL_ARB_vertex_program",             GL_ARB_vertex_program_functions }
152};
153
154const struct dri_extension NV_vp_extension[] = {
155    { "GL_NV_vertex_program",              GL_NV_vertex_program_functions }
156};
157
158const struct dri_extension ATI_fs_extension[] = {
159    { "GL_ATI_fragment_shader",            GL_ATI_fragment_shader_functions }
160};
161
162const struct dri_extension point_extensions[] = {
163    { "GL_ARB_point_sprite",               NULL },
164    { "GL_ARB_point_parameters",           GL_ARB_point_parameters_functions },
165    { NULL,                                NULL }
166};
167
168extern const struct tnl_pipeline_stage _r200_render_stage;
169extern const struct tnl_pipeline_stage _r200_tcl_stage;
170
171static const struct tnl_pipeline_stage *r200_pipeline[] = {
172
173   /* Try and go straight to t&l
174    */
175   &_r200_tcl_stage,
176
177   /* Catch any t&l fallbacks
178    */
179   &_tnl_vertex_transform_stage,
180   &_tnl_normal_transform_stage,
181   &_tnl_lighting_stage,
182   &_tnl_fog_coordinate_stage,
183   &_tnl_texgen_stage,
184   &_tnl_texture_transform_stage,
185   &_tnl_point_attenuation_stage,
186   &_tnl_vertex_program_stage,
187   /* Try again to go to tcl?
188    *     - no good for asymmetric-twoside (do with multipass)
189    *     - no good for asymmetric-unfilled (do with multipass)
190    *     - good for material
191    *     - good for texgen
192    *     - need to manipulate a bit of state
193    *
194    * - worth it/not worth it?
195    */
196
197   /* Else do them here.
198    */
199/*    &_r200_render_stage,  */ /* FIXME: bugs with ut2003 */
200   &_tnl_render_stage,		/* FALLBACK:  */
201   NULL,
202};
203
204
205
206/* Initialize the driver's misc functions.
207 */
208static void r200InitDriverFuncs( struct dd_function_table *functions )
209{
210    functions->GetBufferSize		= NULL; /* OBSOLETE */
211    functions->GetString		= r200GetString;
212}
213
214static const struct dri_debug_control debug_control[] =
215{
216    { "fall",  DEBUG_FALLBACKS },
217    { "tex",   DEBUG_TEXTURE },
218    { "ioctl", DEBUG_IOCTL },
219    { "prim",  DEBUG_PRIMS },
220    { "vert",  DEBUG_VERTS },
221    { "state", DEBUG_STATE },
222    { "code",  DEBUG_CODEGEN },
223    { "vfmt",  DEBUG_VFMT },
224    { "vtxf",  DEBUG_VFMT },
225    { "verb",  DEBUG_VERBOSE },
226    { "dri",   DEBUG_DRI },
227    { "dma",   DEBUG_DMA },
228    { "san",   DEBUG_SANITY },
229    { "sync",  DEBUG_SYNC },
230    { "pix",   DEBUG_PIXEL },
231    { "mem",   DEBUG_MEMORY },
232    { NULL,    0 }
233};
234
235static void r200_get_lock(radeonContextPtr radeon)
236{
237   r200ContextPtr rmesa = (r200ContextPtr)radeon;
238   drm_radeon_sarea_t *sarea = radeon->sarea;
239   int i;
240
241   R200_STATECHANGE( rmesa, ctx );
242   if (rmesa->radeon.sarea->tiling_enabled) {
243      rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] |= R200_COLOR_TILE_ENABLE;
244   }
245   else rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] &= ~R200_COLOR_TILE_ENABLE;
246
247   if ( sarea->ctx_owner != rmesa->radeon.dri.hwContext ) {
248      sarea->ctx_owner = rmesa->radeon.dri.hwContext;
249   }
250
251   for ( i = 0 ; i < rmesa->radeon.nr_heaps ; i++ ) {
252      DRI_AGE_TEXTURES( rmesa->radeon.texture_heaps[ i ] );
253   }
254}
255
256static void r200_vtbl_emit_cs_header(struct radeon_cs *cs, radeonContextPtr rmesa)
257{
258}
259
260
261static void r200_init_vtbl(radeonContextPtr radeon)
262{
263   radeon->vtbl.get_lock = r200_get_lock;
264   radeon->vtbl.update_viewport_offset = r200UpdateViewportOffset;
265   radeon->vtbl.update_draw_buffer = r200UpdateDrawBuffer;
266   radeon->vtbl.emit_cs_header = r200_vtbl_emit_cs_header;
267   radeon->vtbl.swtcl_flush = r200_swtcl_flush;
268}
269
270
271/* Create the device specific rendering context.
272 */
273GLboolean r200CreateContext( const __GLcontextModes *glVisual,
274			     __DRIcontextPrivate *driContextPriv,
275			     void *sharedContextPrivate)
276{
277   __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
278   radeonScreenPtr screen = (radeonScreenPtr)(sPriv->private);
279   struct dd_function_table functions;
280   r200ContextPtr rmesa;
281   GLcontext *ctx;
282   int i;
283   int tcl_mode;
284
285   assert(glVisual);
286   assert(driContextPriv);
287   assert(screen);
288
289   /* Allocate the R200 context */
290   rmesa = (r200ContextPtr) CALLOC( sizeof(*rmesa) );
291   if ( !rmesa )
292      return GL_FALSE;
293
294   r200_init_vtbl(&rmesa->radeon);
295   /* init exp fog table data */
296   r200InitStaticFogData();
297
298   /* Parse configuration files.
299    * Do this here so that initialMaxAnisotropy is set before we create
300    * the default textures.
301    */
302   driParseConfigFiles (&rmesa->radeon.optionCache, &screen->optionCache,
303			screen->driScreen->myNum, "r200");
304   rmesa->radeon.initialMaxAnisotropy = driQueryOptionf(&rmesa->radeon.optionCache,
305							"def_max_anisotropy");
306
307   if ( driQueryOptionb( &rmesa->radeon.optionCache, "hyperz" ) ) {
308      if ( sPriv->drm_version.minor < 13 )
309	 fprintf( stderr, "DRM version 1.%d too old to support HyperZ, "
310			  "disabling.\n", sPriv->drm_version.minor );
311      else
312	 rmesa->using_hyperz = GL_TRUE;
313   }
314
315   if ( sPriv->drm_version.minor >= 15 )
316      rmesa->texmicrotile = GL_TRUE;
317
318   /* Init default driver functions then plug in our R200-specific functions
319    * (the texture functions are especially important)
320    */
321   _mesa_init_driver_functions(&functions);
322   r200InitDriverFuncs(&functions);
323   r200InitIoctlFuncs(&functions);
324   r200InitStateFuncs(&functions);
325   r200InitTextureFuncs(&functions);
326   r200InitShaderFuncs(&functions);
327
328   if (!radeonInitContext(&rmesa->radeon, &functions,
329			  glVisual, driContextPriv,
330			  sharedContextPrivate)) {
331     FREE(rmesa);
332     return GL_FALSE;
333   }
334
335
336   (void) memset( rmesa->radeon.texture_heaps, 0, sizeof( rmesa->radeon.texture_heaps ) );
337   make_empty_list( & rmesa->radeon.swapped );
338
339   rmesa->radeon.nr_heaps = 1 /* screen->numTexHeaps */ ;
340   assert(rmesa->radeon.nr_heaps < RADEON_NR_TEX_HEAPS);
341#if 0
342   for ( i = 0 ; i < rmesa->radeon.nr_heaps ; i++ ) {
343      rmesa->radeon.texture_heaps[i] = driCreateTextureHeap( i, rmesa,
344	    screen->texSize[i],
345	    12,
346	    RADEON_NR_TEX_REGIONS,
347	    (drmTextureRegionPtr)rmesa->radeon.sarea->tex_list[i],
348	    & rmesa->radeon.sarea->tex_age[i],
349	    & rmesa->radeon.swapped,
350	    sizeof( radeonTexObj ),
351	    (destroy_texture_object_t *) r200DestroyTexObj );
352   }
353#endif
354   rmesa->radeon.texture_depth = driQueryOptioni (&rmesa->radeon.optionCache,
355					   "texture_depth");
356   if (rmesa->radeon.texture_depth == DRI_CONF_TEXTURE_DEPTH_FB)
357      rmesa->radeon.texture_depth = ( screen->cpp == 4 ) ?
358	 DRI_CONF_TEXTURE_DEPTH_32 : DRI_CONF_TEXTURE_DEPTH_16;
359
360   rmesa->radeon.swtcl.RenderIndex = ~0;
361   rmesa->radeon.hw.all_dirty = 1;
362
363   /* Set the maximum texture size small enough that we can guarentee that
364    * all texture units can bind a maximal texture and have all of them in
365    * texturable memory at once. Depending on the allow_large_textures driconf
366    * setting allow larger textures.
367    */
368
369   ctx = rmesa->radeon.glCtx;
370   ctx->Const.MaxTextureUnits = driQueryOptioni (&rmesa->radeon.optionCache,
371						 "texture_units");
372   ctx->Const.MaxTextureImageUnits = ctx->Const.MaxTextureUnits;
373   ctx->Const.MaxTextureCoordUnits = ctx->Const.MaxTextureUnits;
374
375   i = driQueryOptioni( &rmesa->radeon.optionCache, "allow_large_textures");
376
377   driCalculateMaxTextureLevels( rmesa->radeon.texture_heaps,
378				 rmesa->radeon.nr_heaps,
379				 & ctx->Const,
380				 4,
381				 11, /* max 2D texture size is 2048x2048 */
382#if ENABLE_HW_3D_TEXTURE
383				 8,  /* max 3D texture size is 256^3 */
384#else
385				 0,  /* 3D textures unsupported */
386#endif
387				 11, /* max cube texture size is 2048x2048 */
388				 11, /* max texture rectangle size is 2048x2048 */
389				 12,
390				 GL_FALSE,
391				 i );
392
393   ctx->Const.MaxTextureMaxAnisotropy = 16.0;
394
395   /* No wide AA points.
396    */
397   ctx->Const.MinPointSize = 1.0;
398   ctx->Const.MinPointSizeAA = 1.0;
399   ctx->Const.MaxPointSizeAA = 1.0;
400   ctx->Const.PointSizeGranularity = 0.0625;
401   if (rmesa->radeon.radeonScreen->drmSupportsPointSprites)
402      ctx->Const.MaxPointSize = 2047.0;
403   else
404      ctx->Const.MaxPointSize = 1.0;
405
406   /* mesa initialization problem - _mesa_init_point was already called */
407   ctx->Point.MaxSize = ctx->Const.MaxPointSize;
408
409   ctx->Const.MinLineWidth = 1.0;
410   ctx->Const.MinLineWidthAA = 1.0;
411   ctx->Const.MaxLineWidth = 10.0;
412   ctx->Const.MaxLineWidthAA = 10.0;
413   ctx->Const.LineWidthGranularity = 0.0625;
414
415   ctx->Const.VertexProgram.MaxNativeInstructions = R200_VSF_MAX_INST;
416   ctx->Const.VertexProgram.MaxNativeAttribs = 12;
417   ctx->Const.VertexProgram.MaxNativeTemps = R200_VSF_MAX_TEMPS;
418   ctx->Const.VertexProgram.MaxNativeParameters = R200_VSF_MAX_PARAM;
419   ctx->Const.VertexProgram.MaxNativeAddressRegs = 1;
420
421   ctx->Const.MaxDrawBuffers = 1;
422
423   /* Initialize the software rasterizer and helper modules.
424    */
425   _swrast_CreateContext( ctx );
426   _vbo_CreateContext( ctx );
427   _tnl_CreateContext( ctx );
428   _swsetup_CreateContext( ctx );
429   _ae_create_context( ctx );
430
431   /* Install the customized pipeline:
432    */
433   _tnl_destroy_pipeline( ctx );
434   _tnl_install_pipeline( ctx, r200_pipeline );
435
436   /* Try and keep materials and vertices separate:
437    */
438/*    _tnl_isolate_materials( ctx, GL_TRUE ); */
439
440
441   /* Configure swrast and TNL to match hardware characteristics:
442    */
443   _swrast_allow_pixel_fog( ctx, GL_FALSE );
444   _swrast_allow_vertex_fog( ctx, GL_TRUE );
445   _tnl_allow_pixel_fog( ctx, GL_FALSE );
446   _tnl_allow_vertex_fog( ctx, GL_TRUE );
447
448
449   for ( i = 0 ; i < R200_MAX_TEXTURE_UNITS ; i++ ) {
450      _math_matrix_ctr( &rmesa->TexGenMatrix[i] );
451      _math_matrix_set_identity( &rmesa->TexGenMatrix[i] );
452   }
453   _math_matrix_ctr( &rmesa->tmpmat );
454   _math_matrix_set_identity( &rmesa->tmpmat );
455
456   driInitExtensions( ctx, card_extensions, GL_TRUE );
457   if (!(rmesa->radeon.radeonScreen->chip_flags & R200_CHIPSET_YCBCR_BROKEN)) {
458     /* yuv textures don't work with some chips - R200 / rv280 okay so far
459	others get the bit ordering right but don't actually do YUV-RGB conversion */
460      _mesa_enable_extension( ctx, "GL_MESA_ycbcr_texture" );
461   }
462   if (rmesa->radeon.glCtx->Mesa_DXTn) {
463      _mesa_enable_extension( ctx, "GL_EXT_texture_compression_s3tc" );
464      _mesa_enable_extension( ctx, "GL_S3_s3tc" );
465   }
466   else if (driQueryOptionb (&rmesa->radeon.optionCache, "force_s3tc_enable")) {
467      _mesa_enable_extension( ctx, "GL_EXT_texture_compression_s3tc" );
468   }
469
470   if (rmesa->radeon.radeonScreen->drmSupportsCubeMapsR200)
471      _mesa_enable_extension( ctx, "GL_ARB_texture_cube_map" );
472   if (rmesa->radeon.radeonScreen->drmSupportsBlendColor) {
473       driInitExtensions( ctx, blend_extensions, GL_FALSE );
474   }
475   if(rmesa->radeon.radeonScreen->drmSupportsVertexProgram)
476      driInitSingleExtension( ctx, ARB_vp_extension );
477   if(driQueryOptionb(&rmesa->radeon.optionCache, "nv_vertex_program"))
478      driInitSingleExtension( ctx, NV_vp_extension );
479
480   if ((ctx->Const.MaxTextureUnits == 6) && rmesa->radeon.radeonScreen->drmSupportsFragShader)
481      driInitSingleExtension( ctx, ATI_fs_extension );
482   if (rmesa->radeon.radeonScreen->drmSupportsPointSprites)
483      driInitExtensions( ctx, point_extensions, GL_FALSE );
484#if 0
485   r200InitDriverFuncs( ctx );
486   r200InitIoctlFuncs( ctx );
487   r200InitStateFuncs( ctx );
488   r200InitTextureFuncs( ctx );
489#endif
490   /* plug in a few more device driver functions */
491   /* XXX these should really go right after _mesa_init_driver_functions() */
492   radeonInitSpanFuncs( ctx );
493   r200InitPixelFuncs( ctx );
494   r200InitTnlFuncs( ctx );
495   r200InitState( rmesa );
496   r200InitSwtcl( ctx );
497
498   rmesa->prefer_gart_client_texturing =
499      (getenv("R200_GART_CLIENT_TEXTURES") != 0);
500
501#if DO_DEBUG
502   R200_DEBUG  = driParseDebugString( getenv( "R200_DEBUG" ),
503				      debug_control );
504   R200_DEBUG |= driParseDebugString( getenv( "RADEON_DEBUG" ),
505				      debug_control );
506#endif
507
508   tcl_mode = driQueryOptioni(&rmesa->radeon.optionCache, "tcl_mode");
509   if (driQueryOptionb(&rmesa->radeon.optionCache, "no_rast")) {
510      fprintf(stderr, "disabling 3D acceleration\n");
511      FALLBACK(rmesa, R200_FALLBACK_DISABLE, 1);
512   }
513   else if (tcl_mode == DRI_CONF_TCL_SW || getenv("R200_NO_TCL") ||
514	    !(rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL)) {
515      if (rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL) {
516	 rmesa->radeon.radeonScreen->chip_flags &= ~RADEON_CHIPSET_TCL;
517	 fprintf(stderr, "Disabling HW TCL support\n");
518      }
519      TCL_FALLBACK(rmesa->radeon.glCtx, R200_TCL_FALLBACK_TCL_DISABLE, 1);
520   }
521
522   return GL_TRUE;
523}
524
525
526/* Destroy the device specific context.
527 */
528/* Destroy the Mesa and driver specific context data.
529 */
530void r200DestroyContext( __DRIcontextPrivate *driContextPriv )
531{
532   GET_CURRENT_CONTEXT(ctx);
533   r200ContextPtr rmesa = (r200ContextPtr) driContextPriv->driverPrivate;
534   r200ContextPtr current = ctx ? R200_CONTEXT(ctx) : NULL;
535
536   /* check if we're deleting the currently bound context */
537   if (rmesa == current) {
538      radeon_firevertices(&rmesa->radeon);
539      _mesa_make_current(NULL, NULL, NULL);
540   }
541
542   /* Free r200 context resources */
543   assert(rmesa); /* should never be null */
544   if ( rmesa ) {
545      GLboolean   release_texture_heaps;
546
547
548      release_texture_heaps = (rmesa->radeon.glCtx->Shared->RefCount == 1);
549      _swsetup_DestroyContext( rmesa->radeon.glCtx );
550      _tnl_DestroyContext( rmesa->radeon.glCtx );
551      _vbo_DestroyContext( rmesa->radeon.glCtx );
552      _swrast_DestroyContext( rmesa->radeon.glCtx );
553
554      r200DestroySwtcl( rmesa->radeon.glCtx );
555      r200ReleaseArrays( rmesa->radeon.glCtx, ~0 );
556
557      if (rmesa->radeon.dma.current) {
558	 rcommonFlushCmdBuf( &rmesa->radeon, __FUNCTION__ );
559      }
560
561      if (rmesa->radeon.state.scissor.pClipRects) {
562	 FREE(rmesa->radeon.state.scissor.pClipRects);
563	 rmesa->radeon.state.scissor.pClipRects = NULL;
564      }
565
566
567      if ( release_texture_heaps ) {
568         /* This share group is about to go away, free our private
569          * texture object data.
570          */
571         int i;
572
573         for ( i = 0 ; i < rmesa->radeon.nr_heaps ; i++ ) {
574	    driDestroyTextureHeap( rmesa->radeon.texture_heaps[ i ] );
575	    rmesa->radeon.texture_heaps[ i ] = NULL;
576         }
577
578	 assert( is_empty_list( & rmesa->radeon.swapped ) );
579      }
580
581      radeonCleanupContext(&rmesa->radeon);
582
583      FREE( rmesa );
584   }
585}
586
587
588
589/* Force the context `c' to be unbound from its buffer.
590 */
591GLboolean
592r200UnbindContext( __DRIcontextPrivate *driContextPriv )
593{
594   r200ContextPtr rmesa = (r200ContextPtr) driContextPriv->driverPrivate;
595
596   if (R200_DEBUG & DEBUG_DRI)
597      fprintf(stderr, "%s ctx %p\n", __FUNCTION__, (void *)rmesa->radeon.glCtx);
598
599   return GL_TRUE;
600}
601