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