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