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