Fix a == vs !- typo for glx_enable_extension
[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
26 /**
27 * \file mga_xmesa.c
28 * MGA screen and context initialization / creation code.
29 *
30 * \author Keith Whitwell <keith@tungstengraphics.com>
31 */
32
33 #include <stdlib.h>
34 #include <stdint.h>
35 #include "drm.h"
36 #include "mga_drm.h"
37 #include "mga_xmesa.h"
38 #include "context.h"
39 #include "matrix.h"
40 #include "simple_list.h"
41 #include "imports.h"
42 #include "framebuffer.h"
43 #include "renderbuffer.h"
44
45 #include "swrast/swrast.h"
46 #include "swrast_setup/swrast_setup.h"
47 #include "tnl/tnl.h"
48 #include "array_cache/acache.h"
49
50 #include "tnl/t_pipeline.h"
51
52 #include "drivers/common/driverfuncs.h"
53
54 #include "mgadd.h"
55 #include "mgastate.h"
56 #include "mgatex.h"
57 #include "mgaspan.h"
58 #include "mgaioctl.h"
59 #include "mgatris.h"
60 #include "mgavb.h"
61 #include "mgapixel.h"
62 #include "mga_xmesa.h"
63 #include "mga_dri.h"
64
65 #include "utils.h"
66 #include "vblank.h"
67
68 #include "extensions.h"
69
70 #include "GL/internal/dri_interface.h"
71
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
78 #if 0
79 #define need_GL_EXT_paletted_texture
80 #endif
81 #define need_GL_NV_vertex_program
82 #include "extension_helper.h"
83
84 /* MGA configuration
85 */
86 #include "xmlpool.h"
87
88 PUBLIC const char __driConfigOptions[] =
89 DRI_CONF_BEGIN
90 DRI_CONF_SECTION_PERFORMANCE
91 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
92 DRI_CONF_SECTION_END
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)
96 DRI_CONF_SECTION_END
97 DRI_CONF_SECTION_SOFTWARE
98 DRI_CONF_ARB_VERTEX_PROGRAM(true)
99 DRI_CONF_NV_VERTEX_PROGRAM(true)
100 DRI_CONF_SECTION_END
101 DRI_CONF_SECTION_DEBUG
102 DRI_CONF_NO_RAST(false)
103 DRI_CONF_SECTION_END
104 DRI_CONF_END;
105 static const GLuint __driNConfigOptions = 6;
106
107 #ifndef MGA_DEBUG
108 int MGA_DEBUG = 0;
109 #endif
110
111 static int getSwapInfo( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo );
112
113 static __GLcontextModes *
114 mgaFillInModes( unsigned pixel_bits, unsigned depth_bits,
115 unsigned stencil_bits, GLboolean have_back_buffer )
116 {
117 __GLcontextModes * modes;
118 __GLcontextModes * m;
119 unsigned num_modes;
120 unsigned depth_buffer_factor;
121 unsigned back_buffer_factor;
122 GLenum fb_format;
123 GLenum fb_type;
124
125 /* GLX_SWAP_COPY_OML is only supported because the MGA driver doesn't
126 * support pageflipping at all.
127 */
128 static const GLenum back_buffer_modes[] = {
129 GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML
130 };
131
132 u_int8_t depth_bits_array[3];
133 u_int8_t stencil_bits_array[3];
134
135
136 depth_bits_array[0] = 0;
137 depth_bits_array[1] = depth_bits;
138 depth_bits_array[2] = depth_bits;
139
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
142 * care about that.
143 */
144 stencil_bits_array[0] = 0;
145 stencil_bits_array[1] = 0;
146 stencil_bits_array[2] = (stencil_bits == 0) ? 8 : stencil_bits;
147
148 depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 3 : 1;
149 back_buffer_factor = (have_back_buffer) ? 2 : 1;
150
151 num_modes = depth_buffer_factor * back_buffer_factor * 4;
152
153 if ( pixel_bits == 16 ) {
154 fb_format = GL_RGB;
155 fb_type = GL_UNSIGNED_SHORT_5_6_5;
156 }
157 else {
158 fb_format = GL_BGR;
159 fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
160 }
161
162 modes = (*dri_interface->createContextModes)( num_modes, sizeof( __GLcontextModes ) );
163 m = modes;
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,
167 GLX_TRUE_COLOR ) ) {
168 fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
169 __func__, __LINE__ );
170 return NULL;
171 }
172
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__ );
179 return NULL;
180 }
181
182 /* Mark the visual as slow if there are "fake" stencil bits.
183 */
184 for ( m = modes ; m != NULL ; m = m->next ) {
185 if ( (m->stencilBits != 0) && (m->stencilBits != stencil_bits) ) {
186 m->visualRating = GLX_SLOW_CONFIG;
187 }
188 }
189
190 return modes;
191 }
192
193
194 static GLboolean
195 mgaInitDriver(__DRIscreenPrivate *sPriv)
196 {
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;
202
203
204 /* Allocate the private area */
205 mgaScreen = (mgaScreenPrivate *)MALLOC(sizeof(mgaScreenPrivate));
206 if (!mgaScreen) {
207 __driUtilMessage("Couldn't malloc screen struct");
208 return GL_FALSE;
209 }
210
211 mgaScreen->sPriv = sPriv;
212 sPriv->private = (void *)mgaScreen;
213
214 if (sPriv->drmMinor >= 1) {
215 int ret;
216 drm_mga_getparam_t gp;
217
218 gp.param = MGA_PARAM_IRQ_NR;
219 gp.value = &mgaScreen->irq;
220 mgaScreen->irq = 0;
221
222 ret = drmCommandWriteRead( sPriv->fd, DRM_MGA_GETPARAM,
223 &gp, sizeof(gp));
224 if (ret) {
225 fprintf(stderr, "drmMgaGetParam (MGA_PARAM_IRQ_NR): %d\n", ret);
226 FREE(mgaScreen);
227 sPriv->private = NULL;
228 return GL_FALSE;
229 }
230 }
231
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" );
238 }
239
240 if (serverInfo->chipset != MGA_CARD_TYPE_G200 &&
241 serverInfo->chipset != MGA_CARD_TYPE_G400) {
242 FREE(mgaScreen);
243 sPriv->private = NULL;
244 __driUtilMessage("Unrecognized chipset");
245 return GL_FALSE;
246 }
247
248
249 mgaScreen->chipset = serverInfo->chipset;
250 mgaScreen->cpp = serverInfo->cpp;
251
252 mgaScreen->agpMode = serverInfo->agpMode;
253
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;
260
261
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).
266 *
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.
269 */
270
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 ) {
277 FREE( mgaScreen );
278 sPriv->private = NULL;
279 __driUtilMessage( "Couldn't map MMIO registers" );
280 return GL_FALSE;
281 }
282
283 mgaScreen->primary.handle = serverInfo->primary.handle;
284 mgaScreen->primary.size = serverInfo->primary.size;
285 }
286 else {
287 (void) memset( & mgaScreen->primary, 0, sizeof( mgaScreen->primary ) );
288 (void) memset( & mgaScreen->mmio, 0, sizeof( mgaScreen->mmio ) );
289 }
290
291 mgaScreen->textureOffset[MGA_CARD_HEAP] = serverInfo->textureOffset;
292 mgaScreen->textureOffset[MGA_AGP_HEAP] = (serverInfo->agpTextureOffset |
293 PDEA_pagpxfer_enable | 1);
294
295 mgaScreen->textureSize[MGA_CARD_HEAP] = serverInfo->textureSize;
296 mgaScreen->textureSize[MGA_AGP_HEAP] = serverInfo->agpTextureSize;
297
298
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
303 * the DRM.
304 */
305
306 mgaScreen->texVirtual[MGA_CARD_HEAP] = (char *)(mgaScreen->sPriv->pFB +
307 serverInfo->textureOffset);
308
309 if ( serverInfo->agpTextureSize > 0 ) {
310 if (drmMap(sPriv->fd, serverInfo->agpTextureOffset,
311 serverInfo->agpTextureSize,
312 (drmAddress *)&mgaScreen->texVirtual[MGA_AGP_HEAP]) != 0) {
313 FREE(mgaScreen);
314 sPriv->private = NULL;
315 __driUtilMessage("Couldn't map agptexture region");
316 return GL_FALSE;
317 }
318 }
319
320
321 /* For calculating setupdma addresses.
322 */
323
324 mgaScreen->bufs = drmMapBufs(sPriv->fd);
325 if (!mgaScreen->bufs) {
326 FREE(mgaScreen);
327 sPriv->private = NULL;
328 __driUtilMessage("Couldn't map dma buffers");
329 return GL_FALSE;
330 }
331 mgaScreen->sarea_priv_offset = serverInfo->sarea_priv_offset;
332
333 /* parse information in __driConfigOptions */
334 driParseOptionInfo (&mgaScreen->optionCache,
335 __driConfigOptions, __driNConfigOptions);
336
337 return GL_TRUE;
338 }
339
340
341 static void
342 mgaDestroyScreen(__DRIscreenPrivate *sPriv)
343 {
344 mgaScreenPrivate *mgaScreen = (mgaScreenPrivate *) sPriv->private;
345
346 if (MGA_DEBUG&DEBUG_VERBOSE_DRI)
347 fprintf(stderr, "mgaDestroyScreen\n");
348
349 drmUnmapBufs(mgaScreen->bufs);
350
351
352 /* free all option information */
353 driDestroyOptionInfo (&mgaScreen->optionCache);
354
355 FREE(mgaScreen);
356 sPriv->private = NULL;
357 }
358
359
360 extern const struct tnl_pipeline_stage _mga_render_stage;
361
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,
367 &_tnl_texgen_stage,
368 &_tnl_texture_transform_stage,
369 &_tnl_vertex_program_stage,
370
371 /* REMOVE: point attenuation stage */
372 #if 0
373 &_mga_render_stage, /* ADD: unclipped rastersetup-to-dma */
374 /* Need new ioctl for wacceptseq */
375 #endif
376 &_tnl_render_stage,
377 0,
378 };
379
380
381 static const struct dri_extension g400_extensions[] =
382 {
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 },
390 { NULL, NULL }
391 };
392
393 static const struct dri_extension card_extensions[] =
394 {
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 },
405 #endif
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 },
410 { NULL, NULL }
411 };
412
413 static const struct dri_extension ARB_vp_extension[] = {
414 { "GL_ARB_vertex_program", GL_ARB_vertex_program_functions },
415 { NULL, NULL }
416 };
417
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 },
421 { NULL, NULL }
422 };
423
424 static const struct dri_debug_control debug_control[] =
425 {
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 },
431 { NULL, 0 }
432 };
433
434
435 static GLboolean
436 mgaCreateContext( const __GLcontextModes *mesaVis,
437 __DRIcontextPrivate *driContextPriv,
438 void *sharedContextPrivate )
439 {
440 int i;
441 unsigned maxlevels;
442 GLcontext *ctx, *shareCtx;
443 mgaContextPtr mmesa;
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;
449
450 if (MGA_DEBUG&DEBUG_VERBOSE_DRI)
451 fprintf(stderr, "mgaCreateContext\n");
452
453 /* allocate mga context */
454 mmesa = (mgaContextPtr) CALLOC(sizeof(mgaContext));
455 if (!mmesa) {
456 return GL_FALSE;
457 }
458
459 /* Init default driver functions then plug in our Radeon-specific functions
460 * (the texture functions are especially important)
461 */
462 _mesa_init_driver_functions( &functions );
463 mgaInitDriverFuncs( &functions );
464 mgaInitTextureFuncs( &functions );
465 mgaInitIoctlFuncs( &functions );
466
467 /* Allocate the Mesa context */
468 if (sharedContextPrivate)
469 shareCtx = ((mgaContextPtr) sharedContextPrivate)->glCtx;
470 else
471 shareCtx = NULL;
472 mmesa->glCtx = _mesa_create_context(mesaVis, shareCtx,
473 &functions, (void *) mmesa);
474 if (!mmesa->glCtx) {
475 FREE(mmesa);
476 return GL_FALSE;
477 }
478 driContextPriv->driverPrivate = mmesa;
479
480 /* Init mga state */
481 mmesa->hHWContext = driContextPriv->hHWContext;
482 mmesa->driFd = sPriv->fd;
483 mmesa->driHwLock = &sPriv->pSAREA->lock;
484
485 mmesa->mgaScreen = mgaScreen;
486 mmesa->driScreen = sPriv;
487 mmesa->sarea = (void *)saPriv;
488
489 /* Parse configuration files */
490 driParseConfigFiles (&mmesa->optionCache, &mgaScreen->optionCache,
491 sPriv->myNum, "mga");
492
493 (void) memset( mmesa->texture_heaps, 0, sizeof( mmesa->texture_heaps ) );
494 make_empty_list( & mmesa->swapped );
495
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],
500 6,
501 MGA_NR_TEX_REGIONS,
502 (drmTextureRegionPtr)mmesa->sarea->texList[i],
503 &mmesa->sarea->texAge[i],
504 &mmesa->swapped,
505 sizeof( mgaTextureObject_t ),
506 (destroy_texture_object_t *) mgaDestroyTexObj );
507 }
508
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.
512 */
513 ctx = mmesa->glCtx;
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;
519
520 }
521 else {
522 ctx->Const.MaxTextureUnits = 2;
523 ctx->Const.MaxTextureImageUnits = 2;
524 ctx->Const.MaxTextureCoordUnits = 2;
525 maxlevels = G400_TEX_MAXLEVELS;
526 }
527
528 driCalculateMaxTextureLevels( mmesa->texture_heaps,
529 mmesa->nr_heaps,
530 & ctx->Const,
531 4,
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 */
536 maxlevels,
537 GL_FALSE );
538
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;
544
545 mmesa->texture_depth = driQueryOptioni (&mmesa->optionCache,
546 "texture_depth");
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;
551
552 switch (mesaVis->depthBits) {
553 case 16:
554 mmesa->depth_scale = 1.0/(GLdouble)0xffff;
555 mmesa->depth_clear_mask = ~0;
556 mmesa->ClearDepth = 0xffff;
557 break;
558 case 24:
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;
563 } else
564 mmesa->depth_clear_mask = ~0;
565 mmesa->ClearDepth = 0xffffff00;
566 break;
567 case 32:
568 mmesa->depth_scale = 1.0/(GLdouble)0xffffffff;
569 mmesa->depth_clear_mask = ~0;
570 mmesa->ClearDepth = 0xffffffff;
571 break;
572 };
573
574 mmesa->haveHwStipple = GL_FALSE;
575 mmesa->RenderIndex = -1; /* impossible value */
576 mmesa->dirty = ~0;
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;
582
583 mmesa->texAge[0] = 0;
584 mmesa->texAge[1] = 0;
585
586 /* Initialize the software rasterizer and helper modules.
587 */
588 _swrast_CreateContext( ctx );
589 _ac_CreateContext( ctx );
590 _tnl_CreateContext( ctx );
591
592 _swsetup_CreateContext( ctx );
593
594 /* Install the customized pipeline:
595 */
596 _tnl_destroy_pipeline( ctx );
597 _tnl_install_pipeline( ctx, mga_pipeline );
598
599 /* Configure swrast and T&L to match hardware characteristics:
600 */
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 );
605
606 mmesa->primary_offset = mmesa->mgaScreen->primary.handle;
607
608 ctx->DriverCtx = (void *) mmesa;
609 mmesa->glCtx = ctx;
610
611 driInitExtensions( ctx, card_extensions, GL_FALSE );
612
613 if (MGA_IS_G400(MGA_CONTEXT(ctx))) {
614 driInitExtensions( ctx, g400_extensions, GL_FALSE );
615 }
616
617 if ( driQueryOptionb( &mmesa->optionCache, "arb_vertex_program" ) ) {
618 driInitSingleExtension( ctx, ARB_vp_extension );
619 }
620
621 if ( driQueryOptionb( &mmesa->optionCache, "nv_vertex_program" ) ) {
622 driInitExtensions( ctx, NV_vp_extensions, GL_FALSE );
623 }
624
625
626 /* XXX these should really go right after _mesa_init_driver_functions() */
627 mgaDDInitStateFuncs( ctx );
628 mgaDDInitSpanFuncs( ctx );
629 mgaDDInitPixelFuncs( ctx );
630 mgaDDInitTriFuncs( ctx );
631
632 mgaInitVB( ctx );
633 mgaInitState( mmesa );
634
635 driContextPriv->driverPrivate = (void *) mmesa;
636
637 #if DO_DEBUG
638 MGA_DEBUG = driParseDebugString( getenv( "MGA_DEBUG" ),
639 debug_control );
640 #endif
641
642 mmesa->vblank_flags = (mmesa->mgaScreen->irq == 0)
643 ? VBLANK_FLAG_NO_IRQ : driGetDefaultVBlankFlags(&mmesa->optionCache);
644
645 (*dri_interface->getUST)( & mmesa->swap_ust );
646
647 if (driQueryOptionb(&mmesa->optionCache, "no_rast")) {
648 fprintf(stderr, "disabling 3D acceleration\n");
649 FALLBACK(mmesa->glCtx, MGA_FALLBACK_DISABLE, 1);
650 }
651
652 return GL_TRUE;
653 }
654
655 static void
656 mgaDestroyContext(__DRIcontextPrivate *driContextPriv)
657 {
658 mgaContextPtr mmesa = (mgaContextPtr) driContextPriv->driverPrivate;
659
660 if (MGA_DEBUG&DEBUG_VERBOSE_DRI)
661 fprintf( stderr, "[%s:%d] mgaDestroyContext start\n",
662 __FILE__, __LINE__ );
663
664 assert(mmesa); /* should never be null */
665 if (mmesa) {
666 GLboolean release_texture_heaps;
667
668
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 );
674
675 mgaFreeVB( mmesa->glCtx );
676
677 /* free the Mesa context */
678 mmesa->glCtx->DriverCtx = NULL;
679 _mesa_destroy_context(mmesa->glCtx);
680
681 if ( release_texture_heaps ) {
682 /* This share group is about to go away, free our private
683 * texture object data.
684 */
685 int i;
686
687 for ( i = 0 ; i < mmesa->nr_heaps ; i++ ) {
688 driDestroyTextureHeap( mmesa->texture_heaps[ i ] );
689 mmesa->texture_heaps[ i ] = NULL;
690 }
691
692 assert( is_empty_list( & mmesa->swapped ) );
693 }
694
695 /* free the option cache */
696 driDestroyOptionCache (&mmesa->optionCache);
697
698 FREE(mmesa);
699 }
700
701 if (MGA_DEBUG&DEBUG_VERBOSE_DRI)
702 fprintf( stderr, "[%s:%d] mgaDestroyContext done\n",
703 __FILE__, __LINE__ );
704 }
705
706
707 static GLboolean
708 mgaCreateBuffer( __DRIscreenPrivate *driScrnPriv,
709 __DRIdrawablePrivate *driDrawPriv,
710 const __GLcontextModes *mesaVis,
711 GLboolean isPixmap )
712 {
713 mgaScreenPrivate *screen = (mgaScreenPrivate *) driScrnPriv->private;
714
715 if (isPixmap) {
716 return GL_FALSE; /* not implemented */
717 }
718 else {
719 GLboolean swStencil = (mesaVis->stencilBits > 0 &&
720 mesaVis->depthBits != 24);
721
722 #if 0
723 driDrawPriv->driverPrivate = (void *)
724 _mesa_create_framebuffer(mesaVis,
725 GL_FALSE, /* software depth buffer? */
726 swStencil,
727 mesaVis->accumRedBits > 0,
728 mesaVis->alphaBits > 0 );
729 #else
730 struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis);
731
732 {
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);
738 }
739
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);
746 }
747
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);
754 }
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);
763 }
764 else {
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);
770 }
771 }
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);
778 }
779
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);
786 }
787
788 _mesa_add_soft_renderbuffers(fb,
789 GL_FALSE, /* color */
790 GL_FALSE, /* depth */
791 swStencil,
792 mesaVis->accumRedBits > 0,
793 GL_FALSE, /* alpha */
794 GL_FALSE /* aux */);
795 driDrawPriv->driverPrivate = (void *) fb;
796 #endif
797
798 return (driDrawPriv->driverPrivate != NULL);
799 }
800 }
801
802
803 static void
804 mgaDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
805 {
806 _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
807 }
808
809 static void
810 mgaSwapBuffers(__DRIdrawablePrivate *dPriv)
811 {
812 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
813 mgaContextPtr mmesa;
814 GLcontext *ctx;
815 mmesa = (mgaContextPtr) dPriv->driContextPriv->driverPrivate;
816 ctx = mmesa->glCtx;
817
818 if (ctx->Visual.doubleBufferMode) {
819 _mesa_notifySwapBuffers( ctx );
820 mgaCopyBuffer( dPriv );
821 }
822 } else {
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__);
825 }
826 }
827
828 static GLboolean
829 mgaUnbindContext(__DRIcontextPrivate *driContextPriv)
830 {
831 mgaContextPtr mmesa = (mgaContextPtr) driContextPriv->driverPrivate;
832 if (mmesa)
833 mmesa->dirty = ~0;
834
835 return GL_TRUE;
836 }
837
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
840 * driDrawablePriv.
841 *
842 * But why are we doing context initialization here???
843 */
844 static GLboolean
845 mgaMakeCurrent(__DRIcontextPrivate *driContextPriv,
846 __DRIdrawablePrivate *driDrawPriv,
847 __DRIdrawablePrivate *driReadPriv)
848 {
849 if (driContextPriv) {
850 mgaContextPtr mmesa = (mgaContextPtr) driContextPriv->driverPrivate;
851
852 if (mmesa->driDrawable != driDrawPriv) {
853 driDrawableInitVBlank( driDrawPriv, mmesa->vblank_flags );
854 mmesa->driDrawable = driDrawPriv;
855 mmesa->dirty = ~0;
856 mmesa->dirty_cliprects = (MGA_FRONT|MGA_BACK);
857 mmesa->mesa_drawable = driDrawPriv;
858 }
859
860 mmesa->driReadable = driReadPriv;
861
862 _mesa_make_current(mmesa->glCtx,
863 (GLframebuffer *) driDrawPriv->driverPrivate,
864 (GLframebuffer *) driReadPriv->driverPrivate);
865 }
866 else {
867 _mesa_make_current(NULL, NULL, NULL);
868 }
869
870 return GL_TRUE;
871 }
872
873
874 void mgaGetLock( mgaContextPtr mmesa, GLuint flags )
875 {
876 __DRIdrawablePrivate *dPriv = mmesa->driDrawable;
877 drm_mga_sarea_t *sarea = mmesa->sarea;
878 int me = mmesa->hHWContext;
879 int i;
880
881 drmGetLock(mmesa->driFd, mmesa->hHWContext, flags);
882
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) );
888 }
889
890 mmesa->dirty |= MGA_UPLOAD_CONTEXT | MGA_UPLOAD_CLIPRECTS;
891
892 mmesa->sarea->dirty |= MGA_UPLOAD_CONTEXT;
893
894 if (sarea->ctxOwner != me) {
895 mmesa->dirty |= (MGA_UPLOAD_CONTEXT | MGA_UPLOAD_TEX0 |
896 MGA_UPLOAD_TEX1 | MGA_UPLOAD_PIPE);
897 sarea->ctxOwner=me;
898 }
899
900 for ( i = 0 ; i < mmesa->nr_heaps ; i++ ) {
901 DRI_AGE_TEXTURES( mmesa->texture_heaps[ i ] );
902 }
903 }
904
905
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,
919 .WaitForSBC = NULL,
920 .SwapBuffersMSC = NULL
921 };
922
923
924 /**
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
929 * pbuffers.
930 *
931 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
932 * failure.
933 */
934 PUBLIC
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 )
945
946 {
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 };
951
952 dri_interface = interface;
953
954 if ( ! driCheckDriDdxDrmVersions2( "MGA",
955 dri_version, & dri_expected,
956 ddx_version, & ddx_expected,
957 drm_version, & drm_expected ) ) {
958 return NULL;
959 }
960
961 psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL,
962 ddx_version, dri_version, drm_version,
963 frame_buffer, pSAREA, fd,
964 internal_api_version, &mgaAPI);
965 if ( psp != NULL ) {
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) );
971
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.
977 *
978 * Hello chicken. Hello egg. How are you two today?
979 */
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 );
984
985 }
986
987 return (void *) psp;
988 }
989
990
991 /**
992 * Get information about previous buffer swaps.
993 */
994 static int
995 getSwapInfo( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo )
996 {
997 mgaContextPtr mmesa;
998
999 if ( (dPriv == NULL) || (dPriv->driContextPriv == NULL)
1000 || (dPriv->driContextPriv->driverPrivate == NULL)
1001 || (sInfo == NULL) ) {
1002 return -1;
1003 }
1004
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;
1009
1010 sInfo->swap_missed_usage = (sInfo->swap_missed_count != 0)
1011 ? driCalculateSwapUsage( dPriv, 0, mmesa->swap_missed_ust )
1012 : 0.0;
1013
1014 return 0;
1015 }