r200_context.c revision 57c9814b9e87924696df4c741861c29d4236d1eb
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 "state.h"
44
45#include "swrast/swrast.h"
46#include "swrast_setup/swrast_setup.h"
47#include "array_cache/acache.h"
48
49#include "tnl/tnl.h"
50#include "tnl/t_pipeline.h"
51
52#include "r200_context.h"
53#include "r200_ioctl.h"
54#include "r200_state.h"
55#include "r200_span.h"
56#include "r200_pixel.h"
57#include "r200_tex.h"
58#include "r200_swtcl.h"
59#include "r200_tcl.h"
60#include "r200_vtxfmt.h"
61#include "r200_maos.h"
62
63#define DRIVER_DATE	"20030328"
64
65#include "vblank.h"
66#include "utils.h"
67#ifndef R200_DEBUG
68int R200_DEBUG = (0);
69#endif
70
71/* R200 configuration
72 */
73#include "xmlpool.h"
74
75
76const char __driConfigOptions[] =
77DRI_CONF_BEGIN
78    DRI_CONF_SECTION_PERFORMANCE
79        DRI_CONF_TCL_MODE(DRI_CONF_TCL_CODEGEN)
80        DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS)
81        DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
82    DRI_CONF_SECTION_END
83    DRI_CONF_SECTION_QUALITY
84        DRI_CONF_PREFERRED_BPT(0,"0,16,32")
85    DRI_CONF_SECTION_END
86    DRI_CONF_SECTION_DEBUG
87        DRI_CONF_NO_RAST(false)
88    DRI_CONF_SECTION_END
89DRI_CONF_END;
90const GLuint __driNConfigOptions = 5;
91
92/* Return the width and height of the given buffer.
93 */
94static void r200GetBufferSize( GLframebuffer *buffer,
95			       GLuint *width, GLuint *height )
96{
97   GET_CURRENT_CONTEXT(ctx);
98   r200ContextPtr rmesa = R200_CONTEXT(ctx);
99
100   LOCK_HARDWARE( rmesa );
101   *width  = rmesa->dri.drawable->w;
102   *height = rmesa->dri.drawable->h;
103   UNLOCK_HARDWARE( rmesa );
104}
105
106/* Return various strings for glGetString().
107 */
108static const GLubyte *r200GetString( GLcontext *ctx, GLenum name )
109{
110   r200ContextPtr rmesa = R200_CONTEXT(ctx);
111   static char buffer[128];
112   unsigned   offset;
113   GLuint agp_mode = rmesa->r200Screen->IsPCI ? 0 :
114      rmesa->r200Screen->AGPMode;
115
116   switch ( name ) {
117   case GL_VENDOR:
118      return (GLubyte *)"Tungsten Graphics, Inc.";
119
120   case GL_RENDERER:
121      offset = driGetRendererString( buffer, "R200", DRIVER_DATE,
122				     agp_mode );
123
124      sprintf( & buffer[ offset ], " %sTCL",
125	       !(rmesa->TclFallback & R200_TCL_FALLBACK_TCL_DISABLE)
126	       ? "" : "NO-" );
127
128      return (GLubyte *)buffer;
129
130   default:
131      return NULL;
132   }
133}
134
135
136/* Extension strings exported by the R200 driver.
137 */
138static const char * const card_extensions[] =
139{
140    "GL_ARB_multisample",
141    "GL_ARB_multitexture",
142    "GL_ARB_texture_border_clamp",
143    "GL_ARB_texture_compression",
144    "GL_ARB_texture_env_add",
145    "GL_ARB_texture_env_combine",
146    "GL_ARB_texture_env_dot3",
147    "GL_ARB_texture_mirrored_repeat",
148    "GL_EXT_blend_logic_op",
149    "GL_EXT_blend_minmax",
150    "GL_EXT_blend_subtract",
151    "GL_EXT_secondary_color",
152    "GL_EXT_stencil_wrap",
153    "GL_EXT_texture_edge_clamp",
154    "GL_EXT_texture_env_add",
155    "GL_EXT_texture_env_combine",
156    "GL_EXT_texture_env_dot3",
157    "GL_EXT_texture_filter_anisotropic",
158    "GL_EXT_texture_lod_bias",
159    "GL_ATI_texture_env_combine3",
160    "GL_ATI_texture_mirror_once",
161    "GL_IBM_texture_mirrored_repeat",
162    "GL_MESA_pack_invert",
163    "GL_MESA_ycbcr_texture",
164    "GL_NV_blend_square",
165    "GL_NV_texture_rectangle",
166    "GL_SGIS_generate_mipmap",
167    "GL_SGIS_texture_border_clamp",
168    "GL_SGIS_texture_edge_clamp",
169    NULL
170};
171
172extern const struct tnl_pipeline_stage _r200_render_stage;
173extern const struct tnl_pipeline_stage _r200_tcl_stage;
174
175static const struct tnl_pipeline_stage *r200_pipeline[] = {
176
177   /* Try and go straight to t&l
178    */
179   &_r200_tcl_stage,
180
181   /* Catch any t&l fallbacks
182    */
183   &_tnl_vertex_transform_stage,
184   &_tnl_normal_transform_stage,
185   &_tnl_lighting_stage,
186   &_tnl_fog_coordinate_stage,
187   &_tnl_texgen_stage,
188   &_tnl_texture_transform_stage,
189
190   /* Try again to go to tcl?
191    *     - no good for asymmetric-twoside (do with multipass)
192    *     - no good for asymmetric-unfilled (do with multipass)
193    *     - good for material
194    *     - good for texgen
195    *     - need to manipulate a bit of state
196    *
197    * - worth it/not worth it?
198    */
199
200   /* Else do them here.
201    */
202/*    &_r200_render_stage,  */ /* FIXME: bugs with ut2003 */
203   &_tnl_render_stage,		/* FALLBACK:  */
204   0,
205};
206
207
208
209/* Initialize the driver's misc functions.
210 */
211static void r200InitDriverFuncs( GLcontext *ctx )
212{
213    ctx->Driver.GetBufferSize		= r200GetBufferSize;
214    ctx->Driver.ResizeBuffers           = _swrast_alloc_buffers;
215    ctx->Driver.GetString		= r200GetString;
216
217    ctx->Driver.Error			= NULL;
218    ctx->Driver.DrawPixels		= NULL;
219    ctx->Driver.Bitmap			= NULL;
220}
221
222static const struct dri_debug_control debug_control[] =
223{
224    { "fall",  DEBUG_FALLBACKS },
225    { "tex",   DEBUG_TEXTURE },
226    { "ioctl", DEBUG_IOCTL },
227    { "prim",  DEBUG_PRIMS },
228    { "vert",  DEBUG_VERTS },
229    { "state", DEBUG_STATE },
230    { "code",  DEBUG_CODEGEN },
231    { "vfmt",  DEBUG_VFMT },
232    { "vtxf",  DEBUG_VFMT },
233    { "verb",  DEBUG_VERBOSE },
234    { "dri",   DEBUG_DRI },
235    { "dma",   DEBUG_DMA },
236    { "san",   DEBUG_SANITY },
237    { "sync",  DEBUG_SYNC },
238    { "pix",   DEBUG_PIXEL },
239    { "mem",   DEBUG_MEMORY },
240    { NULL,    0 }
241};
242
243
244static int
245get_ust_nop( uint64_t * ust )
246{
247   *ust = 1;
248   return 0;
249}
250
251
252/* Create the device specific 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   r200ContextPtr rmesa;
261   GLcontext *ctx, *shareCtx;
262   int i;
263   int tcl_mode, fthrottle_mode, preferred_bpt;
264
265   assert(glVisual);
266   assert(driContextPriv);
267   assert(screen);
268
269   /* Allocate the R200 context */
270   rmesa = (r200ContextPtr) CALLOC( sizeof(*rmesa) );
271   if ( !rmesa )
272      return GL_FALSE;
273
274   /* Allocate the Mesa context */
275   if (sharedContextPrivate)
276      shareCtx = ((r200ContextPtr) sharedContextPrivate)->glCtx;
277   else
278      shareCtx = NULL;
279   rmesa->glCtx = _mesa_create_context(glVisual, shareCtx, (void *) rmesa, GL_TRUE);
280   if (!rmesa->glCtx) {
281      FREE(rmesa);
282      return GL_FALSE;
283   }
284   driContextPriv->driverPrivate = rmesa;
285
286   /* Init r200 context data */
287   rmesa->dri.context = driContextPriv;
288   rmesa->dri.screen = sPriv;
289   rmesa->dri.drawable = NULL; /* Set by XMesaMakeCurrent */
290   rmesa->dri.hwContext = driContextPriv->hHWContext;
291   rmesa->dri.hwLock = &sPriv->pSAREA->lock;
292   rmesa->dri.fd = sPriv->fd;
293   rmesa->dri.drmMinor = sPriv->drmMinor;
294
295   /* Parse configuration files */
296   driParseConfigFiles (&rmesa->optionCache, &screen->optionCache,
297			screen->driScreen->myNum, "r200");
298   rmesa->r200Screen = screen;
299   rmesa->sarea = (RADEONSAREAPrivPtr)((GLubyte *)sPriv->pSAREA +
300				       screen->sarea_priv_offset);
301
302
303   rmesa->dma.buf0_address = rmesa->r200Screen->buffers->list[0].address;
304
305   (void) memset( rmesa->texture_heaps, 0, sizeof( rmesa->texture_heaps ) );
306   make_empty_list( & rmesa->swapped );
307
308   rmesa->nr_heaps = 1 /* screen->numTexHeaps */ ;
309   for ( i = 0 ; i < rmesa->nr_heaps ; i++ ) {
310      rmesa->texture_heaps[i] = driCreateTextureHeap( i, rmesa,
311	    screen->texSize[i],
312	    12,
313	    RADEON_NR_TEX_REGIONS,
314	    rmesa->sarea->texList[i],
315	    & rmesa->sarea->texAge[i],
316	    & rmesa->swapped,
317	    sizeof( r200TexObj ),
318	    (destroy_texture_object_t *) r200DestroyTexObj );
319   }
320   preferred_bpt = driQueryOptioni (&rmesa->optionCache, "preferred_bpt");
321   rmesa->default32BitTextures =
322       ( ( preferred_bpt == 0 && screen->cpp == 4 ) || preferred_bpt == 32 );
323
324   rmesa->swtcl.RenderIndex = ~0;
325   rmesa->lost_context = 1;
326
327   /* Set the maximum texture size small enough that we can guarentee that
328    * all texture units can bind a maximal texture and have them both in
329    * texturable memory at once.
330    */
331
332   ctx = rmesa->glCtx;
333   ctx->Const.MaxTextureUnits = 2;
334
335   driCalculateMaxTextureLevels( rmesa->texture_heaps,
336				 rmesa->nr_heaps,
337				 & ctx->Const,
338				 4,
339				 11, /* max 2D texture size is 2048x2048 */
340#if ENABLE_HW_3D_TEXTURE
341				 8,  /* max 3D texture size is 256^3 */
342#else
343				 0,  /* 3D textures unsupported */
344#endif
345				 11, /* max cube texture size is 2048x2048 */
346				 11, /* max texture rectangle size is 2048x2048 */
347				 12,
348				 GL_FALSE );
349
350   ctx->Const.MaxTextureMaxAnisotropy = 16.0;
351
352   /* No wide points.
353    */
354   ctx->Const.MinPointSize = 1.0;
355   ctx->Const.MinPointSizeAA = 1.0;
356   ctx->Const.MaxPointSize = 1.0;
357   ctx->Const.MaxPointSizeAA = 1.0;
358
359   ctx->Const.MinLineWidth = 1.0;
360   ctx->Const.MinLineWidthAA = 1.0;
361   ctx->Const.MaxLineWidth = 10.0;
362   ctx->Const.MaxLineWidthAA = 10.0;
363   ctx->Const.LineWidthGranularity = 0.0625;
364
365   /* Initialize the software rasterizer and helper modules.
366    */
367   _swrast_CreateContext( ctx );
368   _ac_CreateContext( ctx );
369   _tnl_CreateContext( ctx );
370   _swsetup_CreateContext( ctx );
371   _ae_create_context( ctx );
372
373   /* Install the customized pipeline:
374    */
375   _tnl_destroy_pipeline( ctx );
376   _tnl_install_pipeline( ctx, r200_pipeline );
377   ctx->Driver.FlushVertices = r200FlushVertices;
378
379   /* Try and keep materials and vertices separate:
380    */
381   _tnl_isolate_materials( ctx, GL_TRUE );
382
383
384   /* Configure swrast to match hardware characteristics:
385    */
386   _swrast_allow_pixel_fog( ctx, GL_FALSE );
387   _swrast_allow_vertex_fog( ctx, GL_TRUE );
388
389
390   _math_matrix_ctr( &rmesa->TexGenMatrix[0] );
391   _math_matrix_ctr( &rmesa->TexGenMatrix[1] );
392   _math_matrix_ctr( &rmesa->tmpmat );
393   _math_matrix_set_identity( &rmesa->TexGenMatrix[0] );
394   _math_matrix_set_identity( &rmesa->TexGenMatrix[1] );
395   _math_matrix_set_identity( &rmesa->tmpmat );
396
397   driInitExtensions( ctx, card_extensions, GL_TRUE );
398   if (rmesa->r200Screen->drmSupportsCubeMaps)
399      _mesa_enable_extension( ctx, "GL_ARB_texture_cube_map" );
400
401   r200InitDriverFuncs( ctx );
402   r200InitIoctlFuncs( ctx );
403   r200InitStateFuncs( ctx );
404   r200InitSpanFuncs( ctx );
405   r200InitPixelFuncs( ctx );
406   r200InitTextureFuncs( ctx );
407   r200InitState( rmesa );
408   r200InitSwtcl( ctx );
409
410   fthrottle_mode = driQueryOptioni(&rmesa->optionCache, "fthrottle_mode");
411   rmesa->iw.irq_seq = -1;
412   rmesa->irqsEmitted = 0;
413   rmesa->do_irqs = (rmesa->dri.drmMinor >= 6 &&
414		     fthrottle_mode == DRI_CONF_FTHROTTLE_IRQS &&
415		     rmesa->r200Screen->irq);
416
417   rmesa->do_usleeps = (fthrottle_mode == DRI_CONF_FTHROTTLE_USLEEPS);
418
419   if (!rmesa->do_irqs)
420      fprintf(stderr,
421	      "IRQ's not enabled, falling back to %s: %d %d %d\n",
422	      rmesa->do_usleeps ? "usleeps" : "busy waits",
423	      rmesa->dri.drmMinor,
424	      fthrottle_mode,
425	      rmesa->r200Screen->irq);
426
427   rmesa->vblank_flags = (rmesa->r200Screen->irq != 0)
428       ? driGetDefaultVBlankFlags(&rmesa->optionCache) : VBLANK_FLAG_NO_IRQ;
429
430   rmesa->prefer_gart_client_texturing =
431      (getenv("R200_GART_CLIENT_TEXTURES") != 0);
432#ifndef _SOLO
433   rmesa->get_ust = (PFNGLXGETUSTPROC) glXGetProcAddress( (const GLubyte *) "__glXGetUST" );
434   if ( rmesa->get_ust == NULL ) {
435      rmesa->get_ust = get_ust_nop;
436   }
437#else
438   rmesa->get_ust = get_ust_nop;
439#endif
440   (*rmesa->get_ust)( & rmesa->swap_ust );
441
442
443#if DO_DEBUG
444   R200_DEBUG  = driParseDebugString( getenv( "R200_DEBUG" ),
445				      debug_control );
446   R200_DEBUG |= driParseDebugString( getenv( "RADEON_DEBUG" ),
447				      debug_control );
448#endif
449
450   tcl_mode = driQueryOptioni(&rmesa->optionCache, "tcl_mode");
451   if (driQueryOptionb(&rmesa->optionCache, "no_rast")) {
452      fprintf(stderr, "disabling 3D acceleration\n");
453      FALLBACK(rmesa, R200_FALLBACK_DISABLE, 1);
454   }
455   else if (tcl_mode == DRI_CONF_TCL_SW) {
456      fprintf(stderr, "disabling TCL support\n");
457      TCL_FALLBACK(rmesa->glCtx, R200_TCL_FALLBACK_TCL_DISABLE, 1);
458   }
459   else {
460      if (tcl_mode >= DRI_CONF_TCL_VTXFMT) {
461	 r200VtxfmtInit( ctx, tcl_mode >= DRI_CONF_TCL_CODEGEN );
462      }
463      _tnl_need_dlist_norm_lengths( ctx, GL_FALSE );
464   }
465   return GL_TRUE;
466}
467
468
469/* Destroy the device specific context.
470 */
471/* Destroy the Mesa and driver specific context data.
472 */
473void r200DestroyContext( __DRIcontextPrivate *driContextPriv )
474{
475   GET_CURRENT_CONTEXT(ctx);
476   r200ContextPtr rmesa = (r200ContextPtr) driContextPriv->driverPrivate;
477   r200ContextPtr current = ctx ? R200_CONTEXT(ctx) : NULL;
478
479   /* check if we're deleting the currently bound context */
480   if (rmesa == current) {
481      R200_FIREVERTICES( rmesa );
482      _mesa_make_current2(NULL, NULL, NULL);
483   }
484
485   /* Free r200 context resources */
486   assert(rmesa); /* should never be null */
487   if ( rmesa ) {
488      GLboolean   release_texture_heaps;
489
490
491      release_texture_heaps = (rmesa->glCtx->Shared->RefCount == 1);
492      _swsetup_DestroyContext( rmesa->glCtx );
493      _tnl_DestroyContext( rmesa->glCtx );
494      _ac_DestroyContext( rmesa->glCtx );
495      _swrast_DestroyContext( rmesa->glCtx );
496
497      r200DestroySwtcl( rmesa->glCtx );
498      r200ReleaseArrays( rmesa->glCtx, ~0 );
499
500      if (rmesa->dma.current.buf) {
501	 r200ReleaseDmaRegion( rmesa, &rmesa->dma.current, __FUNCTION__ );
502	 r200FlushCmdBuf( rmesa, __FUNCTION__ );
503      }
504
505      if (!(rmesa->TclFallback & R200_TCL_FALLBACK_TCL_DISABLE)) {
506	 int tcl_mode = driQueryOptioni(&rmesa->optionCache, "tcl_mode");
507	 if (tcl_mode >= DRI_CONF_TCL_VTXFMT)
508	    r200VtxfmtDestroy( rmesa->glCtx );
509      }
510
511      /* free the Mesa context */
512      rmesa->glCtx->DriverCtx = NULL;
513      _mesa_destroy_context( rmesa->glCtx );
514
515      if (rmesa->state.scissor.pClipRects) {
516	 FREE(rmesa->state.scissor.pClipRects);
517	 rmesa->state.scissor.pClipRects = 0;
518      }
519
520      if ( release_texture_heaps ) {
521         /* This share group is about to go away, free our private
522          * texture object data.
523          */
524         int i;
525
526	 /* this assert is wrong. The default textures are always on swap list
527	 assert( is_empty_list( & rmesa->swapped ) ); */
528
529         for ( i = 0 ; i < rmesa->nr_heaps ; i++ ) {
530	    driDestroyTextureHeap( rmesa->texture_heaps[ i ] );
531	    rmesa->texture_heaps[ i ] = NULL;
532         }
533      }
534
535      /* free the option cache */
536      driDestroyOptionCache (&rmesa->optionCache);
537
538      FREE( rmesa );
539   }
540}
541
542
543
544
545void
546r200SwapBuffers( __DRIdrawablePrivate *dPriv )
547{
548   if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
549      r200ContextPtr rmesa;
550      GLcontext *ctx;
551      rmesa = (r200ContextPtr) dPriv->driContextPriv->driverPrivate;
552      ctx = rmesa->glCtx;
553      if (ctx->Visual.doubleBufferMode) {
554         _mesa_notifySwapBuffers( ctx );  /* flush pending rendering comands */
555         if ( rmesa->doPageFlip ) {
556            r200PageFlip( dPriv );
557         }
558         else {
559            r200CopyBuffer( dPriv );
560         }
561      }
562   }
563   else {
564      /* XXX this shouldn't be an error but we can't handle it for now */
565      _mesa_problem(NULL, "%s: drawable has no context!", __FUNCTION__);
566   }
567}
568
569
570/* Force the context `c' to be the current context and associate with it
571 * buffer `b'.
572 */
573GLboolean
574r200MakeCurrent( __DRIcontextPrivate *driContextPriv,
575                   __DRIdrawablePrivate *driDrawPriv,
576                   __DRIdrawablePrivate *driReadPriv )
577{
578   if ( driContextPriv ) {
579      r200ContextPtr newCtx =
580	 (r200ContextPtr) driContextPriv->driverPrivate;
581
582      if (R200_DEBUG & DEBUG_DRI)
583	 fprintf(stderr, "%s ctx %p\n", __FUNCTION__, newCtx->glCtx);
584
585      if ( newCtx->dri.drawable != driDrawPriv ) {
586	 driDrawableInitVBlank( driDrawPriv, newCtx->vblank_flags );
587	 newCtx->dri.drawable = driDrawPriv;
588	 r200UpdateWindow( newCtx->glCtx );
589	 r200UpdateViewportOffset( newCtx->glCtx );
590      }
591
592      _mesa_make_current2( newCtx->glCtx,
593			   (GLframebuffer *) driDrawPriv->driverPrivate,
594			   (GLframebuffer *) driReadPriv->driverPrivate );
595
596      if ( !newCtx->glCtx->Viewport.Width ) {
597	 _mesa_set_viewport( newCtx->glCtx, 0, 0,
598			     driDrawPriv->w, driDrawPriv->h );
599      }
600
601      if (newCtx->vb.enabled)
602	 r200VtxfmtMakeCurrent( newCtx->glCtx );
603
604      _mesa_update_state( newCtx->glCtx );
605      r200ValidateState( newCtx->glCtx );
606
607   } else {
608      if (R200_DEBUG & DEBUG_DRI)
609	 fprintf(stderr, "%s ctx is null\n", __FUNCTION__);
610      _mesa_make_current( 0, 0 );
611   }
612
613   if (R200_DEBUG & DEBUG_DRI)
614      fprintf(stderr, "End %s\n", __FUNCTION__);
615   return GL_TRUE;
616}
617
618/* Force the context `c' to be unbound from its buffer.
619 */
620GLboolean
621r200UnbindContext( __DRIcontextPrivate *driContextPriv )
622{
623   r200ContextPtr rmesa = (r200ContextPtr) driContextPriv->driverPrivate;
624
625   if (R200_DEBUG & DEBUG_DRI)
626      fprintf(stderr, "%s ctx %p\n", __FUNCTION__, rmesa->glCtx);
627
628   r200VtxfmtUnbindContext( rmesa->glCtx );
629   return GL_TRUE;
630}
631