1 /* $XFree86: xc/lib/GL/mesa/src/drv/mga/mga_xmesa.c,v 1.19 2003/03/26 20:43:49 tsi Exp $ */
3 * Copyright 2000-2001 VA Linux Systems, Inc.
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:
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
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.
28 * MGA screen and context initialization / creation code.
30 * \author Keith Whitwell <keith@tungstengraphics.com>
37 #include "mga_xmesa.h"
40 #include "simple_list.h"
42 #include "framebuffer.h"
43 #include "renderbuffer.h"
45 #include "swrast/swrast.h"
46 #include "swrast_setup/swrast_setup.h"
48 #include "array_cache/acache.h"
50 #include "tnl/t_pipeline.h"
52 #include "drivers/common/driverfuncs.h"
62 #include "mga_xmesa.h"
68 #include "extensions.h"
70 #include "GL/internal/dri_interface.h"
72 #define need_GL_ARB_multisample
73 #define need_GL_ARB_texture_compression
74 #define need_GL_ARB_vertex_program
75 #define need_GL_EXT_fog_coord
76 #define need_GL_EXT_multi_draw_arrays
77 #define need_GL_EXT_secondary_color
79 #define need_GL_EXT_paletted_texture
81 #define need_GL_NV_vertex_program
82 #include "extension_helper.h"
88 PUBLIC
const char __driConfigOptions
[] =
90 DRI_CONF_SECTION_PERFORMANCE
91 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0
)
93 DRI_CONF_SECTION_QUALITY
94 DRI_CONF_TEXTURE_DEPTH(DRI_CONF_TEXTURE_DEPTH_FB
)
95 DRI_CONF_COLOR_REDUCTION(DRI_CONF_COLOR_REDUCTION_DITHER
)
97 DRI_CONF_SECTION_SOFTWARE
98 DRI_CONF_ARB_VERTEX_PROGRAM(true)
99 DRI_CONF_NV_VERTEX_PROGRAM(true)
101 DRI_CONF_SECTION_DEBUG
102 DRI_CONF_NO_RAST(false)
105 static const GLuint __driNConfigOptions
= 6;
111 static int getSwapInfo( __DRIdrawablePrivate
*dPriv
, __DRIswapInfo
* sInfo
);
113 static __GLcontextModes
*
114 mgaFillInModes( unsigned pixel_bits
, unsigned depth_bits
,
115 unsigned stencil_bits
, GLboolean have_back_buffer
)
117 __GLcontextModes
* modes
;
118 __GLcontextModes
* m
;
120 unsigned depth_buffer_factor
;
121 unsigned back_buffer_factor
;
125 /* GLX_SWAP_COPY_OML is only supported because the MGA driver doesn't
126 * support pageflipping at all.
128 static const GLenum back_buffer_modes
[] = {
129 GLX_NONE
, GLX_SWAP_UNDEFINED_OML
, GLX_SWAP_COPY_OML
132 u_int8_t depth_bits_array
[3];
133 u_int8_t stencil_bits_array
[3];
136 depth_bits_array
[0] = 0;
137 depth_bits_array
[1] = depth_bits
;
138 depth_bits_array
[2] = depth_bits
;
140 /* Just like with the accumulation buffer, always provide some modes
141 * with a stencil buffer. It will be a sw fallback, but some apps won't
144 stencil_bits_array
[0] = 0;
145 stencil_bits_array
[1] = 0;
146 stencil_bits_array
[2] = (stencil_bits
== 0) ? 8 : stencil_bits
;
148 depth_buffer_factor
= ((depth_bits
!= 0) || (stencil_bits
!= 0)) ? 3 : 1;
149 back_buffer_factor
= (have_back_buffer
) ? 2 : 1;
151 num_modes
= depth_buffer_factor
* back_buffer_factor
* 4;
153 if ( pixel_bits
== 16 ) {
155 fb_type
= GL_UNSIGNED_SHORT_5_6_5
;
159 fb_type
= GL_UNSIGNED_INT_8_8_8_8_REV
;
162 modes
= (*dri_interface
->createContextModes
)( num_modes
, sizeof( __GLcontextModes
) );
164 if ( ! driFillInModes( & m
, fb_format
, fb_type
,
165 depth_bits_array
, stencil_bits_array
, depth_buffer_factor
,
166 back_buffer_modes
, back_buffer_factor
,
168 fprintf( stderr
, "[%s:%u] Error creating FBConfig!\n",
169 __func__
, __LINE__
);
173 if ( ! driFillInModes( & m
, fb_format
, fb_type
,
174 depth_bits_array
, stencil_bits_array
, depth_buffer_factor
,
175 back_buffer_modes
, back_buffer_factor
,
176 GLX_DIRECT_COLOR
) ) {
177 fprintf( stderr
, "[%s:%u] Error creating FBConfig!\n",
178 __func__
, __LINE__
);
182 /* Mark the visual as slow if there are "fake" stencil bits.
184 for ( m
= modes
; m
!= NULL
; m
= m
->next
) {
185 if ( (m
->stencilBits
!= 0) && (m
->stencilBits
!= stencil_bits
) ) {
186 m
->visualRating
= GLX_SLOW_CONFIG
;
195 mgaInitDriver(__DRIscreenPrivate
*sPriv
)
197 mgaScreenPrivate
*mgaScreen
;
198 MGADRIPtr serverInfo
= (MGADRIPtr
)sPriv
->pDevPriv
;
199 PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension
=
200 (PFNGLXSCRENABLEEXTENSIONPROC
) (*dri_interface
->getProcAddress("glxEnableExtension"));
201 void * const psc
= sPriv
->psc
->screenConfigs
;
204 /* Allocate the private area */
205 mgaScreen
= (mgaScreenPrivate
*)MALLOC(sizeof(mgaScreenPrivate
));
207 __driUtilMessage("Couldn't malloc screen struct");
211 mgaScreen
->sPriv
= sPriv
;
212 sPriv
->private = (void *)mgaScreen
;
214 if (sPriv
->drmMinor
>= 1) {
216 drm_mga_getparam_t gp
;
218 gp
.param
= MGA_PARAM_IRQ_NR
;
219 gp
.value
= &mgaScreen
->irq
;
222 ret
= drmCommandWriteRead( sPriv
->fd
, DRM_MGA_GETPARAM
,
225 fprintf(stderr
, "drmMgaGetParam (MGA_PARAM_IRQ_NR): %d\n", ret
);
227 sPriv
->private = NULL
;
232 if ( glx_enable_extension
!= NULL
) {
233 (*glx_enable_extension
)( psc
, "GLX_MESA_swap_control" );
234 (*glx_enable_extension
)( psc
, "GLX_MESA_swap_frame_usage" );
235 (*glx_enable_extension
)( psc
, "GLX_SGI_make_current_read" );
236 (*glx_enable_extension
)( psc
, "GLX_SGI_swap_control" );
237 (*glx_enable_extension
)( psc
, "GLX_SGI_video_sync" );
240 if (serverInfo
->chipset
!= MGA_CARD_TYPE_G200
&&
241 serverInfo
->chipset
!= MGA_CARD_TYPE_G400
) {
243 sPriv
->private = NULL
;
244 __driUtilMessage("Unrecognized chipset");
249 mgaScreen
->chipset
= serverInfo
->chipset
;
250 mgaScreen
->cpp
= serverInfo
->cpp
;
252 mgaScreen
->agpMode
= serverInfo
->agpMode
;
254 mgaScreen
->frontPitch
= serverInfo
->frontPitch
;
255 mgaScreen
->frontOffset
= serverInfo
->frontOffset
;
256 mgaScreen
->backOffset
= serverInfo
->backOffset
;
257 mgaScreen
->backPitch
= serverInfo
->backPitch
;
258 mgaScreen
->depthOffset
= serverInfo
->depthOffset
;
259 mgaScreen
->depthPitch
= serverInfo
->depthPitch
;
262 /* The only reason that the MMIO region needs to be accessable and the
263 * primary DMA region base address needs to be known is so that the driver
264 * can busy wait for certain DMA operations to complete (see
265 * mgaWaitForFrameCompletion in mgaioctl.c).
267 * Starting with MGA DRM version 3.2, these are completely unneeded as
268 * there is a new, in-kernel mechanism for handling the wait.
271 if (mgaScreen
->sPriv
->drmMinor
< 2) {
272 mgaScreen
->mmio
.handle
= serverInfo
->registers
.handle
;
273 mgaScreen
->mmio
.size
= serverInfo
->registers
.size
;
274 if ( drmMap( sPriv
->fd
,
275 mgaScreen
->mmio
.handle
, mgaScreen
->mmio
.size
,
276 &mgaScreen
->mmio
.map
) < 0 ) {
278 sPriv
->private = NULL
;
279 __driUtilMessage( "Couldn't map MMIO registers" );
283 mgaScreen
->primary
.handle
= serverInfo
->primary
.handle
;
284 mgaScreen
->primary
.size
= serverInfo
->primary
.size
;
287 (void) memset( & mgaScreen
->primary
, 0, sizeof( mgaScreen
->primary
) );
288 (void) memset( & mgaScreen
->mmio
, 0, sizeof( mgaScreen
->mmio
) );
291 mgaScreen
->textureOffset
[MGA_CARD_HEAP
] = serverInfo
->textureOffset
;
292 mgaScreen
->textureOffset
[MGA_AGP_HEAP
] = (serverInfo
->agpTextureOffset
|
293 PDEA_pagpxfer_enable
| 1);
295 mgaScreen
->textureSize
[MGA_CARD_HEAP
] = serverInfo
->textureSize
;
296 mgaScreen
->textureSize
[MGA_AGP_HEAP
] = serverInfo
->agpTextureSize
;
299 /* The texVirtual array stores the base addresses in the CPU's address
300 * space of the texture memory pools. The base address of the on-card
301 * memory pool is calculated as an offset of the base of video memory. The
302 * AGP texture pool has to be mapped into the processes address space by
306 mgaScreen
->texVirtual
[MGA_CARD_HEAP
] = (char *)(mgaScreen
->sPriv
->pFB
+
307 serverInfo
->textureOffset
);
309 if ( serverInfo
->agpTextureSize
> 0 ) {
310 if (drmMap(sPriv
->fd
, serverInfo
->agpTextureOffset
,
311 serverInfo
->agpTextureSize
,
312 (drmAddress
*)&mgaScreen
->texVirtual
[MGA_AGP_HEAP
]) != 0) {
314 sPriv
->private = NULL
;
315 __driUtilMessage("Couldn't map agptexture region");
321 /* For calculating setupdma addresses.
324 mgaScreen
->bufs
= drmMapBufs(sPriv
->fd
);
325 if (!mgaScreen
->bufs
) {
327 sPriv
->private = NULL
;
328 __driUtilMessage("Couldn't map dma buffers");
331 mgaScreen
->sarea_priv_offset
= serverInfo
->sarea_priv_offset
;
333 /* parse information in __driConfigOptions */
334 driParseOptionInfo (&mgaScreen
->optionCache
,
335 __driConfigOptions
, __driNConfigOptions
);
342 mgaDestroyScreen(__DRIscreenPrivate
*sPriv
)
344 mgaScreenPrivate
*mgaScreen
= (mgaScreenPrivate
*) sPriv
->private;
346 if (MGA_DEBUG
&DEBUG_VERBOSE_DRI
)
347 fprintf(stderr
, "mgaDestroyScreen\n");
349 drmUnmapBufs(mgaScreen
->bufs
);
352 /* free all option information */
353 driDestroyOptionInfo (&mgaScreen
->optionCache
);
356 sPriv
->private = NULL
;
360 extern const struct tnl_pipeline_stage _mga_render_stage
;
362 static const struct tnl_pipeline_stage
*mga_pipeline
[] = {
363 &_tnl_vertex_transform_stage
,
364 &_tnl_normal_transform_stage
,
365 &_tnl_lighting_stage
,
366 &_tnl_fog_coordinate_stage
,
368 &_tnl_texture_transform_stage
,
369 &_tnl_vertex_program_stage
,
371 /* REMOVE: point attenuation stage */
373 &_mga_render_stage
, /* ADD: unclipped rastersetup-to-dma */
374 /* Need new ioctl for wacceptseq */
381 static const struct dri_extension g400_extensions
[] =
383 { "GL_ARB_multitexture", NULL
},
384 { "GL_ARB_texture_env_add", NULL
},
385 { "GL_ARB_texture_env_combine", NULL
},
386 { "GL_ARB_texture_env_crossbar", NULL
},
387 { "GL_EXT_texture_env_combine", NULL
},
388 { "GL_EXT_texture_edge_clamp", NULL
},
389 { "GL_ATI_texture_env_combine3", NULL
},
393 static const struct dri_extension card_extensions
[] =
395 { "GL_ARB_multisample", GL_ARB_multisample_functions
},
396 { "GL_ARB_texture_compression", GL_ARB_texture_compression_functions
},
397 { "GL_ARB_texture_rectangle", NULL
},
398 { "GL_EXT_blend_logic_op", NULL
},
399 { "GL_EXT_fog_coord", GL_EXT_fog_coord_functions
},
400 { "GL_EXT_multi_draw_arrays", GL_EXT_multi_draw_arrays_functions
},
401 /* paletted_textures currently doesn't work, but we could fix them later */
402 #if defined( need_GL_EXT_paletted_texture )
403 { "GL_EXT_shared_texture_palette", NULL
},
404 { "GL_EXT_paletted_texture", GL_EXT_paletted_texture_functions
},
406 { "GL_EXT_secondary_color", GL_EXT_secondary_color_functions
},
407 { "GL_EXT_stencil_wrap", NULL
},
408 { "GL_MESA_ycbcr_texture", NULL
},
409 { "GL_SGIS_generate_mipmap", NULL
},
413 static const struct dri_extension ARB_vp_extension
[] = {
414 { "GL_ARB_vertex_program", GL_ARB_vertex_program_functions
},
418 static const struct dri_extension NV_vp_extensions
[] = {
419 { "GL_NV_vertex_program", GL_NV_vertex_program_functions
},
420 { "GL_NV_vertex_program1_1", NULL
},
424 static const struct dri_debug_control debug_control
[] =
426 { "fall", DEBUG_VERBOSE_FALLBACK
},
427 { "tex", DEBUG_VERBOSE_TEXTURE
},
428 { "ioctl", DEBUG_VERBOSE_IOCTL
},
429 { "verb", DEBUG_VERBOSE_MSG
},
430 { "dri", DEBUG_VERBOSE_DRI
},
436 mgaCreateContext( const __GLcontextModes
*mesaVis
,
437 __DRIcontextPrivate
*driContextPriv
,
438 void *sharedContextPrivate
)
442 GLcontext
*ctx
, *shareCtx
;
444 __DRIscreenPrivate
*sPriv
= driContextPriv
->driScreenPriv
;
445 mgaScreenPrivate
*mgaScreen
= (mgaScreenPrivate
*)sPriv
->private;
446 drm_mga_sarea_t
*saPriv
= (drm_mga_sarea_t
*)(((char*)sPriv
->pSAREA
)+
447 mgaScreen
->sarea_priv_offset
);
448 struct dd_function_table functions
;
450 if (MGA_DEBUG
&DEBUG_VERBOSE_DRI
)
451 fprintf(stderr
, "mgaCreateContext\n");
453 /* allocate mga context */
454 mmesa
= (mgaContextPtr
) CALLOC(sizeof(mgaContext
));
459 /* Init default driver functions then plug in our Radeon-specific functions
460 * (the texture functions are especially important)
462 _mesa_init_driver_functions( &functions
);
463 mgaInitDriverFuncs( &functions
);
464 mgaInitTextureFuncs( &functions
);
465 mgaInitIoctlFuncs( &functions
);
467 /* Allocate the Mesa context */
468 if (sharedContextPrivate
)
469 shareCtx
= ((mgaContextPtr
) sharedContextPrivate
)->glCtx
;
472 mmesa
->glCtx
= _mesa_create_context(mesaVis
, shareCtx
,
473 &functions
, (void *) mmesa
);
478 driContextPriv
->driverPrivate
= mmesa
;
481 mmesa
->hHWContext
= driContextPriv
->hHWContext
;
482 mmesa
->driFd
= sPriv
->fd
;
483 mmesa
->driHwLock
= &sPriv
->pSAREA
->lock
;
485 mmesa
->mgaScreen
= mgaScreen
;
486 mmesa
->driScreen
= sPriv
;
487 mmesa
->sarea
= (void *)saPriv
;
489 /* Parse configuration files */
490 driParseConfigFiles (&mmesa
->optionCache
, &mgaScreen
->optionCache
,
491 sPriv
->myNum
, "mga");
493 (void) memset( mmesa
->texture_heaps
, 0, sizeof( mmesa
->texture_heaps
) );
494 make_empty_list( & mmesa
->swapped
);
496 mmesa
->nr_heaps
= mgaScreen
->texVirtual
[MGA_AGP_HEAP
] ? 2 : 1;
497 for ( i
= 0 ; i
< mmesa
->nr_heaps
; i
++ ) {
498 mmesa
->texture_heaps
[i
] = driCreateTextureHeap( i
, mmesa
,
499 mgaScreen
->textureSize
[i
],
502 (drmTextureRegionPtr
)mmesa
->sarea
->texList
[i
],
503 &mmesa
->sarea
->texAge
[i
],
505 sizeof( mgaTextureObject_t
),
506 (destroy_texture_object_t
*) mgaDestroyTexObj
);
509 /* Set the maximum texture size small enough that we can guarentee
510 * that both texture units can bind a maximal texture and have them
511 * on the card at once.
514 if ( mgaScreen
->chipset
== MGA_CARD_TYPE_G200
) {
515 ctx
->Const
.MaxTextureUnits
= 1;
516 ctx
->Const
.MaxTextureImageUnits
= 1;
517 ctx
->Const
.MaxTextureCoordUnits
= 1;
518 maxlevels
= G200_TEX_MAXLEVELS
;
522 ctx
->Const
.MaxTextureUnits
= 2;
523 ctx
->Const
.MaxTextureImageUnits
= 2;
524 ctx
->Const
.MaxTextureCoordUnits
= 2;
525 maxlevels
= G400_TEX_MAXLEVELS
;
528 driCalculateMaxTextureLevels( mmesa
->texture_heaps
,
532 11, /* max 2D texture size is 2048x2048 */
533 0, /* 3D textures unsupported. */
534 0, /* cube textures unsupported. */
535 11, /* max texture rect size is 2048x2048 */
539 ctx
->Const
.MinLineWidth
= 1.0;
540 ctx
->Const
.MinLineWidthAA
= 1.0;
541 ctx
->Const
.MaxLineWidth
= 10.0;
542 ctx
->Const
.MaxLineWidthAA
= 10.0;
543 ctx
->Const
.LineWidthGranularity
= 1.0;
545 mmesa
->texture_depth
= driQueryOptioni (&mmesa
->optionCache
,
547 if (mmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_FB
)
548 mmesa
->texture_depth
= ( mesaVis
->rgbBits
>= 24 ) ?
549 DRI_CONF_TEXTURE_DEPTH_32
: DRI_CONF_TEXTURE_DEPTH_16
;
550 mmesa
->hw_stencil
= mesaVis
->stencilBits
&& mesaVis
->depthBits
== 24;
552 switch (mesaVis
->depthBits
) {
554 mmesa
->depth_scale
= 1.0/(GLdouble
)0xffff;
555 mmesa
->depth_clear_mask
= ~0;
556 mmesa
->ClearDepth
= 0xffff;
559 mmesa
->depth_scale
= 1.0/(GLdouble
)0xffffff;
560 if (mmesa
->hw_stencil
) {
561 mmesa
->depth_clear_mask
= 0xffffff00;
562 mmesa
->stencil_clear_mask
= 0x000000ff;
564 mmesa
->depth_clear_mask
= ~0;
565 mmesa
->ClearDepth
= 0xffffff00;
568 mmesa
->depth_scale
= 1.0/(GLdouble
)0xffffffff;
569 mmesa
->depth_clear_mask
= ~0;
570 mmesa
->ClearDepth
= 0xffffffff;
574 mmesa
->haveHwStipple
= GL_FALSE
;
575 mmesa
->RenderIndex
= -1; /* impossible value */
577 mmesa
->vertex_format
= 0;
578 mmesa
->CurrentTexObj
[0] = 0;
579 mmesa
->CurrentTexObj
[1] = 0;
580 mmesa
->tmu_source
[0] = 0;
581 mmesa
->tmu_source
[1] = 1;
583 mmesa
->texAge
[0] = 0;
584 mmesa
->texAge
[1] = 0;
586 /* Initialize the software rasterizer and helper modules.
588 _swrast_CreateContext( ctx
);
589 _ac_CreateContext( ctx
);
590 _tnl_CreateContext( ctx
);
592 _swsetup_CreateContext( ctx
);
594 /* Install the customized pipeline:
596 _tnl_destroy_pipeline( ctx
);
597 _tnl_install_pipeline( ctx
, mga_pipeline
);
599 /* Configure swrast and T&L to match hardware characteristics:
601 _swrast_allow_pixel_fog( ctx
, GL_FALSE
);
602 _swrast_allow_vertex_fog( ctx
, GL_TRUE
);
603 _tnl_allow_pixel_fog( ctx
, GL_FALSE
);
604 _tnl_allow_vertex_fog( ctx
, GL_TRUE
);
606 mmesa
->primary_offset
= mmesa
->mgaScreen
->primary
.handle
;
608 ctx
->DriverCtx
= (void *) mmesa
;
611 driInitExtensions( ctx
, card_extensions
, GL_FALSE
);
613 if (MGA_IS_G400(MGA_CONTEXT(ctx
))) {
614 driInitExtensions( ctx
, g400_extensions
, GL_FALSE
);
617 if ( driQueryOptionb( &mmesa
->optionCache
, "arb_vertex_program" ) ) {
618 driInitSingleExtension( ctx
, ARB_vp_extension
);
621 if ( driQueryOptionb( &mmesa
->optionCache
, "nv_vertex_program" ) ) {
622 driInitExtensions( ctx
, NV_vp_extensions
, GL_FALSE
);
626 /* XXX these should really go right after _mesa_init_driver_functions() */
627 mgaDDInitStateFuncs( ctx
);
628 mgaDDInitSpanFuncs( ctx
);
629 mgaDDInitPixelFuncs( ctx
);
630 mgaDDInitTriFuncs( ctx
);
633 mgaInitState( mmesa
);
635 driContextPriv
->driverPrivate
= (void *) mmesa
;
638 MGA_DEBUG
= driParseDebugString( getenv( "MGA_DEBUG" ),
642 mmesa
->vblank_flags
= (mmesa
->mgaScreen
->irq
== 0)
643 ? VBLANK_FLAG_NO_IRQ
: driGetDefaultVBlankFlags(&mmesa
->optionCache
);
645 (*dri_interface
->getUST
)( & mmesa
->swap_ust
);
647 if (driQueryOptionb(&mmesa
->optionCache
, "no_rast")) {
648 fprintf(stderr
, "disabling 3D acceleration\n");
649 FALLBACK(mmesa
->glCtx
, MGA_FALLBACK_DISABLE
, 1);
656 mgaDestroyContext(__DRIcontextPrivate
*driContextPriv
)
658 mgaContextPtr mmesa
= (mgaContextPtr
) driContextPriv
->driverPrivate
;
660 if (MGA_DEBUG
&DEBUG_VERBOSE_DRI
)
661 fprintf( stderr
, "[%s:%d] mgaDestroyContext start\n",
662 __FILE__
, __LINE__
);
664 assert(mmesa
); /* should never be null */
666 GLboolean release_texture_heaps
;
669 release_texture_heaps
= (mmesa
->glCtx
->Shared
->RefCount
== 1);
670 _swsetup_DestroyContext( mmesa
->glCtx
);
671 _tnl_DestroyContext( mmesa
->glCtx
);
672 _ac_DestroyContext( mmesa
->glCtx
);
673 _swrast_DestroyContext( mmesa
->glCtx
);
675 mgaFreeVB( mmesa
->glCtx
);
677 /* free the Mesa context */
678 mmesa
->glCtx
->DriverCtx
= NULL
;
679 _mesa_destroy_context(mmesa
->glCtx
);
681 if ( release_texture_heaps
) {
682 /* This share group is about to go away, free our private
683 * texture object data.
687 for ( i
= 0 ; i
< mmesa
->nr_heaps
; i
++ ) {
688 driDestroyTextureHeap( mmesa
->texture_heaps
[ i
] );
689 mmesa
->texture_heaps
[ i
] = NULL
;
692 assert( is_empty_list( & mmesa
->swapped
) );
695 /* free the option cache */
696 driDestroyOptionCache (&mmesa
->optionCache
);
701 if (MGA_DEBUG
&DEBUG_VERBOSE_DRI
)
702 fprintf( stderr
, "[%s:%d] mgaDestroyContext done\n",
703 __FILE__
, __LINE__
);
708 mgaCreateBuffer( __DRIscreenPrivate
*driScrnPriv
,
709 __DRIdrawablePrivate
*driDrawPriv
,
710 const __GLcontextModes
*mesaVis
,
713 mgaScreenPrivate
*screen
= (mgaScreenPrivate
*) driScrnPriv
->private;
716 return GL_FALSE
; /* not implemented */
719 GLboolean swStencil
= (mesaVis
->stencilBits
> 0 &&
720 mesaVis
->depthBits
!= 24);
723 driDrawPriv
->driverPrivate
= (void *)
724 _mesa_create_framebuffer(mesaVis
,
725 GL_FALSE
, /* software depth buffer? */
727 mesaVis
->accumRedBits
> 0,
728 mesaVis
->alphaBits
> 0 );
730 struct gl_framebuffer
*fb
= _mesa_create_framebuffer(mesaVis
);
733 driRenderbuffer
*frontRb
734 = driNewRenderbuffer(GL_RGBA
, screen
->cpp
,
735 screen
->frontOffset
, screen
->frontPitch
);
736 mgaSetSpanFunctions(frontRb
, mesaVis
);
737 _mesa_add_renderbuffer(fb
, BUFFER_FRONT_LEFT
, &frontRb
->Base
);
740 if (mesaVis
->doubleBufferMode
) {
741 driRenderbuffer
*backRb
742 = driNewRenderbuffer(GL_RGBA
, screen
->cpp
,
743 screen
->backOffset
, screen
->backPitch
);
744 mgaSetSpanFunctions(backRb
, mesaVis
);
745 _mesa_add_renderbuffer(fb
, BUFFER_BACK_LEFT
, &backRb
->Base
);
748 if (mesaVis
->depthBits
== 16) {
749 driRenderbuffer
*depthRb
750 = driNewRenderbuffer(GL_DEPTH_COMPONENT16
, screen
->cpp
,
751 screen
->depthOffset
, screen
->depthPitch
);
752 mgaSetSpanFunctions(depthRb
, mesaVis
);
753 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
755 else if (mesaVis
->depthBits
== 24) {
756 /* XXX is this right? */
757 if (mesaVis
->stencilBits
) {
758 driRenderbuffer
*depthRb
759 = driNewRenderbuffer(GL_DEPTH_COMPONENT24
, screen
->cpp
,
760 screen
->depthOffset
, screen
->depthPitch
);
761 mgaSetSpanFunctions(depthRb
, mesaVis
);
762 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
765 driRenderbuffer
*depthRb
766 = driNewRenderbuffer(GL_DEPTH_COMPONENT32
, screen
->cpp
,
767 screen
->depthOffset
, screen
->depthPitch
);
768 mgaSetSpanFunctions(depthRb
, mesaVis
);
769 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
772 else if (mesaVis
->depthBits
== 32) {
773 driRenderbuffer
*depthRb
774 = driNewRenderbuffer(GL_DEPTH_COMPONENT32
, screen
->cpp
,
775 screen
->depthOffset
, screen
->depthPitch
);
776 mgaSetSpanFunctions(depthRb
, mesaVis
);
777 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
780 if (mesaVis
->stencilBits
> 0 && !swStencil
) {
781 driRenderbuffer
*stencilRb
782 = driNewRenderbuffer(GL_STENCIL_INDEX8_EXT
, screen
->cpp
,
783 screen
->depthOffset
, screen
->depthPitch
);
784 mgaSetSpanFunctions(stencilRb
, mesaVis
);
785 _mesa_add_renderbuffer(fb
, BUFFER_STENCIL
, &stencilRb
->Base
);
788 _mesa_add_soft_renderbuffers(fb
,
789 GL_FALSE
, /* color */
790 GL_FALSE
, /* depth */
792 mesaVis
->accumRedBits
> 0,
793 GL_FALSE
, /* alpha */
795 driDrawPriv
->driverPrivate
= (void *) fb
;
798 return (driDrawPriv
->driverPrivate
!= NULL
);
804 mgaDestroyBuffer(__DRIdrawablePrivate
*driDrawPriv
)
806 _mesa_destroy_framebuffer((GLframebuffer
*) (driDrawPriv
->driverPrivate
));
810 mgaSwapBuffers(__DRIdrawablePrivate
*dPriv
)
812 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
815 mmesa
= (mgaContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
818 if (ctx
->Visual
.doubleBufferMode
) {
819 _mesa_notifySwapBuffers( ctx
);
820 mgaCopyBuffer( dPriv
);
823 /* XXX this shouldn't be an error but we can't handle it for now */
824 _mesa_problem(NULL
, "%s: drawable has no context!\n", __FUNCTION__
);
829 mgaUnbindContext(__DRIcontextPrivate
*driContextPriv
)
831 mgaContextPtr mmesa
= (mgaContextPtr
) driContextPriv
->driverPrivate
;
838 /* This looks buggy to me - the 'b' variable isn't used anywhere...
839 * Hmm - It seems that the drawable is already hooked in to
842 * But why are we doing context initialization here???
845 mgaMakeCurrent(__DRIcontextPrivate
*driContextPriv
,
846 __DRIdrawablePrivate
*driDrawPriv
,
847 __DRIdrawablePrivate
*driReadPriv
)
849 if (driContextPriv
) {
850 mgaContextPtr mmesa
= (mgaContextPtr
) driContextPriv
->driverPrivate
;
852 if (mmesa
->driDrawable
!= driDrawPriv
) {
853 driDrawableInitVBlank( driDrawPriv
, mmesa
->vblank_flags
);
854 mmesa
->driDrawable
= driDrawPriv
;
856 mmesa
->dirty_cliprects
= (MGA_FRONT
|MGA_BACK
);
857 mmesa
->mesa_drawable
= driDrawPriv
;
860 mmesa
->driReadable
= driReadPriv
;
862 _mesa_make_current(mmesa
->glCtx
,
863 (GLframebuffer
*) driDrawPriv
->driverPrivate
,
864 (GLframebuffer
*) driReadPriv
->driverPrivate
);
867 _mesa_make_current(NULL
, NULL
, NULL
);
874 void mgaGetLock( mgaContextPtr mmesa
, GLuint flags
)
876 __DRIdrawablePrivate
*dPriv
= mmesa
->driDrawable
;
877 drm_mga_sarea_t
*sarea
= mmesa
->sarea
;
878 int me
= mmesa
->hHWContext
;
881 drmGetLock(mmesa
->driFd
, mmesa
->hHWContext
, flags
);
883 if (*(dPriv
->pStamp
) != mmesa
->lastStamp
) {
884 mmesa
->lastStamp
= *(dPriv
->pStamp
);
885 mmesa
->SetupNewInputs
|= VERT_BIT_POS
;
886 mmesa
->dirty_cliprects
= (MGA_FRONT
|MGA_BACK
);
887 mgaUpdateRects( mmesa
, (MGA_FRONT
|MGA_BACK
) );
890 mmesa
->dirty
|= MGA_UPLOAD_CONTEXT
| MGA_UPLOAD_CLIPRECTS
;
892 mmesa
->sarea
->dirty
|= MGA_UPLOAD_CONTEXT
;
894 if (sarea
->ctxOwner
!= me
) {
895 mmesa
->dirty
|= (MGA_UPLOAD_CONTEXT
| MGA_UPLOAD_TEX0
|
896 MGA_UPLOAD_TEX1
| MGA_UPLOAD_PIPE
);
900 for ( i
= 0 ; i
< mmesa
->nr_heaps
; i
++ ) {
901 DRI_AGE_TEXTURES( mmesa
->texture_heaps
[ i
] );
906 static const struct __DriverAPIRec mgaAPI
= {
907 .InitDriver
= mgaInitDriver
,
908 .DestroyScreen
= mgaDestroyScreen
,
909 .CreateContext
= mgaCreateContext
,
910 .DestroyContext
= mgaDestroyContext
,
911 .CreateBuffer
= mgaCreateBuffer
,
912 .DestroyBuffer
= mgaDestroyBuffer
,
913 .SwapBuffers
= mgaSwapBuffers
,
914 .MakeCurrent
= mgaMakeCurrent
,
915 .UnbindContext
= mgaUnbindContext
,
916 .GetSwapInfo
= getSwapInfo
,
917 .GetMSC
= driGetMSC32
,
918 .WaitForMSC
= driWaitForMSC32
,
920 .SwapBuffersMSC
= NULL
925 * This is the bootstrap function for the driver. libGL supplies all of the
926 * requisite information about the system, and the driver initializes itself.
927 * This routine also fills in the linked list pointed to by \c driver_modes
928 * with the \c __GLcontextModes that the driver can support for windows or
931 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
935 void * __driCreateNewScreen_20050727( __DRInativeDisplay
*dpy
, int scrn
, __DRIscreen
*psc
,
936 const __GLcontextModes
* modes
,
937 const __DRIversion
* ddx_version
,
938 const __DRIversion
* dri_version
,
939 const __DRIversion
* drm_version
,
940 const __DRIframebuffer
* frame_buffer
,
941 drmAddress pSAREA
, int fd
,
942 int internal_api_version
,
943 const __DRIinterfaceMethods
* interface
,
944 __GLcontextModes
** driver_modes
)
947 __DRIscreenPrivate
*psp
;
948 static const __DRIversion ddx_expected
= { 1, 1, 1 };
949 static const __DRIversion dri_expected
= { 4, 0, 0 };
950 static const __DRIversion drm_expected
= { 3, 0, 0 };
952 dri_interface
= interface
;
954 if ( ! driCheckDriDdxDrmVersions2( "MGA",
955 dri_version
, & dri_expected
,
956 ddx_version
, & ddx_expected
,
957 drm_version
, & drm_expected
) ) {
961 psp
= __driUtilCreateNewScreen(dpy
, scrn
, psc
, NULL
,
962 ddx_version
, dri_version
, drm_version
,
963 frame_buffer
, pSAREA
, fd
,
964 internal_api_version
, &mgaAPI
);
966 MGADRIPtr dri_priv
= (MGADRIPtr
) psp
->pDevPriv
;
967 *driver_modes
= mgaFillInModes( dri_priv
->cpp
* 8,
968 (dri_priv
->cpp
== 2) ? 16 : 24,
969 (dri_priv
->cpp
== 2) ? 0 : 8,
970 (dri_priv
->backOffset
!= dri_priv
->depthOffset
) );
972 /* Calling driInitExtensions here, with a NULL context pointer, does not actually
973 * enable the extensions. It just makes sure that all the dispatch offsets for all
974 * the extensions that *might* be enables are known. This is needed because the
975 * dispatch offsets need to be known when _mesa_context_create is called, but we can't
976 * enable the extensions until we have a context pointer.
978 * Hello chicken. Hello egg. How are you two today?
980 driInitExtensions( NULL
, card_extensions
, GL_FALSE
);
981 driInitExtensions( NULL
, g400_extensions
, GL_FALSE
);
982 driInitSingleExtension( NULL
, ARB_vp_extension
);
983 driInitExtensions( NULL
, NV_vp_extensions
, GL_FALSE
);
992 * Get information about previous buffer swaps.
995 getSwapInfo( __DRIdrawablePrivate
*dPriv
, __DRIswapInfo
* sInfo
)
999 if ( (dPriv
== NULL
) || (dPriv
->driContextPriv
== NULL
)
1000 || (dPriv
->driContextPriv
->driverPrivate
== NULL
)
1001 || (sInfo
== NULL
) ) {
1005 mmesa
= (mgaContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
1006 sInfo
->swap_count
= mmesa
->swap_count
;
1007 sInfo
->swap_ust
= mmesa
->swap_ust
;
1008 sInfo
->swap_missed_count
= mmesa
->swap_missed_count
;
1010 sInfo
->swap_missed_usage
= (sInfo
->swap_missed_count
!= 0)
1011 ? driCalculateSwapUsage( dPriv
, 0, mmesa
->swap_missed_ust
)