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