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