Also PUBLICize the config option table
[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 <stdlib.h>
30 #include "drm.h"
31 #include "mga_drm.h"
32 #include "mga_xmesa.h"
33 #include "context.h"
34 #include "matrix.h"
35 #include "simple_list.h"
36 #include "imports.h"
37
38 #include "swrast/swrast.h"
39 #include "swrast_setup/swrast_setup.h"
40 #include "tnl/tnl.h"
41 #include "array_cache/acache.h"
42
43 #include "tnl/t_pipeline.h"
44
45 #include "drivers/common/driverfuncs.h"
46
47 #include "mgadd.h"
48 #include "mgastate.h"
49 #include "mgatex.h"
50 #include "mgaspan.h"
51 #include "mgaioctl.h"
52 #include "mgatris.h"
53 #include "mgavb.h"
54 #include "mgapixel.h"
55 #include "mga_xmesa.h"
56 #include "mga_dri.h"
57
58
59 #include "utils.h"
60 #include "vblank.h"
61
62 #include "extensions.h"
63
64 #include "GL/internal/dri_interface.h"
65
66 /* MGA configuration
67 */
68 #include "xmlpool.h"
69
70 PUBLIC const char __driConfigOptions[] =
71 DRI_CONF_BEGIN
72 DRI_CONF_SECTION_PERFORMANCE
73 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
74 DRI_CONF_SECTION_END
75 DRI_CONF_SECTION_QUALITY
76 DRI_CONF_TEXTURE_DEPTH(DRI_CONF_TEXTURE_DEPTH_FB)
77 DRI_CONF_COLOR_REDUCTION(DRI_CONF_COLOR_REDUCTION_DITHER)
78 DRI_CONF_SECTION_END
79 DRI_CONF_SECTION_SOFTWARE
80 DRI_CONF_ARB_VERTEX_PROGRAM(true)
81 DRI_CONF_NV_VERTEX_PROGRAM(true)
82 DRI_CONF_SECTION_END
83 DRI_CONF_END;
84 static const GLuint __driNConfigOptions = 5;
85
86 #ifdef USE_NEW_INTERFACE
87 static PFNGLXCREATECONTEXTMODES create_context_modes = NULL;
88 #endif /* USE_NEW_INTERFACE */
89
90 #ifndef MGA_DEBUG
91 int MGA_DEBUG = 0;
92 #endif
93
94 static int getSwapInfo( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo );
95
96 #ifdef USE_NEW_INTERFACE
97 static __GLcontextModes *
98 mgaFillInModes( unsigned pixel_bits, unsigned depth_bits,
99 unsigned stencil_bits, GLboolean have_back_buffer )
100 {
101 __GLcontextModes * modes;
102 __GLcontextModes * m;
103 unsigned num_modes;
104 unsigned depth_buffer_factor;
105 unsigned back_buffer_factor;
106 GLenum fb_format;
107 GLenum fb_type;
108
109 /* GLX_SWAP_COPY_OML is only supported because the MGA driver doesn't
110 * support pageflipping at all.
111 */
112 static const GLenum back_buffer_modes[] = {
113 GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML
114 };
115
116 u_int8_t depth_bits_array[3];
117 u_int8_t stencil_bits_array[3];
118
119
120 depth_bits_array[0] = 0;
121 depth_bits_array[1] = depth_bits;
122 depth_bits_array[2] = depth_bits;
123
124 /* Just like with the accumulation buffer, always provide some modes
125 * with a stencil buffer. It will be a sw fallback, but some apps won't
126 * care about that.
127 */
128 stencil_bits_array[0] = 0;
129 stencil_bits_array[1] = 0;
130 stencil_bits_array[2] = (stencil_bits == 0) ? 8 : stencil_bits;
131
132 depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 3 : 1;
133 back_buffer_factor = (have_back_buffer) ? 2 : 1;
134
135 num_modes = depth_buffer_factor * back_buffer_factor * 4;
136
137 if ( pixel_bits == 16 ) {
138 fb_format = GL_RGB;
139 fb_type = GL_UNSIGNED_SHORT_5_6_5;
140 }
141 else {
142 fb_format = GL_BGR;
143 fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
144 }
145
146 modes = (*create_context_modes)( num_modes, sizeof( __GLcontextModes ) );
147 m = modes;
148 if ( ! driFillInModes( & m, fb_format, fb_type,
149 depth_bits_array, stencil_bits_array, depth_buffer_factor,
150 back_buffer_modes, back_buffer_factor,
151 GLX_TRUE_COLOR ) ) {
152 fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
153 __func__, __LINE__ );
154 return NULL;
155 }
156
157 if ( ! driFillInModes( & m, fb_format, fb_type,
158 depth_bits_array, stencil_bits_array, depth_buffer_factor,
159 back_buffer_modes, back_buffer_factor,
160 GLX_DIRECT_COLOR ) ) {
161 fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
162 __func__, __LINE__ );
163 return NULL;
164 }
165
166 /* Mark the visual as slow if there are "fake" stencil bits.
167 */
168 for ( m = modes ; m != NULL ; m = m->next ) {
169 if ( (m->stencilBits != 0) && (m->stencilBits != stencil_bits) ) {
170 m->visualRating = GLX_SLOW_CONFIG;
171 }
172 }
173
174 return modes;
175 }
176 #endif /* USE_NEW_INTERFACE */
177
178
179 static GLboolean
180 mgaInitDriver(__DRIscreenPrivate *sPriv)
181 {
182 mgaScreenPrivate *mgaScreen;
183 MGADRIPtr serverInfo = (MGADRIPtr)sPriv->pDevPriv;
184
185
186 /* Allocate the private area */
187 mgaScreen = (mgaScreenPrivate *)MALLOC(sizeof(mgaScreenPrivate));
188 if (!mgaScreen) {
189 __driUtilMessage("Couldn't malloc screen struct");
190 return GL_FALSE;
191 }
192
193 mgaScreen->sPriv = sPriv;
194 sPriv->private = (void *)mgaScreen;
195
196 if (sPriv->drmMinor >= 1) {
197 int ret;
198 drm_mga_getparam_t gp;
199
200 gp.param = MGA_PARAM_IRQ_NR;
201 gp.value = &mgaScreen->irq;
202 mgaScreen->irq = 0;
203
204 ret = drmCommandWriteRead( sPriv->fd, DRM_MGA_GETPARAM,
205 &gp, sizeof(gp));
206 if (ret) {
207 fprintf(stderr, "drmMgaGetParam (MGA_PARAM_IRQ_NR): %d\n", ret);
208 FREE(mgaScreen);
209 sPriv->private = NULL;
210 return GL_FALSE;
211 }
212 }
213
214 mgaScreen->linecomp_sane = (sPriv->ddxMajor > 1) || (sPriv->ddxMinor > 1)
215 || ((sPriv->ddxMinor == 1) && (sPriv->ddxPatch > 0));
216
217 if ( driCompareGLXAPIVersion( 20030813 ) >= 0 ) {
218 PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension =
219 (PFNGLXSCRENABLEEXTENSIONPROC) glXGetProcAddress( (const GLubyte *) "__glXScrEnableExtension" );
220 void * const psc = sPriv->psc->screenConfigs;
221
222 if ( glx_enable_extension != NULL ) {
223 if ( mgaScreen->linecomp_sane ) {
224 (*glx_enable_extension)( psc, "GLX_SGI_swap_control" );
225 (*glx_enable_extension)( psc, "GLX_SGI_video_sync" );
226 (*glx_enable_extension)( psc, "GLX_MESA_swap_control" );
227 }
228
229 (*glx_enable_extension)( psc, "GLX_SGI_make_current_read" );
230 (*glx_enable_extension)( psc, "GLX_MESA_swap_frame_usage" );
231
232 if ( driCompareGLXAPIVersion( 20030915 ) >= 0 ) {
233 (*glx_enable_extension)( psc, "GLX_SGIX_fbconfig" );
234 (*glx_enable_extension)( psc, "GLX_OML_swap_method" );
235 }
236 }
237 }
238
239 if (serverInfo->chipset != MGA_CARD_TYPE_G200 &&
240 serverInfo->chipset != MGA_CARD_TYPE_G400) {
241 FREE(mgaScreen);
242 sPriv->private = NULL;
243 __driUtilMessage("Unrecognized chipset");
244 return GL_FALSE;
245 }
246
247
248 mgaScreen->chipset = serverInfo->chipset;
249 mgaScreen->width = serverInfo->width;
250 mgaScreen->height = serverInfo->height;
251 mgaScreen->mem = serverInfo->mem;
252 mgaScreen->cpp = serverInfo->cpp;
253
254 mgaScreen->agpMode = serverInfo->agpMode;
255
256 mgaScreen->frontPitch = serverInfo->frontPitch;
257 mgaScreen->frontOffset = serverInfo->frontOffset;
258 mgaScreen->backOffset = serverInfo->backOffset;
259 mgaScreen->backPitch = serverInfo->backPitch;
260 mgaScreen->depthOffset = serverInfo->depthOffset;
261 mgaScreen->depthPitch = serverInfo->depthPitch;
262
263 mgaScreen->mmio.handle = serverInfo->registers.handle;
264 mgaScreen->mmio.size = serverInfo->registers.size;
265 if ( drmMap( sPriv->fd,
266 mgaScreen->mmio.handle, mgaScreen->mmio.size,
267 &mgaScreen->mmio.map ) < 0 ) {
268 FREE( mgaScreen );
269 sPriv->private = NULL;
270 __driUtilMessage( "Couldn't map MMIO registers" );
271 return GL_FALSE;
272 }
273
274 mgaScreen->primary.handle = serverInfo->primary.handle;
275 mgaScreen->primary.size = serverInfo->primary.size;
276 mgaScreen->buffers.handle = serverInfo->buffers.handle;
277 mgaScreen->buffers.size = serverInfo->buffers.size;
278
279 #if 0
280 mgaScreen->agp.handle = serverInfo->agp;
281 mgaScreen->agp.size = serverInfo->agpSize;
282
283 if (drmMap(sPriv->fd,
284 mgaScreen->agp.handle,
285 mgaScreen->agp.size,
286 (drmAddress *)&mgaScreen->agp.map) != 0)
287 {
288 Xfree(mgaScreen);
289 sPriv->private = NULL;
290 __driUtilMessage("Couldn't map agp region");
291 return GL_FALSE;
292 }
293 #endif
294
295 mgaScreen->textureOffset[MGA_CARD_HEAP] = serverInfo->textureOffset;
296 mgaScreen->textureOffset[MGA_AGP_HEAP] = (serverInfo->agpTextureOffset |
297 PDEA_pagpxfer_enable | 1);
298
299 mgaScreen->textureSize[MGA_CARD_HEAP] = serverInfo->textureSize;
300 mgaScreen->textureSize[MGA_AGP_HEAP] = serverInfo->agpTextureSize;
301
302 mgaScreen->logTextureGranularity[MGA_CARD_HEAP] =
303 serverInfo->logTextureGranularity;
304 mgaScreen->logTextureGranularity[MGA_AGP_HEAP] =
305 serverInfo->logAgpTextureGranularity;
306
307 mgaScreen->texVirtual[MGA_CARD_HEAP] = (char *)(mgaScreen->sPriv->pFB +
308 serverInfo->textureOffset);
309 if (drmMap(sPriv->fd,
310 serverInfo->agpTextureOffset,
311 serverInfo->agpTextureSize,
312 (drmAddress *)&mgaScreen->texVirtual[MGA_AGP_HEAP]) != 0)
313 {
314 FREE(mgaScreen);
315 sPriv->private = NULL;
316 __driUtilMessage("Couldn't map agptexture region");
317 return GL_FALSE;
318 }
319
320 #if 0
321 mgaScreen->texVirtual[MGA_AGP_HEAP] = (mgaScreen->agp.map +
322 serverInfo->agpTextureOffset);
323 #endif
324
325 mgaScreen->mAccess = serverInfo->mAccess;
326
327 /* For calculating setupdma addresses.
328 */
329 mgaScreen->dmaOffset = serverInfo->buffers.handle;
330
331 mgaScreen->bufs = drmMapBufs(sPriv->fd);
332 if (!mgaScreen->bufs) {
333 /*drmUnmap(mgaScreen->agp_tex.map, mgaScreen->agp_tex.size);*/
334 FREE(mgaScreen);
335 sPriv->private = NULL;
336 __driUtilMessage("Couldn't map dma buffers");
337 return GL_FALSE;
338 }
339 mgaScreen->sarea_priv_offset = serverInfo->sarea_priv_offset;
340
341 /* parse information in __driConfigOptions */
342 driParseOptionInfo (&mgaScreen->optionCache,
343 __driConfigOptions, __driNConfigOptions);
344
345 return GL_TRUE;
346 }
347
348
349 static void
350 mgaDestroyScreen(__DRIscreenPrivate *sPriv)
351 {
352 mgaScreenPrivate *mgaScreen = (mgaScreenPrivate *) sPriv->private;
353
354 if (MGA_DEBUG&DEBUG_VERBOSE_DRI)
355 fprintf(stderr, "mgaDestroyScreen\n");
356
357 drmUnmapBufs(mgaScreen->bufs);
358
359 /*drmUnmap(mgaScreen->agp_tex.map, mgaScreen->agp_tex.size);*/
360
361 /* free all option information */
362 driDestroyOptionInfo (&mgaScreen->optionCache);
363
364 FREE(mgaScreen);
365 sPriv->private = NULL;
366 }
367
368
369 extern const struct tnl_pipeline_stage _mga_render_stage;
370
371 static const struct tnl_pipeline_stage *mga_pipeline[] = {
372 &_tnl_vertex_transform_stage,
373 &_tnl_normal_transform_stage,
374 &_tnl_lighting_stage,
375 &_tnl_fog_coordinate_stage,
376 &_tnl_texgen_stage,
377 &_tnl_texture_transform_stage,
378 &_tnl_vertex_program_stage,
379
380 /* REMOVE: point attenuation stage */
381 #if 0
382 &_mga_render_stage, /* ADD: unclipped rastersetup-to-dma */
383 /* Need new ioctl for wacceptseq */
384 #endif
385 &_tnl_render_stage,
386 0,
387 };
388
389
390 static const char * const g400_extensions[] =
391 {
392 "GL_ARB_multitexture",
393 "GL_ARB_texture_env_add",
394 "GL_ARB_texture_env_combine",
395 "GL_ARB_texture_env_crossbar",
396 "GL_EXT_texture_env_combine",
397 "GL_EXT_texture_edge_clamp",
398 "GL_ATI_texture_env_combine3",
399 #if defined (MESA_packed_depth_stencil)
400 "GL_MESA_packed_depth_stencil",
401 #endif
402 NULL
403 };
404
405 static const char * const card_extensions[] =
406 {
407 "GL_ARB_multisample",
408 "GL_ARB_texture_compression",
409 "GL_ARB_texture_rectangle",
410 "GL_EXT_blend_logic_op",
411 "GL_EXT_fog_coord",
412 "GL_EXT_multi_draw_arrays",
413 /* paletted_textures currently doesn't work, but we could fix them later */
414 #if 0
415 "GL_EXT_shared_texture_palette",
416 "GL_EXT_paletted_texture",
417 #endif
418 "GL_EXT_secondary_color",
419 "GL_EXT_stencil_wrap",
420 "GL_MESA_ycbcr_texture",
421 "GL_SGIS_generate_mipmap",
422 NULL
423 };
424
425 static const struct dri_debug_control debug_control[] =
426 {
427 { "fall", DEBUG_VERBOSE_FALLBACK },
428 { "tex", DEBUG_VERBOSE_TEXTURE },
429 { "ioctl", DEBUG_VERBOSE_IOCTL },
430 { "verb", DEBUG_VERBOSE_MSG },
431 { "dri", DEBUG_VERBOSE_DRI },
432 { NULL, 0 }
433 };
434
435
436 static int
437 get_ust_nop( int64_t * ust )
438 {
439 *ust = 1;
440 return 0;
441 }
442
443
444 static GLboolean
445 mgaCreateContext( const __GLcontextModes *mesaVis,
446 __DRIcontextPrivate *driContextPriv,
447 void *sharedContextPrivate )
448 {
449 int i;
450 unsigned maxlevels;
451 GLcontext *ctx, *shareCtx;
452 mgaContextPtr mmesa;
453 __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
454 mgaScreenPrivate *mgaScreen = (mgaScreenPrivate *)sPriv->private;
455 drm_mga_sarea_t *saPriv = (drm_mga_sarea_t *)(((char*)sPriv->pSAREA)+
456 mgaScreen->sarea_priv_offset);
457 struct dd_function_table functions;
458
459 if (MGA_DEBUG&DEBUG_VERBOSE_DRI)
460 fprintf(stderr, "mgaCreateContext\n");
461
462 /* allocate mga context */
463 mmesa = (mgaContextPtr) CALLOC(sizeof(mgaContext));
464 if (!mmesa) {
465 return GL_FALSE;
466 }
467
468 /* Init default driver functions then plug in our Radeon-specific functions
469 * (the texture functions are especially important)
470 */
471 _mesa_init_driver_functions( &functions );
472 mgaInitDriverFuncs( &functions );
473 mgaInitTextureFuncs( &functions );
474 mgaInitIoctlFuncs( &functions );
475
476 /* Allocate the Mesa context */
477 if (sharedContextPrivate)
478 shareCtx = ((mgaContextPtr) sharedContextPrivate)->glCtx;
479 else
480 shareCtx = NULL;
481 mmesa->glCtx = _mesa_create_context(mesaVis, shareCtx,
482 &functions, (void *) mmesa);
483 if (!mmesa->glCtx) {
484 FREE(mmesa);
485 return GL_FALSE;
486 }
487 driContextPriv->driverPrivate = mmesa;
488
489 /* Init mga state */
490 mmesa->hHWContext = driContextPriv->hHWContext;
491 mmesa->driFd = sPriv->fd;
492 mmesa->driHwLock = &sPriv->pSAREA->lock;
493
494 mmesa->mgaScreen = mgaScreen;
495 mmesa->driScreen = sPriv;
496 mmesa->sarea = (void *)saPriv;
497
498 /* Parse configuration files */
499 driParseConfigFiles (&mmesa->optionCache, &mgaScreen->optionCache,
500 sPriv->myNum, "mga");
501
502 (void) memset( mmesa->texture_heaps, 0, sizeof( mmesa->texture_heaps ) );
503 make_empty_list( & mmesa->swapped );
504
505 mmesa->nr_heaps = mgaScreen->texVirtual[MGA_AGP_HEAP] ? 2 : 1;
506 for ( i = 0 ; i < mmesa->nr_heaps ; i++ ) {
507 mmesa->texture_heaps[i] = driCreateTextureHeap( i, mmesa,
508 mgaScreen->textureSize[i],
509 6,
510 MGA_NR_TEX_REGIONS,
511 (drmTextureRegionPtr)mmesa->sarea->texList[i],
512 &mmesa->sarea->texAge[i],
513 &mmesa->swapped,
514 sizeof( mgaTextureObject_t ),
515 (destroy_texture_object_t *) mgaDestroyTexObj );
516 }
517
518 /* Set the maximum texture size small enough that we can guarentee
519 * that both texture units can bind a maximal texture and have them
520 * on the card at once.
521 */
522 ctx = mmesa->glCtx;
523 if ( mgaScreen->chipset == MGA_CARD_TYPE_G200 ) {
524 ctx->Const.MaxTextureUnits = 1;
525 ctx->Const.MaxTextureImageUnits = 1;
526 ctx->Const.MaxTextureCoordUnits = 1;
527 maxlevels = G200_TEX_MAXLEVELS;
528
529 }
530 else {
531 ctx->Const.MaxTextureUnits = 2;
532 ctx->Const.MaxTextureImageUnits = 2;
533 ctx->Const.MaxTextureCoordUnits = 2;
534 maxlevels = G400_TEX_MAXLEVELS;
535 }
536
537 driCalculateMaxTextureLevels( mmesa->texture_heaps,
538 mmesa->nr_heaps,
539 & ctx->Const,
540 4,
541 11, /* max 2D texture size is 2048x2048 */
542 0, /* 3D textures unsupported. */
543 0, /* cube textures unsupported. */
544 11, /* max texture rect size is 2048x2048 */
545 maxlevels,
546 GL_FALSE );
547
548 ctx->Const.MinLineWidth = 1.0;
549 ctx->Const.MinLineWidthAA = 1.0;
550 ctx->Const.MaxLineWidth = 10.0;
551 ctx->Const.MaxLineWidthAA = 10.0;
552 ctx->Const.LineWidthGranularity = 1.0;
553
554 mmesa->texture_depth = driQueryOptioni (&mmesa->optionCache,
555 "texture_depth");
556 if (mmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FB)
557 mmesa->texture_depth = ( mesaVis->rgbBits >= 24 ) ?
558 DRI_CONF_TEXTURE_DEPTH_32 : DRI_CONF_TEXTURE_DEPTH_16;
559 mmesa->hw_stencil = mesaVis->stencilBits && mesaVis->depthBits == 24;
560
561 switch (mesaVis->depthBits) {
562 case 16:
563 mmesa->depth_scale = 1.0/(GLdouble)0xffff;
564 mmesa->depth_clear_mask = ~0;
565 mmesa->ClearDepth = 0xffff;
566 break;
567 case 24:
568 mmesa->depth_scale = 1.0/(GLdouble)0xffffff;
569 if (mmesa->hw_stencil) {
570 mmesa->depth_clear_mask = 0xffffff00;
571 mmesa->stencil_clear_mask = 0x000000ff;
572 } else
573 mmesa->depth_clear_mask = ~0;
574 mmesa->ClearDepth = 0xffffff00;
575 break;
576 case 32:
577 mmesa->depth_scale = 1.0/(GLdouble)0xffffffff;
578 mmesa->depth_clear_mask = ~0;
579 mmesa->ClearDepth = 0xffffffff;
580 break;
581 };
582
583 mmesa->haveHwStipple = GL_FALSE;
584 mmesa->RenderIndex = -1; /* impossible value */
585 mmesa->dirty = ~0;
586 mmesa->vertex_format = 0;
587 mmesa->CurrentTexObj[0] = 0;
588 mmesa->CurrentTexObj[1] = 0;
589 mmesa->tmu_source[0] = 0;
590 mmesa->tmu_source[1] = 1;
591
592 mmesa->texAge[0] = 0;
593 mmesa->texAge[1] = 0;
594
595 /* Initialize the software rasterizer and helper modules.
596 */
597 _swrast_CreateContext( ctx );
598 _ac_CreateContext( ctx );
599 _tnl_CreateContext( ctx );
600
601 _swsetup_CreateContext( ctx );
602
603 /* Install the customized pipeline:
604 */
605 _tnl_destroy_pipeline( ctx );
606 _tnl_install_pipeline( ctx, mga_pipeline );
607
608 /* Configure swrast and T&L to match hardware characteristics:
609 */
610 _swrast_allow_pixel_fog( ctx, GL_FALSE );
611 _swrast_allow_vertex_fog( ctx, GL_TRUE );
612 _tnl_allow_pixel_fog( ctx, GL_FALSE );
613 _tnl_allow_vertex_fog( ctx, GL_TRUE );
614
615 mmesa->primary_offset = mmesa->mgaScreen->primary.handle;
616
617 ctx->DriverCtx = (void *) mmesa;
618 mmesa->glCtx = ctx;
619
620 driInitExtensions( ctx, card_extensions, GL_FALSE );
621
622 if (MGA_IS_G400(MGA_CONTEXT(ctx))) {
623 driInitExtensions( ctx, g400_extensions, GL_FALSE );
624 }
625
626 if ( driQueryOptionb( &mmesa->optionCache, "arb_vertex_program" ) ) {
627 _mesa_enable_extension( ctx, "GL_ARB_vertex_program" );
628 }
629
630 if ( driQueryOptionb( &mmesa->optionCache, "nv_vertex_program" ) ) {
631 _mesa_enable_extension( ctx, "GL_NV_vertex_program" );
632 _mesa_enable_extension( ctx, "GL_NV_vertex_program1_1" );
633 }
634
635
636 /* XXX these should really go right after _mesa_init_driver_functions() */
637 mgaDDInitStateFuncs( ctx );
638 mgaDDInitSpanFuncs( ctx );
639 mgaDDInitPixelFuncs( ctx );
640 mgaDDInitTriFuncs( ctx );
641
642 mgaInitVB( ctx );
643 mgaInitState( mmesa );
644
645 driContextPriv->driverPrivate = (void *) mmesa;
646
647 #if DO_DEBUG
648 MGA_DEBUG = driParseDebugString( getenv( "MGA_DEBUG" ),
649 debug_control );
650 #endif
651
652 mmesa->vblank_flags = ((mmesa->mgaScreen->irq == 0)
653 || !mmesa->mgaScreen->linecomp_sane)
654 ? VBLANK_FLAG_NO_IRQ : driGetDefaultVBlankFlags(&mmesa->optionCache);
655
656 mmesa->get_ust = (PFNGLXGETUSTPROC) glXGetProcAddress( (const GLubyte *) "__glXGetUST" );
657 if ( mmesa->get_ust == NULL ) {
658 mmesa->get_ust = get_ust_nop;
659 }
660
661 (*mmesa->get_ust)( & mmesa->swap_ust );
662
663 return GL_TRUE;
664 }
665
666 static void
667 mgaDestroyContext(__DRIcontextPrivate *driContextPriv)
668 {
669 mgaContextPtr mmesa = (mgaContextPtr) driContextPriv->driverPrivate;
670
671 if (MGA_DEBUG&DEBUG_VERBOSE_DRI)
672 fprintf( stderr, "[%s:%d] mgaDestroyContext start\n",
673 __FILE__, __LINE__ );
674
675 assert(mmesa); /* should never be null */
676 if (mmesa) {
677 GLboolean release_texture_heaps;
678
679
680 release_texture_heaps = (mmesa->glCtx->Shared->RefCount == 1);
681 _swsetup_DestroyContext( mmesa->glCtx );
682 _tnl_DestroyContext( mmesa->glCtx );
683 _ac_DestroyContext( mmesa->glCtx );
684 _swrast_DestroyContext( mmesa->glCtx );
685
686 mgaFreeVB( mmesa->glCtx );
687
688 /* free the Mesa context */
689 mmesa->glCtx->DriverCtx = NULL;
690 _mesa_destroy_context(mmesa->glCtx);
691
692 if ( release_texture_heaps ) {
693 /* This share group is about to go away, free our private
694 * texture object data.
695 */
696 int i;
697
698 for ( i = 0 ; i < mmesa->nr_heaps ; i++ ) {
699 driDestroyTextureHeap( mmesa->texture_heaps[ i ] );
700 mmesa->texture_heaps[ i ] = NULL;
701 }
702
703 assert( is_empty_list( & mmesa->swapped ) );
704 }
705
706 /* free the option cache */
707 driDestroyOptionCache (&mmesa->optionCache);
708
709 FREE(mmesa);
710 }
711
712 if (MGA_DEBUG&DEBUG_VERBOSE_DRI)
713 fprintf( stderr, "[%s:%d] mgaDestroyContext done\n",
714 __FILE__, __LINE__ );
715 }
716
717
718 static GLboolean
719 mgaCreateBuffer( __DRIscreenPrivate *driScrnPriv,
720 __DRIdrawablePrivate *driDrawPriv,
721 const __GLcontextModes *mesaVis,
722 GLboolean isPixmap )
723 {
724 if (isPixmap) {
725 return GL_FALSE; /* not implemented */
726 }
727 else {
728 GLboolean swStencil = (mesaVis->stencilBits > 0 &&
729 mesaVis->depthBits != 24);
730
731 driDrawPriv->driverPrivate = (void *)
732 _mesa_create_framebuffer(mesaVis,
733 GL_FALSE, /* software depth buffer? */
734 swStencil,
735 mesaVis->accumRedBits > 0,
736 mesaVis->alphaBits > 0 );
737
738 return (driDrawPriv->driverPrivate != NULL);
739 }
740 }
741
742
743 static void
744 mgaDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
745 {
746 _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
747 }
748
749 static void
750 mgaSwapBuffers(__DRIdrawablePrivate *dPriv)
751 {
752 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
753 mgaContextPtr mmesa;
754 GLcontext *ctx;
755 mmesa = (mgaContextPtr) dPriv->driContextPriv->driverPrivate;
756 ctx = mmesa->glCtx;
757
758 if (ctx->Visual.doubleBufferMode) {
759 _mesa_notifySwapBuffers( ctx );
760 mgaCopyBuffer( dPriv );
761 }
762 } else {
763 /* XXX this shouldn't be an error but we can't handle it for now */
764 _mesa_problem(NULL, "%s: drawable has no context!\n", __FUNCTION__);
765 }
766 }
767
768 static GLboolean
769 mgaUnbindContext(__DRIcontextPrivate *driContextPriv)
770 {
771 mgaContextPtr mmesa = (mgaContextPtr) driContextPriv->driverPrivate;
772 if (mmesa)
773 mmesa->dirty = ~0;
774
775 return GL_TRUE;
776 }
777
778 /* This looks buggy to me - the 'b' variable isn't used anywhere...
779 * Hmm - It seems that the drawable is already hooked in to
780 * driDrawablePriv.
781 *
782 * But why are we doing context initialization here???
783 */
784 static GLboolean
785 mgaMakeCurrent(__DRIcontextPrivate *driContextPriv,
786 __DRIdrawablePrivate *driDrawPriv,
787 __DRIdrawablePrivate *driReadPriv)
788 {
789 if (driContextPriv) {
790 mgaContextPtr mmesa = (mgaContextPtr) driContextPriv->driverPrivate;
791
792 if (mmesa->driDrawable != driDrawPriv) {
793 driDrawableInitVBlank( driDrawPriv, mmesa->vblank_flags );
794 mmesa->driDrawable = driDrawPriv;
795 mmesa->dirty = ~0;
796 mmesa->dirty_cliprects = (MGA_FRONT|MGA_BACK);
797 mmesa->mesa_drawable = driDrawPriv;
798 }
799
800 mmesa->driReadable = driReadPriv;
801
802 _mesa_make_current2(mmesa->glCtx,
803 (GLframebuffer *) driDrawPriv->driverPrivate,
804 (GLframebuffer *) driReadPriv->driverPrivate);
805 }
806 else {
807 _mesa_make_current(NULL, NULL);
808 }
809
810 return GL_TRUE;
811 }
812
813
814 void mgaGetLock( mgaContextPtr mmesa, GLuint flags )
815 {
816 __DRIdrawablePrivate *dPriv = mmesa->driDrawable;
817 drm_mga_sarea_t *sarea = mmesa->sarea;
818 int me = mmesa->hHWContext;
819 int i;
820
821 drmGetLock(mmesa->driFd, mmesa->hHWContext, flags);
822
823 if (*(dPriv->pStamp) != mmesa->lastStamp) {
824 mmesa->lastStamp = *(dPriv->pStamp);
825 mmesa->SetupNewInputs |= VERT_BIT_POS;
826 mmesa->dirty_cliprects = (MGA_FRONT|MGA_BACK);
827 mgaUpdateRects( mmesa, (MGA_FRONT|MGA_BACK) );
828 }
829
830 mmesa->dirty |= MGA_UPLOAD_CONTEXT | MGA_UPLOAD_CLIPRECTS;
831
832 mmesa->sarea->dirty |= MGA_UPLOAD_CONTEXT;
833
834 if (sarea->ctxOwner != me) {
835 mmesa->dirty |= (MGA_UPLOAD_CONTEXT | MGA_UPLOAD_TEX0 |
836 MGA_UPLOAD_TEX1 | MGA_UPLOAD_PIPE);
837 sarea->ctxOwner=me;
838 }
839
840 for ( i = 0 ; i < mmesa->nr_heaps ; i++ ) {
841 DRI_AGE_TEXTURES( mmesa->texture_heaps[ i ] );
842 }
843
844 sarea->last_quiescent = -1; /* just kill it for now */
845 }
846
847
848 static const struct __DriverAPIRec mgaAPI = {
849 .InitDriver = mgaInitDriver,
850 .DestroyScreen = mgaDestroyScreen,
851 .CreateContext = mgaCreateContext,
852 .DestroyContext = mgaDestroyContext,
853 .CreateBuffer = mgaCreateBuffer,
854 .DestroyBuffer = mgaDestroyBuffer,
855 .SwapBuffers = mgaSwapBuffers,
856 .MakeCurrent = mgaMakeCurrent,
857 .UnbindContext = mgaUnbindContext,
858 .GetSwapInfo = getSwapInfo,
859 .GetMSC = driGetMSC32,
860 .WaitForMSC = driWaitForMSC32,
861 .WaitForSBC = NULL,
862 .SwapBuffersMSC = NULL
863 };
864
865
866 /*
867 * This is the bootstrap function for the driver.
868 * The __driCreateScreen name is the symbol that libGL.so fetches.
869 * Return: pointer to a __DRIscreenPrivate.
870 */
871 #if !defined(DRI_NEW_INTERFACE_ONLY)
872 void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
873 int numConfigs, __GLXvisualConfig *config)
874 {
875 __DRIscreenPrivate *psp;
876 psp = __driUtilCreateScreen(dpy, scrn, psc, numConfigs, config, &mgaAPI);
877 return (void *) psp;
878 }
879 #endif /* !defined(DRI_NEW_INTERFACE_ONLY) */
880
881
882 /**
883 * This is the bootstrap function for the driver. libGL supplies all of the
884 * requisite information about the system, and the driver initializes itself.
885 * This routine also fills in the linked list pointed to by \c driver_modes
886 * with the \c __GLcontextModes that the driver can support for windows or
887 * pbuffers.
888 *
889 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
890 * failure.
891 */
892 #ifdef USE_NEW_INTERFACE
893 PUBLIC
894 void * __driCreateNewScreen( __DRInativeDisplay *dpy, int scrn, __DRIscreen *psc,
895 const __GLcontextModes * modes,
896 const __DRIversion * ddx_version,
897 const __DRIversion * dri_version,
898 const __DRIversion * drm_version,
899 const __DRIframebuffer * frame_buffer,
900 drmAddress pSAREA, int fd,
901 int internal_api_version,
902 __GLcontextModes ** driver_modes )
903
904 {
905 __DRIscreenPrivate *psp;
906 static const __DRIversion ddx_expected = { 1, 0, 0 };
907 static const __DRIversion dri_expected = { 4, 0, 0 };
908 static const __DRIversion drm_expected = { 3, 0, 0 };
909
910 if ( ! driCheckDriDdxDrmVersions2( "MGA",
911 dri_version, & dri_expected,
912 ddx_version, & ddx_expected,
913 drm_version, & drm_expected ) ) {
914 return NULL;
915 }
916
917 psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL,
918 ddx_version, dri_version, drm_version,
919 frame_buffer, pSAREA, fd,
920 internal_api_version, &mgaAPI);
921 if ( psp != NULL ) {
922 create_context_modes = (PFNGLXCREATECONTEXTMODES)
923 glXGetProcAddress( (const GLubyte *) "__glXCreateContextModes" );
924 if ( create_context_modes != NULL ) {
925 MGADRIPtr dri_priv = (MGADRIPtr) psp->pDevPriv;
926 *driver_modes = mgaFillInModes( dri_priv->cpp * 8,
927 (dri_priv->cpp == 2) ? 16 : 24,
928 (dri_priv->cpp == 2) ? 0 : 8,
929 (dri_priv->backOffset != dri_priv->depthOffset) );
930 }
931 }
932
933 return (void *) psp;
934 }
935 #endif /* USE_NEW_INTERFACE */
936
937
938 /**
939 * Get information about previous buffer swaps.
940 */
941 static int
942 getSwapInfo( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo )
943 {
944 mgaContextPtr mmesa;
945
946 if ( (dPriv == NULL) || (dPriv->driContextPriv == NULL)
947 || (dPriv->driContextPriv->driverPrivate == NULL)
948 || (sInfo == NULL) ) {
949 return -1;
950 }
951
952 mmesa = (mgaContextPtr) dPriv->driContextPriv->driverPrivate;
953 sInfo->swap_count = mmesa->swap_count;
954 sInfo->swap_ust = mmesa->swap_ust;
955 sInfo->swap_missed_count = mmesa->swap_missed_count;
956
957 sInfo->swap_missed_usage = (sInfo->swap_missed_count != 0)
958 ? driCalculateSwapUsage( dPriv, 0, mmesa->swap_missed_ust )
959 : 0.0;
960
961 return 0;
962 }