bring over latest mga DRI driver from DRI trunk
[mesa.git] / src / mesa / drivers / dri / mga / mga_xmesa.c
1 /* $XFree86: xc/lib/GL/mesa/src/drv/mga/mga_xmesa.c,v 1.19 2003/03/26 20:43:49 tsi Exp $ */
2 /*
3 * Copyright 2000-2001 VA Linux Systems, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * on the rights to use, copy, modify, merge, publish, distribute, sub
10 * license, and/or sell copies of the Software, and to permit persons to whom
11 * the Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
20 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * OTHER DEALINGS IN THE SOFTWARE.
24 *
25 * Authors:
26 * Keith Whitwell <keith@tungstengraphics.com>
27 */
28
29 #include "mga_common.h"
30 #include "mga_xmesa.h"
31 #include "context.h"
32 #include "matrix.h"
33 #include "simple_list.h"
34 #include "imports.h"
35
36 #include "swrast/swrast.h"
37 #include "swrast_setup/swrast_setup.h"
38 #include "tnl/tnl.h"
39 #include "array_cache/acache.h"
40
41 #include "tnl/t_pipeline.h"
42
43 #include "mgadd.h"
44 #include "mgastate.h"
45 #include "mgatex.h"
46 #include "mgaspan.h"
47 #include "mgaioctl.h"
48 #include "mgatris.h"
49 #include "mgavb.h"
50 #include "mgapixel.h"
51 #include "mga_xmesa.h"
52 #include "mga_dri.h"
53
54
55 #include "utils.h"
56 #include "vblank.h"
57
58 #ifndef _SOLO
59 #include "glxextensions.h"
60 #endif
61
62 /* MGA configuration
63 */
64 #include "xmlpool.h"
65
66 const char __driConfigOptions[] =
67 DRI_CONF_BEGIN
68 DRI_CONF_SECTION_PERFORMANCE
69 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
70 DRI_CONF_SECTION_END
71 DRI_CONF_SECTION_QUALITY
72 DRI_CONF_TEXTURE_DEPTH(DRI_CONF_TEXTURE_DEPTH_FB)
73 DRI_CONF_COLOR_REDUCTION(DRI_CONF_COLOR_REDUCTION_DITHER)
74 DRI_CONF_SECTION_END
75 DRI_CONF_END;
76 const GLuint __driNConfigOptions = 3;
77
78 #ifndef MGA_DEBUG
79 int MGA_DEBUG = 0;
80 #endif
81
82 static int getSwapInfo( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo );
83
84 static GLboolean
85 mgaInitDriver(__DRIscreenPrivate *sPriv)
86 {
87 mgaScreenPrivate *mgaScreen;
88 MGADRIPtr serverInfo = (MGADRIPtr)sPriv->pDevPriv;
89
90 if ( ! driCheckDriDdxDrmVersions( sPriv, "MGA", 4, 0, 1, 0, 3, 0 ) )
91 return GL_FALSE;
92
93 /* Allocate the private area */
94 mgaScreen = (mgaScreenPrivate *)MALLOC(sizeof(mgaScreenPrivate));
95 if (!mgaScreen) {
96 __driUtilMessage("Couldn't malloc screen struct");
97 return GL_FALSE;
98 }
99
100 mgaScreen->sPriv = sPriv;
101 sPriv->private = (void *)mgaScreen;
102
103 if (sPriv->drmMinor >= 1) {
104 int ret;
105 drmMGAGetParam gp;
106
107 gp.param = MGA_PARAM_IRQ_NR;
108 gp.value = &mgaScreen->irq;
109
110 ret = drmCommandWriteRead( sPriv->fd, DRM_MGA_GETPARAM,
111 &gp, sizeof(gp));
112 if (ret) {
113 fprintf(stderr, "drmMgaGetParam (MGA_PARAM_IRQ_NR): %d\n", ret);
114 FREE(mgaScreen);
115 sPriv->private = NULL;
116 return GL_FALSE;
117 }
118 }
119
120 mgaScreen->linecomp_sane = (sPriv->ddxMajor > 1) || (sPriv->ddxMinor > 1)
121 || ((sPriv->ddxMinor == 1) && (sPriv->ddxPatch > 0));
122 #ifndef _SOLO
123 if ( driCompareGLXAPIVersion( 20030813 ) >= 0 ) {
124 PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension =
125 (PFNGLXSCRENABLEEXTENSIONPROC) glXGetProcAddress( (const GLubyte *) "__glXScrEnableExtension" );
126 void * const psc = sPriv->psc->screenConfigs;
127
128 if ( glx_enable_extension != NULL ) {
129 if ( mgaScreen->linecomp_sane ) {
130 (*glx_enable_extension)( psc, "GLX_SGI_swap_control" );
131 (*glx_enable_extension)( psc, "GLX_SGI_video_sync" );
132 (*glx_enable_extension)( psc, "GLX_MESA_swap_control" );
133 }
134
135 (*glx_enable_extension)( psc, "GLX_SGI_make_current_read" );
136 (*glx_enable_extension)( psc, "GLX_MESA_swap_frame_usage" );
137 }
138 }
139 #endif
140
141 if (serverInfo->chipset != MGA_CARD_TYPE_G200 &&
142 serverInfo->chipset != MGA_CARD_TYPE_G400) {
143 FREE(mgaScreen);
144 sPriv->private = NULL;
145 __driUtilMessage("Unrecognized chipset");
146 return GL_FALSE;
147 }
148
149
150 mgaScreen->chipset = serverInfo->chipset;
151 mgaScreen->width = serverInfo->width;
152 mgaScreen->height = serverInfo->height;
153 mgaScreen->mem = serverInfo->mem;
154 mgaScreen->cpp = serverInfo->cpp;
155
156 mgaScreen->agpMode = serverInfo->agpMode;
157
158 mgaScreen->frontPitch = serverInfo->frontPitch;
159 mgaScreen->frontOffset = serverInfo->frontOffset;
160 mgaScreen->backOffset = serverInfo->backOffset;
161 mgaScreen->backPitch = serverInfo->backPitch;
162 mgaScreen->depthOffset = serverInfo->depthOffset;
163 mgaScreen->depthPitch = serverInfo->depthPitch;
164
165 mgaScreen->mmio.handle = serverInfo->registers.handle;
166 mgaScreen->mmio.size = serverInfo->registers.size;
167 if ( drmMap( sPriv->fd,
168 mgaScreen->mmio.handle, mgaScreen->mmio.size,
169 &mgaScreen->mmio.map ) < 0 ) {
170 FREE( mgaScreen );
171 sPriv->private = NULL;
172 __driUtilMessage( "Couldn't map MMIO registers" );
173 return GL_FALSE;
174 }
175
176 mgaScreen->primary.handle = serverInfo->primary.handle;
177 mgaScreen->primary.size = serverInfo->primary.size;
178 mgaScreen->buffers.handle = serverInfo->buffers.handle;
179 mgaScreen->buffers.size = serverInfo->buffers.size;
180
181 #if 0
182 mgaScreen->agp.handle = serverInfo->agp;
183 mgaScreen->agp.size = serverInfo->agpSize;
184
185 if (drmMap(sPriv->fd,
186 mgaScreen->agp.handle,
187 mgaScreen->agp.size,
188 (drmAddress *)&mgaScreen->agp.map) != 0)
189 {
190 Xfree(mgaScreen);
191 sPriv->private = NULL;
192 __driUtilMessage("Couldn't map agp region");
193 return GL_FALSE;
194 }
195 #endif
196
197 mgaScreen->textureOffset[MGA_CARD_HEAP] = serverInfo->textureOffset;
198 mgaScreen->textureOffset[MGA_AGP_HEAP] = (serverInfo->agpTextureOffset |
199 PDEA_pagpxfer_enable | 1);
200
201 mgaScreen->textureSize[MGA_CARD_HEAP] = serverInfo->textureSize;
202 mgaScreen->textureSize[MGA_AGP_HEAP] = serverInfo->agpTextureSize;
203
204 mgaScreen->logTextureGranularity[MGA_CARD_HEAP] =
205 serverInfo->logTextureGranularity;
206 mgaScreen->logTextureGranularity[MGA_AGP_HEAP] =
207 serverInfo->logAgpTextureGranularity;
208
209 mgaScreen->texVirtual[MGA_CARD_HEAP] = (char *)(mgaScreen->sPriv->pFB +
210 serverInfo->textureOffset);
211 if (drmMap(sPriv->fd,
212 serverInfo->agpTextureOffset,
213 serverInfo->agpTextureSize,
214 (drmAddress *)&mgaScreen->texVirtual[MGA_AGP_HEAP]) != 0)
215 {
216 FREE(mgaScreen);
217 sPriv->private = NULL;
218 __driUtilMessage("Couldn't map agptexture region");
219 return GL_FALSE;
220 }
221
222 #if 0
223 mgaScreen->texVirtual[MGA_AGP_HEAP] = (mgaScreen->agp.map +
224 serverInfo->agpTextureOffset);
225 #endif
226
227 mgaScreen->mAccess = serverInfo->mAccess;
228
229 /* For calculating setupdma addresses.
230 */
231 mgaScreen->dmaOffset = serverInfo->buffers.handle;
232
233 mgaScreen->bufs = drmMapBufs(sPriv->fd);
234 if (!mgaScreen->bufs) {
235 /*drmUnmap(mgaScreen->agp_tex.map, mgaScreen->agp_tex.size);*/
236 FREE(mgaScreen);
237 sPriv->private = NULL;
238 __driUtilMessage("Couldn't map dma buffers");
239 return GL_FALSE;
240 }
241 mgaScreen->sarea_priv_offset = serverInfo->sarea_priv_offset;
242
243 /* parse information in __driConfigOptions */
244 driParseOptionInfo (&mgaScreen->optionCache);
245
246 return GL_TRUE;
247 }
248
249
250 static void
251 mgaDestroyScreen(__DRIscreenPrivate *sPriv)
252 {
253 mgaScreenPrivate *mgaScreen = (mgaScreenPrivate *) sPriv->private;
254
255 if (MGA_DEBUG&DEBUG_VERBOSE_DRI)
256 fprintf(stderr, "mgaDestroyScreen\n");
257
258 /*drmUnmap(mgaScreen->agp_tex.map, mgaScreen->agp_tex.size);*/
259
260 /* free all option information */
261 driDestroyOptionInfo (&mgaScreen->optionCache);
262
263 FREE(mgaScreen);
264 sPriv->private = NULL;
265 }
266
267
268 extern const struct tnl_pipeline_stage _mga_render_stage;
269
270 static const struct tnl_pipeline_stage *mga_pipeline[] = {
271 &_tnl_vertex_transform_stage,
272 &_tnl_normal_transform_stage,
273 &_tnl_lighting_stage,
274 &_tnl_fog_coordinate_stage,
275 &_tnl_texgen_stage,
276 &_tnl_texture_transform_stage,
277 /* REMOVE: point attenuation stage */
278 #if 0
279 &_mga_render_stage, /* ADD: unclipped rastersetup-to-dma */
280 /* Need new ioctl for wacceptseq */
281 #endif
282 &_tnl_render_stage,
283 0,
284 };
285
286
287 static const char * const g400_extensions[] =
288 {
289 "GL_ARB_multitexture",
290 "GL_ARB_texture_env_add",
291 "GL_EXT_texture_env_add",
292 "GL_ARB_texture_env_combine",
293 "GL_EXT_texture_env_combine",
294 "GL_ARB_texture_env_crossbar",
295 "GL_ATI_texture_env_combine3",
296 "GL_EXT_texture_edge_clamp",
297 "GL_SGIS_texture_edge_clamp",
298 #if defined (MESA_packed_depth_stencil)
299 "GL_MESA_packed_depth_stencil",
300 #endif
301 NULL
302 };
303
304 static const char * const card_extensions[] =
305 {
306 "GL_ARB_multisample",
307 "GL_ARB_texture_compression",
308 "GL_EXT_blend_logic_op",
309 "GL_EXT_fog_coord",
310 /* paletted_textures currently doesn't work, but we could fix them later */
311 #if 0
312 "GL_EXT_shared_texture_palette",
313 "GL_EXT_paletted_texture",
314 #endif
315 "GL_EXT_secondary_color",
316 "GL_EXT_stencil_wrap",
317 "GL_MESA_ycbcr_texture",
318 "GL_SGIS_generate_mipmap",
319 "GL_SGIS_texture_lod",
320 "GL_NV_texture_rectangle",
321 NULL
322 };
323
324 static const struct dri_debug_control debug_control[] =
325 {
326 { "fall", DEBUG_VERBOSE_FALLBACK },
327 { "tex", DEBUG_VERBOSE_TEXTURE },
328 { "ioctl", DEBUG_VERBOSE_IOCTL },
329 { "verb", DEBUG_VERBOSE_MSG },
330 { "dri", DEBUG_VERBOSE_DRI },
331 { NULL, 0 }
332 };
333
334
335 static int
336 get_ust_nop( int64_t * ust )
337 {
338 *ust = 1;
339 return 0;
340 }
341
342
343 static GLboolean
344 mgaCreateContext( const __GLcontextModes *mesaVis,
345 __DRIcontextPrivate *driContextPriv,
346 void *sharedContextPrivate )
347 {
348 int i;
349 unsigned maxlevels;
350 GLcontext *ctx, *shareCtx;
351 mgaContextPtr mmesa;
352 __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
353 mgaScreenPrivate *mgaScreen = (mgaScreenPrivate *)sPriv->private;
354 MGASAREAPrivPtr saPriv=(MGASAREAPrivPtr)(((char*)sPriv->pSAREA)+
355 mgaScreen->sarea_priv_offset);
356
357 if (MGA_DEBUG&DEBUG_VERBOSE_DRI)
358 fprintf(stderr, "mgaCreateContext\n");
359
360 /* allocate mga context */
361 mmesa = (mgaContextPtr) CALLOC(sizeof(mgaContext));
362 if (!mmesa) {
363 return GL_FALSE;
364 }
365
366 /* Allocate the Mesa context */
367 if (sharedContextPrivate)
368 shareCtx = ((mgaContextPtr) sharedContextPrivate)->glCtx;
369 else
370 shareCtx = NULL;
371 mmesa->glCtx = _mesa_create_context(mesaVis, shareCtx, (void *) mmesa, GL_TRUE);
372 if (!mmesa->glCtx) {
373 FREE(mmesa);
374 return GL_FALSE;
375 }
376 driContextPriv->driverPrivate = mmesa;
377
378 /* Init mga state */
379 mmesa->hHWContext = driContextPriv->hHWContext;
380 mmesa->driFd = sPriv->fd;
381 mmesa->driHwLock = &sPriv->pSAREA->lock;
382
383 mmesa->mgaScreen = mgaScreen;
384 mmesa->driScreen = sPriv;
385 mmesa->sarea = (void *)saPriv;
386
387 /* Parse configuration files */
388 driParseConfigFiles (&mmesa->optionCache, &mgaScreen->optionCache,
389 sPriv->myNum, "mga");
390
391 (void) memset( mmesa->texture_heaps, 0, sizeof( mmesa->texture_heaps ) );
392 make_empty_list( & mmesa->swapped );
393
394 mmesa->nr_heaps = mgaScreen->texVirtual[MGA_AGP_HEAP] ? 2 : 1;
395 for ( i = 0 ; i < mmesa->nr_heaps ; i++ ) {
396 mmesa->texture_heaps[i] = driCreateTextureHeap( i, mmesa,
397 mgaScreen->textureSize[i],
398 6,
399 MGA_NR_TEX_REGIONS,
400 mmesa->sarea->texList[i],
401 & mmesa->sarea->texAge[i],
402 & mmesa->swapped,
403 sizeof( mgaTextureObject_t ),
404 (destroy_texture_object_t *) mgaDestroyTexObj );
405 }
406
407 /* Set the maximum texture size small enough that we can guarentee
408 * that both texture units can bind a maximal texture and have them
409 * on the card at once.
410 */
411 ctx = mmesa->glCtx;
412 if ( mgaScreen->chipset == MGA_CARD_TYPE_G200 ) {
413 ctx->Const.MaxTextureUnits = 1;
414 maxlevels = G200_TEX_MAXLEVELS;
415
416 }
417 else {
418 ctx->Const.MaxTextureUnits = 2;
419 maxlevels = G400_TEX_MAXLEVELS;
420 }
421
422 driCalculateMaxTextureLevels( mmesa->texture_heaps,
423 mmesa->nr_heaps,
424 & ctx->Const,
425 4,
426 11, /* max 2D texture size is 2048x2048 */
427 0, /* 3D textures unsupported. */
428 0, /* cube textures unsupported. */
429 11, /* max texture rect size is 2048x2048 */
430 maxlevels,
431 GL_FALSE );
432
433 ctx->Const.MinLineWidth = 1.0;
434 ctx->Const.MinLineWidthAA = 1.0;
435 ctx->Const.MaxLineWidth = 10.0;
436 ctx->Const.MaxLineWidthAA = 10.0;
437 ctx->Const.LineWidthGranularity = 1.0;
438
439 mmesa->texture_depth = driQueryOptioni (&mmesa->optionCache,
440 "texture_depth");
441 if (mmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FB)
442 mmesa->texture_depth = ( mesaVis->rgbBits >= 24 ) ?
443 DRI_CONF_TEXTURE_DEPTH_32 : DRI_CONF_TEXTURE_DEPTH_16;
444 mmesa->hw_stencil = mesaVis->stencilBits && mesaVis->depthBits == 24;
445
446 switch (mesaVis->depthBits) {
447 case 16:
448 mmesa->depth_scale = 1.0/(GLdouble)0xffff;
449 mmesa->depth_clear_mask = ~0;
450 mmesa->ClearDepth = 0xffff;
451 break;
452 case 24:
453 mmesa->depth_scale = 1.0/(GLdouble)0xffffff;
454 if (mmesa->hw_stencil) {
455 mmesa->depth_clear_mask = 0xffffff00;
456 mmesa->stencil_clear_mask = 0x000000ff;
457 } else
458 mmesa->depth_clear_mask = ~0;
459 mmesa->ClearDepth = 0xffffff00;
460 break;
461 case 32:
462 mmesa->depth_scale = 1.0/(GLdouble)0xffffffff;
463 mmesa->depth_clear_mask = ~0;
464 mmesa->ClearDepth = 0xffffffff;
465 break;
466 };
467
468 mmesa->haveHwStipple = GL_FALSE;
469 mmesa->RenderIndex = -1; /* impossible value */
470 mmesa->dirty = ~0;
471 mmesa->vertex_format = 0;
472 mmesa->CurrentTexObj[0] = 0;
473 mmesa->CurrentTexObj[1] = 0;
474 mmesa->tmu_source[0] = 0;
475 mmesa->tmu_source[1] = 1;
476
477 mmesa->texAge[0] = 0;
478 mmesa->texAge[1] = 0;
479
480 /* Initialize the software rasterizer and helper modules.
481 */
482 _swrast_CreateContext( ctx );
483 _ac_CreateContext( ctx );
484 _tnl_CreateContext( ctx );
485
486 _swsetup_CreateContext( ctx );
487
488 /* Install the customized pipeline:
489 */
490 _tnl_destroy_pipeline( ctx );
491 _tnl_install_pipeline( ctx, mga_pipeline );
492
493 /* Configure swrast to match hardware characteristics:
494 */
495 _swrast_allow_pixel_fog( ctx, GL_FALSE );
496 _swrast_allow_vertex_fog( ctx, GL_TRUE );
497
498 mmesa->primary_offset = mmesa->mgaScreen->primary.handle;
499
500 ctx->DriverCtx = (void *) mmesa;
501 mmesa->glCtx = ctx;
502
503 driInitExtensions( ctx, card_extensions, GL_FALSE );
504
505 if (MGA_IS_G400(MGA_CONTEXT(ctx))) {
506 driInitExtensions( ctx, g400_extensions, GL_FALSE );
507 }
508
509 mgaDDInitStateFuncs( ctx );
510 mgaDDInitTextureFuncs( ctx );
511 mgaDDInitSpanFuncs( ctx );
512 mgaDDInitDriverFuncs( ctx );
513 mgaDDInitIoctlFuncs( ctx );
514 mgaDDInitPixelFuncs( ctx );
515 mgaDDInitTriFuncs( ctx );
516
517 mgaInitVB( ctx );
518 mgaInitState( mmesa );
519
520 driContextPriv->driverPrivate = (void *) mmesa;
521
522 #if DO_DEBUG
523 MGA_DEBUG = driParseDebugString( getenv( "MGA_DEBUG" ),
524 debug_control );
525 #endif
526
527 mmesa->vblank_flags = ((mmesa->mgaScreen->irq == 0)
528 || !mmesa->mgaScreen->linecomp_sane)
529 ? VBLANK_FLAG_NO_IRQ : driGetDefaultVBlankFlags(&mmesa->optionCache);
530 #ifndef _SOLO
531 mmesa->get_ust = (PFNGLXGETUSTPROC) glXGetProcAddress( (const GLubyte *) "__glXGetUST" );
532 if ( mmesa->get_ust == NULL ) {
533 mmesa->get_ust = get_ust_nop;
534 }
535 #else
536 mmesa->get_ust = get_ust_nop;
537 #endif
538
539 (*mmesa->get_ust)( & mmesa->swap_ust );
540
541 return GL_TRUE;
542 }
543
544 static void
545 mgaDestroyContext(__DRIcontextPrivate *driContextPriv)
546 {
547 mgaContextPtr mmesa = (mgaContextPtr) driContextPriv->driverPrivate;
548
549 if (MGA_DEBUG&DEBUG_VERBOSE_DRI)
550 fprintf( stderr, "[%s:%d] mgaDestroyContext start\n",
551 __FILE__, __LINE__ );
552
553 assert(mmesa); /* should never be null */
554 if (mmesa) {
555 GLboolean release_texture_heaps;
556
557
558 release_texture_heaps = (mmesa->glCtx->Shared->RefCount == 1);
559 _swsetup_DestroyContext( mmesa->glCtx );
560 _tnl_DestroyContext( mmesa->glCtx );
561 _ac_DestroyContext( mmesa->glCtx );
562 _swrast_DestroyContext( mmesa->glCtx );
563
564 mgaFreeVB( mmesa->glCtx );
565
566 /* free the Mesa context */
567 mmesa->glCtx->DriverCtx = NULL;
568 _mesa_destroy_context(mmesa->glCtx);
569
570 if ( release_texture_heaps ) {
571 /* This share group is about to go away, free our private
572 * texture object data.
573 */
574 int i;
575
576 assert( is_empty_list( & mmesa->swapped ) );
577
578 for ( i = 0 ; i < mmesa->nr_heaps ; i++ ) {
579 driDestroyTextureHeap( mmesa->texture_heaps[ i ] );
580 mmesa->texture_heaps[ i ] = NULL;
581 }
582 }
583
584 /* free the option cache */
585 driDestroyOptionCache (&mmesa->optionCache);
586
587 FREE(mmesa);
588 }
589
590 if (MGA_DEBUG&DEBUG_VERBOSE_DRI)
591 fprintf( stderr, "[%s:%d] mgaDestroyContext done\n",
592 __FILE__, __LINE__ );
593 }
594
595
596 static GLboolean
597 mgaCreateBuffer( __DRIscreenPrivate *driScrnPriv,
598 __DRIdrawablePrivate *driDrawPriv,
599 const __GLcontextModes *mesaVis,
600 GLboolean isPixmap )
601 {
602 if (isPixmap) {
603 return GL_FALSE; /* not implemented */
604 }
605 else {
606 GLboolean swStencil = (mesaVis->stencilBits > 0 &&
607 mesaVis->depthBits != 24);
608
609 driDrawPriv->driverPrivate = (void *)
610 _mesa_create_framebuffer(mesaVis,
611 GL_FALSE, /* software depth buffer? */
612 swStencil,
613 mesaVis->accumRedBits > 0,
614 mesaVis->alphaBits > 0 );
615
616 return (driDrawPriv->driverPrivate != NULL);
617 }
618 }
619
620
621 static void
622 mgaDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
623 {
624 _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
625 }
626
627 static void
628 mgaSwapBuffers(__DRIdrawablePrivate *dPriv)
629 {
630 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
631 mgaContextPtr mmesa;
632 GLcontext *ctx;
633 mmesa = (mgaContextPtr) dPriv->driContextPriv->driverPrivate;
634 ctx = mmesa->glCtx;
635
636 if (ctx->Visual.doubleBufferMode) {
637 _mesa_notifySwapBuffers( ctx );
638 mgaCopyBuffer( dPriv );
639 }
640 } else {
641 /* XXX this shouldn't be an error but we can't handle it for now */
642 _mesa_problem(NULL, "%s: drawable has no context!\n", __FUNCTION__);
643 }
644 }
645
646 static GLboolean
647 mgaUnbindContext(__DRIcontextPrivate *driContextPriv)
648 {
649 mgaContextPtr mmesa = (mgaContextPtr) driContextPriv->driverPrivate;
650 if (mmesa)
651 mmesa->dirty = ~0;
652
653 return GL_TRUE;
654 }
655
656 static GLboolean
657 mgaOpenCloseFullScreen(__DRIcontextPrivate *driContextPriv)
658 {
659 return GL_TRUE;
660 }
661
662
663 /* This looks buggy to me - the 'b' variable isn't used anywhere...
664 * Hmm - It seems that the drawable is already hooked in to
665 * driDrawablePriv.
666 *
667 * But why are we doing context initialization here???
668 */
669 static GLboolean
670 mgaMakeCurrent(__DRIcontextPrivate *driContextPriv,
671 __DRIdrawablePrivate *driDrawPriv,
672 __DRIdrawablePrivate *driReadPriv)
673 {
674 if (driContextPriv) {
675 mgaContextPtr mmesa = (mgaContextPtr) driContextPriv->driverPrivate;
676
677 if (mmesa->driDrawable != driDrawPriv) {
678 driDrawableInitVBlank( driDrawPriv, mmesa->vblank_flags );
679 mmesa->driDrawable = driDrawPriv;
680 mmesa->dirty = ~0;
681 mmesa->dirty_cliprects = (MGA_FRONT|MGA_BACK);
682 mmesa->mesa_drawable = driDrawPriv;
683 }
684
685 mmesa->driReadable = driReadPriv;
686
687 _mesa_make_current2(mmesa->glCtx,
688 (GLframebuffer *) driDrawPriv->driverPrivate,
689 (GLframebuffer *) driReadPriv->driverPrivate);
690
691 if (!mmesa->glCtx->Viewport.Width)
692 _mesa_set_viewport(mmesa->glCtx, 0, 0,
693 driDrawPriv->w, driDrawPriv->h);
694
695 }
696 else {
697 _mesa_make_current(NULL, NULL);
698 }
699
700 return GL_TRUE;
701 }
702
703
704 void mgaGetLock( mgaContextPtr mmesa, GLuint flags )
705 {
706 __DRIdrawablePrivate *dPriv = mmesa->driDrawable;
707 MGASAREAPrivPtr sarea = mmesa->sarea;
708 int me = mmesa->hHWContext;
709 int i;
710
711 drmGetLock(mmesa->driFd, mmesa->hHWContext, flags);
712
713 if (*(dPriv->pStamp) != mmesa->lastStamp) {
714 mmesa->lastStamp = *(dPriv->pStamp);
715 mmesa->SetupNewInputs |= VERT_BIT_POS;
716 mmesa->dirty_cliprects = (MGA_FRONT|MGA_BACK);
717 mgaUpdateRects( mmesa, (MGA_FRONT|MGA_BACK) );
718 }
719
720 mmesa->dirty |= MGA_UPLOAD_CONTEXT | MGA_UPLOAD_CLIPRECTS;
721
722 mmesa->sarea->dirty |= MGA_UPLOAD_CONTEXT;
723
724 if (sarea->ctxOwner != me) {
725 mmesa->dirty |= (MGA_UPLOAD_CONTEXT | MGA_UPLOAD_TEX0 |
726 MGA_UPLOAD_TEX1 | MGA_UPLOAD_PIPE);
727 sarea->ctxOwner=me;
728 }
729
730 for ( i = 0 ; i < mmesa->nr_heaps ; i++ ) {
731 DRI_AGE_TEXTURES( mmesa->texture_heaps[ i ] );
732 }
733
734 sarea->last_quiescent = -1; /* just kill it for now */
735 }
736
737
738 static const struct __DriverAPIRec mgaAPI = {
739 .InitDriver = mgaInitDriver,
740 .DestroyScreen = mgaDestroyScreen,
741 .CreateContext = mgaCreateContext,
742 .DestroyContext = mgaDestroyContext,
743 .CreateBuffer = mgaCreateBuffer,
744 .DestroyBuffer = mgaDestroyBuffer,
745 .SwapBuffers = mgaSwapBuffers,
746 .MakeCurrent = mgaMakeCurrent,
747 .UnbindContext = mgaUnbindContext,
748 .OpenFullScreen = mgaOpenCloseFullScreen,
749 .CloseFullScreen = mgaOpenCloseFullScreen,
750 .GetSwapInfo = getSwapInfo,
751 .GetMSC = driGetMSC32,
752 .WaitForMSC = driWaitForMSC32,
753 .WaitForSBC = NULL,
754 .SwapBuffersMSC = NULL
755 };
756
757
758 /*
759 * This is the bootstrap function for the driver.
760 * The __driCreateScreen name is the symbol that libGL.so fetches.
761 * Return: pointer to a __DRIscreenPrivate.
762 */
763 #ifndef _SOLO
764 void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
765 int numConfigs, __GLXvisualConfig *config)
766 {
767 __DRIscreenPrivate *psp;
768 psp = __driUtilCreateScreen(dpy, scrn, psc, numConfigs, config, &mgaAPI);
769 return (void *) psp;
770 }
771 #else
772 void *__driCreateScreen(struct DRIDriverRec *driver,
773 struct DRIDriverContextRec *driverContext)
774 {
775 __DRIscreenPrivate *psp;
776 psp = __driUtilCreateScreen(driver, driverContext, &mgaAPI);
777 return (void *) psp;
778 }
779 #endif
780
781
782 /**
783 * Get information about previous buffer swaps.
784 */
785 static int
786 getSwapInfo( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo )
787 {
788 mgaContextPtr mmesa;
789
790 if ( (dPriv == NULL) || (dPriv->driContextPriv == NULL)
791 || (dPriv->driContextPriv->driverPrivate == NULL)
792 || (sInfo == NULL) ) {
793 return -1;
794 }
795
796 mmesa = (mgaContextPtr) dPriv->driContextPriv->driverPrivate;
797 sInfo->swap_count = mmesa->swap_count;
798 sInfo->swap_ust = mmesa->swap_ust;
799 sInfo->swap_missed_count = mmesa->swap_missed_count;
800
801 sInfo->swap_missed_usage = (sInfo->swap_missed_count != 0)
802 ? driCalculateSwapUsage( dPriv, 0, mmesa->swap_missed_ust )
803 : 0.0;
804
805 return 0;
806 }