r200_context.c revision 5f1ba3e21b62cee1a4f900a2e6964728f3eeea9b
1/* $XFree86: xc/lib/GL/mesa/src/drv/r200/r200_context.c,v 1.3 2003/05/06 23:52:08 daenzer Exp $ */
2/*
3Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
4
5The Weather Channel (TM) funded Tungsten Graphics to develop the
6initial release of the Radeon 8500 driver under the XFree86 license.
7This notice must be preserved.
8
9Permission is hereby granted, free of charge, to any person obtaining
10a copy of this software and associated documentation files (the
11"Software"), to deal in the Software without restriction, including
12without limitation the rights to use, copy, modify, merge, publish,
13distribute, sublicense, and/or sell copies of the Software, and to
14permit persons to whom the Software is furnished to do so, subject to
15the following conditions:
16
17The above copyright notice and this permission notice (including the
18next paragraph) shall be included in all copies or substantial
19portions of the Software.
20
21THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
25LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
29**************************************************************************/
30
31/*
32 * Authors:
33 *   Keith Whitwell <keith@tungstengraphics.com>
34 */
35
36#include "glheader.h"
37#include "api_arrayelt.h"
38#include "context.h"
39#include "simple_list.h"
40#include "imports.h"
41#include "matrix.h"
42#include "extensions.h"
43#include "framebuffer.h"
44#include "state.h"
45
46#include "swrast/swrast.h"
47#include "swrast_setup/swrast_setup.h"
48#include "array_cache/acache.h"
49
50#include "tnl/tnl.h"
51#include "tnl/t_pipeline.h"
52
53#include "drivers/common/driverfuncs.h"
54
55#include "r200_context.h"
56#include "r200_ioctl.h"
57#include "r200_state.h"
58#include "r200_span.h"
59#include "r200_pixel.h"
60#include "r200_tex.h"
61#include "r200_swtcl.h"
62#include "r200_tcl.h"
63#include "r200_vtxfmt.h"
64#include "r200_maos.h"
65
66#define need_GL_ARB_multisample
67#define need_GL_ARB_texture_compression
68#define need_GL_ARB_vertex_buffer_object
69#define need_GL_ARB_vertex_program
70#define need_GL_EXT_blend_minmax
71#define need_GL_EXT_fog_coord
72#define need_GL_EXT_secondary_color
73#define need_GL_EXT_blend_equation_separate
74#define need_GL_EXT_blend_func_separate
75#define need_GL_NV_vertex_program
76#include "extension_helper.h"
77
78#define DRIVER_DATE	"20041207"
79
80#include "vblank.h"
81#include "utils.h"
82#include "xmlpool.h" /* for symbolic values of enum-type options */
83#ifndef R200_DEBUG
84int R200_DEBUG = (0);
85#endif
86
87
88/* Return the width and height of the given buffer.
89 */
90static void r200GetBufferSize( GLframebuffer *buffer,
91			       GLuint *width, GLuint *height )
92{
93   GET_CURRENT_CONTEXT(ctx);
94   r200ContextPtr rmesa = R200_CONTEXT(ctx);
95
96   LOCK_HARDWARE( rmesa );
97   *width  = rmesa->dri.drawable->w;
98   *height = rmesa->dri.drawable->h;
99   UNLOCK_HARDWARE( rmesa );
100}
101
102/* Return various strings for glGetString().
103 */
104static const GLubyte *r200GetString( GLcontext *ctx, GLenum name )
105{
106   r200ContextPtr rmesa = R200_CONTEXT(ctx);
107   static char buffer[128];
108   unsigned   offset;
109   GLuint agp_mode = rmesa->r200Screen->IsPCI ? 0 :
110      rmesa->r200Screen->AGPMode;
111
112   switch ( name ) {
113   case GL_VENDOR:
114      return (GLubyte *)"Tungsten Graphics, Inc.";
115
116   case GL_RENDERER:
117      offset = driGetRendererString( buffer, "R200", DRIVER_DATE,
118				     agp_mode );
119
120      sprintf( & buffer[ offset ], " %sTCL",
121	       !(rmesa->TclFallback & R200_TCL_FALLBACK_TCL_DISABLE)
122	       ? "" : "NO-" );
123
124      return (GLubyte *)buffer;
125
126   default:
127      return NULL;
128   }
129}
130
131
132/* Extension strings exported by the R200 driver.
133 */
134static const struct dri_extension card_extensions[] =
135{
136    { "GL_ARB_multisample",                GL_ARB_multisample_functions },
137    { "GL_ARB_multitexture",               NULL },
138    { "GL_ARB_texture_border_clamp",       NULL },
139    { "GL_ARB_texture_compression",        GL_ARB_texture_compression_functions },
140    { "GL_ARB_texture_env_add",            NULL },
141    { "GL_ARB_texture_env_combine",        NULL },
142    { "GL_ARB_texture_env_dot3",           NULL },
143    { "GL_ARB_texture_mirrored_repeat",    NULL },
144    { "GL_ARB_vertex_buffer_object",       GL_ARB_vertex_buffer_object_functions },
145    { "GL_EXT_blend_minmax",               GL_EXT_blend_minmax_functions },
146    { "GL_EXT_blend_subtract",             NULL },
147    { "GL_EXT_fog_coord",                  GL_EXT_fog_coord_functions },
148    { "GL_EXT_secondary_color",            GL_EXT_secondary_color_functions },
149    { "GL_EXT_stencil_wrap",               NULL },
150    { "GL_EXT_texture_edge_clamp",         NULL },
151    { "GL_EXT_texture_env_combine",        NULL },
152    { "GL_EXT_texture_env_dot3",           NULL },
153    { "GL_EXT_texture_filter_anisotropic", NULL },
154    { "GL_EXT_texture_lod_bias",           NULL },
155    { "GL_EXT_texture_mirror_clamp",       NULL },
156    { "GL_EXT_texture_rectangle",          NULL },
157    { "GL_ATI_texture_env_combine3",       NULL },
158    { "GL_ATI_texture_mirror_once",        NULL },
159    { "GL_MESA_pack_invert",               NULL },
160    { "GL_NV_blend_square",                NULL },
161    { "GL_SGIS_generate_mipmap",           NULL },
162    { NULL,                                NULL }
163};
164
165static const struct dri_extension blend_extensions[] = {
166    { "GL_EXT_blend_equation_separate",    GL_EXT_blend_equation_separate_functions },
167    { "GL_EXT_blend_func_separate",        GL_EXT_blend_func_separate_functions },
168    { NULL,                                NULL }
169};
170
171static const struct dri_extension ARB_vp_extension[] = {
172    { "GL_ARB_vertex_program",             GL_ARB_vertex_program_functions }
173};
174
175static const struct dri_extension NV_vp_extension[] = {
176    { "GL_NV_vertex_program",              GL_NV_vertex_program_functions }
177};
178
179extern const struct tnl_pipeline_stage _r200_render_stage;
180extern const struct tnl_pipeline_stage _r200_tcl_stage;
181
182static const struct tnl_pipeline_stage *r200_pipeline[] = {
183
184   /* Try and go straight to t&l
185    */
186   &_r200_tcl_stage,
187
188   /* Catch any t&l fallbacks
189    */
190   &_tnl_vertex_transform_stage,
191   &_tnl_normal_transform_stage,
192   &_tnl_lighting_stage,
193   &_tnl_fog_coordinate_stage,
194   &_tnl_texgen_stage,
195   &_tnl_texture_transform_stage,
196   &_tnl_vertex_program_stage,
197
198   /* Try again to go to tcl?
199    *     - no good for asymmetric-twoside (do with multipass)
200    *     - no good for asymmetric-unfilled (do with multipass)
201    *     - good for material
202    *     - good for texgen
203    *     - need to manipulate a bit of state
204    *
205    * - worth it/not worth it?
206    */
207
208   /* Else do them here.
209    */
210/*    &_r200_render_stage,  */ /* FIXME: bugs with ut2003 */
211   &_tnl_render_stage,		/* FALLBACK:  */
212   NULL,
213};
214
215
216
217/* Initialize the driver's misc functions.
218 */
219static void r200InitDriverFuncs( struct dd_function_table *functions )
220{
221    functions->GetBufferSize		= r200GetBufferSize;
222    functions->ResizeBuffers            = _mesa_resize_framebuffer;
223    functions->GetString		= r200GetString;
224
225    functions->Error			= NULL;
226    functions->DrawPixels		= NULL;
227    functions->Bitmap			= NULL;
228}
229
230static const struct dri_debug_control debug_control[] =
231{
232    { "fall",  DEBUG_FALLBACKS },
233    { "tex",   DEBUG_TEXTURE },
234    { "ioctl", DEBUG_IOCTL },
235    { "prim",  DEBUG_PRIMS },
236    { "vert",  DEBUG_VERTS },
237    { "state", DEBUG_STATE },
238    { "code",  DEBUG_CODEGEN },
239    { "vfmt",  DEBUG_VFMT },
240    { "vtxf",  DEBUG_VFMT },
241    { "verb",  DEBUG_VERBOSE },
242    { "dri",   DEBUG_DRI },
243    { "dma",   DEBUG_DMA },
244    { "san",   DEBUG_SANITY },
245    { "sync",  DEBUG_SYNC },
246    { "pix",   DEBUG_PIXEL },
247    { "mem",   DEBUG_MEMORY },
248    { NULL,    0 }
249};
250
251
252/* Create the device specific rendering context.
253 */
254GLboolean r200CreateContext( const __GLcontextModes *glVisual,
255			     __DRIcontextPrivate *driContextPriv,
256			     void *sharedContextPrivate)
257{
258   __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
259   r200ScreenPtr screen = (r200ScreenPtr)(sPriv->private);
260   struct dd_function_table functions;
261   r200ContextPtr rmesa;
262   GLcontext *ctx, *shareCtx;
263   int i;
264   int tcl_mode, fthrottle_mode;
265
266   assert(glVisual);
267   assert(driContextPriv);
268   assert(screen);
269
270   /* Allocate the R200 context */
271   rmesa = (r200ContextPtr) CALLOC( sizeof(*rmesa) );
272   if ( !rmesa )
273      return GL_FALSE;
274
275   /* init exp fog table data */
276   r200InitStaticFogData();
277
278   /* Parse configuration files.
279    * Do this here so that initialMaxAnisotropy is set before we create
280    * the default textures.
281    */
282   driParseConfigFiles (&rmesa->optionCache, &screen->optionCache,
283			screen->driScreen->myNum, "r200");
284   rmesa->initialMaxAnisotropy = driQueryOptionf(&rmesa->optionCache,
285                                                 "def_max_anisotropy");
286
287   if ( driQueryOptionb( &rmesa->optionCache, "hyperz" ) ) {
288      if ( sPriv->drmMinor < 13 )
289	 fprintf( stderr, "DRM version 1.%d too old to support HyperZ, "
290			  "disabling.\n",sPriv->drmMinor );
291      else
292	 rmesa->using_hyperz = GL_TRUE;
293   }
294
295   if ( sPriv->drmMinor >= 15 )
296      rmesa->texmicrotile = GL_TRUE;
297
298   /* Init default driver functions then plug in our R200-specific functions
299    * (the texture functions are especially important)
300    */
301   _mesa_init_driver_functions(&functions);
302   r200InitDriverFuncs(&functions);
303   r200InitIoctlFuncs(&functions);
304   r200InitStateFuncs(&functions);
305   r200InitTextureFuncs(&functions);
306
307   /* Allocate and initialize the Mesa context */
308   if (sharedContextPrivate)
309      shareCtx = ((r200ContextPtr) sharedContextPrivate)->glCtx;
310   else
311      shareCtx = NULL;
312   rmesa->glCtx = _mesa_create_context(glVisual, shareCtx,
313                                       &functions, (void *) rmesa);
314   if (!rmesa->glCtx) {
315      FREE(rmesa);
316      return GL_FALSE;
317   }
318   driContextPriv->driverPrivate = rmesa;
319
320   /* Init r200 context data */
321   rmesa->dri.context = driContextPriv;
322   rmesa->dri.screen = sPriv;
323   rmesa->dri.drawable = NULL; /* Set by XMesaMakeCurrent */
324   rmesa->dri.hwContext = driContextPriv->hHWContext;
325   rmesa->dri.hwLock = &sPriv->pSAREA->lock;
326   rmesa->dri.fd = sPriv->fd;
327   rmesa->dri.drmMinor = sPriv->drmMinor;
328
329   rmesa->r200Screen = screen;
330   rmesa->sarea = (drm_radeon_sarea_t *)((GLubyte *)sPriv->pSAREA +
331				       screen->sarea_priv_offset);
332
333
334   rmesa->dma.buf0_address = rmesa->r200Screen->buffers->list[0].address;
335
336   (void) memset( rmesa->texture_heaps, 0, sizeof( rmesa->texture_heaps ) );
337   make_empty_list( & rmesa->swapped );
338
339   rmesa->nr_heaps = 1 /* screen->numTexHeaps */ ;
340   assert(rmesa->nr_heaps < R200_NR_TEX_HEAPS);
341   for ( i = 0 ; i < rmesa->nr_heaps ; i++ ) {
342      rmesa->texture_heaps[i] = driCreateTextureHeap( i, rmesa,
343	    screen->texSize[i],
344	    12,
345	    RADEON_NR_TEX_REGIONS,
346	    (drmTextureRegionPtr)rmesa->sarea->tex_list[i],
347	    & rmesa->sarea->tex_age[i],
348	    & rmesa->swapped,
349	    sizeof( r200TexObj ),
350	    (destroy_texture_object_t *) r200DestroyTexObj );
351   }
352   rmesa->texture_depth = driQueryOptioni (&rmesa->optionCache,
353					   "texture_depth");
354   if (rmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FB)
355      rmesa->texture_depth = ( screen->cpp == 4 ) ?
356	 DRI_CONF_TEXTURE_DEPTH_32 : DRI_CONF_TEXTURE_DEPTH_16;
357
358   rmesa->swtcl.RenderIndex = ~0;
359   rmesa->hw.all_dirty = 1;
360
361   /* Set the maximum texture size small enough that we can guarentee that
362    * all texture units can bind a maximal texture and have them both in
363    * texturable memory at once.
364    */
365
366   ctx = rmesa->glCtx;
367   ctx->Const.MaxTextureUnits = driQueryOptioni (&rmesa->optionCache,
368						 "texture_units");
369   ctx->Const.MaxTextureImageUnits = ctx->Const.MaxTextureUnits;
370   ctx->Const.MaxTextureCoordUnits = ctx->Const.MaxTextureUnits;
371
372   driCalculateMaxTextureLevels( rmesa->texture_heaps,
373				 rmesa->nr_heaps,
374				 & ctx->Const,
375				 4,
376				 11, /* max 2D texture size is 2048x2048 */
377#if ENABLE_HW_3D_TEXTURE
378				 8,  /* max 3D texture size is 256^3 */
379#else
380				 0,  /* 3D textures unsupported */
381#endif
382				 11, /* max cube texture size is 2048x2048 */
383				 11, /* max texture rectangle size is 2048x2048 */
384				 12,
385				 GL_FALSE );
386
387   /* adjust max texture size a bit. Hack, but I really want to use larger textures
388      which will work just fine in 99.999999% of all cases, especially with texture compression... */
389   if (driQueryOptionb( &rmesa->optionCache, "texture_level_hack" ))
390   {
391     if (ctx->Const.MaxTextureLevels < 12) ctx->Const.MaxTextureLevels += 1;
392   }
393
394   ctx->Const.MaxTextureMaxAnisotropy = 16.0;
395
396   /* No wide points.
397    */
398   ctx->Const.MinPointSize = 1.0;
399   ctx->Const.MinPointSizeAA = 1.0;
400   ctx->Const.MaxPointSize = 1.0;
401   ctx->Const.MaxPointSizeAA = 1.0;
402
403   ctx->Const.MinLineWidth = 1.0;
404   ctx->Const.MinLineWidthAA = 1.0;
405   ctx->Const.MaxLineWidth = 10.0;
406   ctx->Const.MaxLineWidthAA = 10.0;
407   ctx->Const.LineWidthGranularity = 0.0625;
408
409   /* Initialize the software rasterizer and helper modules.
410    */
411   _swrast_CreateContext( ctx );
412   _ac_CreateContext( ctx );
413   _tnl_CreateContext( ctx );
414   _swsetup_CreateContext( ctx );
415   _ae_create_context( ctx );
416
417   /* Install the customized pipeline:
418    */
419   _tnl_destroy_pipeline( ctx );
420   _tnl_install_pipeline( ctx, r200_pipeline );
421   ctx->Driver.FlushVertices = r200FlushVertices;
422
423   /* Try and keep materials and vertices separate:
424    */
425   _tnl_isolate_materials( ctx, GL_TRUE );
426
427
428   /* Configure swrast and TNL to match hardware characteristics:
429    */
430   _swrast_allow_pixel_fog( ctx, GL_FALSE );
431   _swrast_allow_vertex_fog( ctx, GL_TRUE );
432   _tnl_allow_pixel_fog( ctx, GL_FALSE );
433   _tnl_allow_vertex_fog( ctx, GL_TRUE );
434
435
436   for ( i = 0 ; i < R200_MAX_TEXTURE_UNITS ; i++ ) {
437      _math_matrix_ctr( &rmesa->TexGenMatrix[i] );
438      _math_matrix_set_identity( &rmesa->TexGenMatrix[i] );
439   }
440   _math_matrix_ctr( &rmesa->tmpmat );
441   _math_matrix_set_identity( &rmesa->tmpmat );
442
443   driInitExtensions( ctx, card_extensions, GL_TRUE );
444   if (!(rmesa->r200Screen->chipset & R200_CHIPSET_YCBCR_BROKEN)) {
445     /* yuv textures don't work with some chips - R200 / rv280 okay so far
446	others get the bit ordering right but don't actually do YUV-RGB conversion */
447      _mesa_enable_extension( ctx, "GL_MESA_ycbcr_texture" );
448   }
449   if (rmesa->glCtx->Mesa_DXTn) {
450      _mesa_enable_extension( ctx, "GL_EXT_texture_compression_s3tc" );
451      _mesa_enable_extension( ctx, "GL_S3_s3tc" );
452   }
453   else if (driQueryOptionb (&rmesa->optionCache, "force_s3tc_enable")) {
454      _mesa_enable_extension( ctx, "GL_EXT_texture_compression_s3tc" );
455   }
456
457   if (rmesa->r200Screen->drmSupportsCubeMaps)
458      _mesa_enable_extension( ctx, "GL_ARB_texture_cube_map" );
459   if (rmesa->r200Screen->drmSupportsBlendColor) {
460       driInitExtensions( ctx, blend_extensions, GL_FALSE );
461   }
462   if(driQueryOptionb(&rmesa->optionCache, "arb_vertex_program"))
463      driInitSingleExtension( ctx, ARB_vp_extension );
464   if(driQueryOptionb(&rmesa->optionCache, "nv_vertex_program"))
465      driInitSingleExtension( ctx, NV_vp_extension );
466
467#if 0
468   r200InitDriverFuncs( ctx );
469   r200InitIoctlFuncs( ctx );
470   r200InitStateFuncs( ctx );
471   r200InitTextureFuncs( ctx );
472#endif
473   /* plug in a few more device driver functions */
474   /* XXX these should really go right after _mesa_init_driver_functions() */
475   r200InitPixelFuncs( ctx );
476   r200InitSpanFuncs( ctx );
477   r200InitTnlFuncs( ctx );
478   r200InitState( rmesa );
479   r200InitSwtcl( ctx );
480
481   fthrottle_mode = driQueryOptioni(&rmesa->optionCache, "fthrottle_mode");
482   rmesa->iw.irq_seq = -1;
483   rmesa->irqsEmitted = 0;
484   rmesa->do_irqs = (rmesa->dri.drmMinor >= 6 &&
485		     fthrottle_mode == DRI_CONF_FTHROTTLE_IRQS &&
486		     rmesa->r200Screen->irq);
487
488   rmesa->do_usleeps = (fthrottle_mode == DRI_CONF_FTHROTTLE_USLEEPS);
489
490   if (!rmesa->do_irqs)
491      fprintf(stderr,
492	      "IRQ's not enabled, falling back to %s: %d %d %d\n",
493	      rmesa->do_usleeps ? "usleeps" : "busy waits",
494	      rmesa->dri.drmMinor,
495	      fthrottle_mode,
496	      rmesa->r200Screen->irq);
497
498   rmesa->vblank_flags = (rmesa->r200Screen->irq != 0)
499       ? driGetDefaultVBlankFlags(&rmesa->optionCache) : VBLANK_FLAG_NO_IRQ;
500
501   rmesa->prefer_gart_client_texturing =
502      (getenv("R200_GART_CLIENT_TEXTURES") != 0);
503
504   (*dri_interface->getUST)( & rmesa->swap_ust );
505
506
507#if DO_DEBUG
508   R200_DEBUG  = driParseDebugString( getenv( "R200_DEBUG" ),
509				      debug_control );
510   R200_DEBUG |= driParseDebugString( getenv( "RADEON_DEBUG" ),
511				      debug_control );
512#endif
513
514   tcl_mode = driQueryOptioni(&rmesa->optionCache, "tcl_mode");
515   if (driQueryOptionb(&rmesa->optionCache, "no_rast")) {
516      fprintf(stderr, "disabling 3D acceleration\n");
517      FALLBACK(rmesa, R200_FALLBACK_DISABLE, 1);
518   }
519   else if (tcl_mode == DRI_CONF_TCL_SW || getenv("R200_NO_TCL") ||
520	    !(rmesa->r200Screen->chipset & R200_CHIPSET_TCL)) {
521      if (rmesa->r200Screen->chipset & R200_CHIPSET_TCL) {
522	 rmesa->r200Screen->chipset &= ~R200_CHIPSET_TCL;
523	 fprintf(stderr, "Disabling HW TCL support\n");
524      }
525      TCL_FALLBACK(rmesa->glCtx, R200_TCL_FALLBACK_TCL_DISABLE, 1);
526   }
527   if (rmesa->r200Screen->chipset & R200_CHIPSET_TCL) {
528      if (tcl_mode >= DRI_CONF_TCL_VTXFMT && !getenv("R200_NO_VTXFMT")) {
529	 r200VtxfmtInit( ctx, tcl_mode >= DRI_CONF_TCL_CODEGEN );
530      }
531      _tnl_need_dlist_norm_lengths( ctx, GL_FALSE );
532   }
533   return GL_TRUE;
534}
535
536
537/* Destroy the device specific context.
538 */
539/* Destroy the Mesa and driver specific context data.
540 */
541void r200DestroyContext( __DRIcontextPrivate *driContextPriv )
542{
543   GET_CURRENT_CONTEXT(ctx);
544   r200ContextPtr rmesa = (r200ContextPtr) driContextPriv->driverPrivate;
545   r200ContextPtr current = ctx ? R200_CONTEXT(ctx) : NULL;
546
547   /* check if we're deleting the currently bound context */
548   if (rmesa == current) {
549      R200_FIREVERTICES( rmesa );
550      _mesa_make_current(NULL, NULL, NULL);
551   }
552
553   /* Free r200 context resources */
554   assert(rmesa); /* should never be null */
555   if ( rmesa ) {
556      GLboolean   release_texture_heaps;
557
558
559      release_texture_heaps = (rmesa->glCtx->Shared->RefCount == 1);
560      _swsetup_DestroyContext( rmesa->glCtx );
561      _tnl_DestroyContext( rmesa->glCtx );
562      _ac_DestroyContext( rmesa->glCtx );
563      _swrast_DestroyContext( rmesa->glCtx );
564
565      r200DestroySwtcl( rmesa->glCtx );
566      r200ReleaseArrays( rmesa->glCtx, ~0 );
567
568      if (rmesa->dma.current.buf) {
569	 r200ReleaseDmaRegion( rmesa, &rmesa->dma.current, __FUNCTION__ );
570	 r200FlushCmdBuf( rmesa, __FUNCTION__ );
571      }
572
573      if (!(rmesa->TclFallback & R200_TCL_FALLBACK_TCL_DISABLE)) {
574	 int tcl_mode = driQueryOptioni(&rmesa->optionCache, "tcl_mode");
575	 if (tcl_mode >= DRI_CONF_TCL_VTXFMT)
576	    r200VtxfmtDestroy( rmesa->glCtx );
577      }
578
579      /* free the Mesa context */
580      rmesa->glCtx->DriverCtx = NULL;
581      _mesa_destroy_context( rmesa->glCtx );
582
583      if (rmesa->state.scissor.pClipRects) {
584	 FREE(rmesa->state.scissor.pClipRects);
585	 rmesa->state.scissor.pClipRects = NULL;
586      }
587
588      if ( release_texture_heaps ) {
589         /* This share group is about to go away, free our private
590          * texture object data.
591          */
592         int i;
593
594         for ( i = 0 ; i < rmesa->nr_heaps ; i++ ) {
595	    driDestroyTextureHeap( rmesa->texture_heaps[ i ] );
596	    rmesa->texture_heaps[ i ] = NULL;
597         }
598
599	 assert( is_empty_list( & rmesa->swapped ) );
600      }
601
602      /* free the option cache */
603      driDestroyOptionCache (&rmesa->optionCache);
604
605      FREE( rmesa );
606   }
607}
608
609
610
611
612void
613r200SwapBuffers( __DRIdrawablePrivate *dPriv )
614{
615   if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
616      r200ContextPtr rmesa;
617      GLcontext *ctx;
618      rmesa = (r200ContextPtr) dPriv->driContextPriv->driverPrivate;
619      ctx = rmesa->glCtx;
620      if (ctx->Visual.doubleBufferMode) {
621         _mesa_notifySwapBuffers( ctx );  /* flush pending rendering comands */
622         if ( rmesa->doPageFlip ) {
623            r200PageFlip( dPriv );
624         }
625         else {
626            r200CopyBuffer( dPriv );
627         }
628      }
629   }
630   else {
631      /* XXX this shouldn't be an error but we can't handle it for now */
632      _mesa_problem(NULL, "%s: drawable has no context!", __FUNCTION__);
633   }
634}
635
636
637/* Force the context `c' to be the current context and associate with it
638 * buffer `b'.
639 */
640GLboolean
641r200MakeCurrent( __DRIcontextPrivate *driContextPriv,
642                   __DRIdrawablePrivate *driDrawPriv,
643                   __DRIdrawablePrivate *driReadPriv )
644{
645   if ( driContextPriv ) {
646      r200ContextPtr newCtx =
647	 (r200ContextPtr) driContextPriv->driverPrivate;
648
649      if (R200_DEBUG & DEBUG_DRI)
650	 fprintf(stderr, "%s ctx %p\n", __FUNCTION__, (void *)newCtx->glCtx);
651
652      if ( newCtx->dri.drawable != driDrawPriv ) {
653	 driDrawableInitVBlank( driDrawPriv, newCtx->vblank_flags );
654	 newCtx->dri.drawable = driDrawPriv;
655	 r200UpdateWindow( newCtx->glCtx );
656	 r200UpdateViewportOffset( newCtx->glCtx );
657      }
658
659      _mesa_make_current( newCtx->glCtx,
660			  (GLframebuffer *) driDrawPriv->driverPrivate,
661			  (GLframebuffer *) driReadPriv->driverPrivate );
662
663      if (newCtx->vb.enabled)
664	 r200VtxfmtMakeCurrent( newCtx->glCtx );
665
666      _mesa_update_state( newCtx->glCtx );
667      r200ValidateState( newCtx->glCtx );
668
669   } else {
670      if (R200_DEBUG & DEBUG_DRI)
671	 fprintf(stderr, "%s ctx is null\n", __FUNCTION__);
672      _mesa_make_current( NULL, NULL, NULL );
673   }
674
675   if (R200_DEBUG & DEBUG_DRI)
676      fprintf(stderr, "End %s\n", __FUNCTION__);
677   return GL_TRUE;
678}
679
680/* Force the context `c' to be unbound from its buffer.
681 */
682GLboolean
683r200UnbindContext( __DRIcontextPrivate *driContextPriv )
684{
685   r200ContextPtr rmesa = (r200ContextPtr) driContextPriv->driverPrivate;
686
687   if (R200_DEBUG & DEBUG_DRI)
688      fprintf(stderr, "%s ctx %p\n", __FUNCTION__, (void *)rmesa->glCtx);
689
690   r200VtxfmtUnbindContext( rmesa->glCtx );
691   return GL_TRUE;
692}
693