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