eba96486f6756cc17fdd8cbfa85d164eaa8b2226
[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 "vbo/vbo.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 #include "drirenderbuffer.h"
70
71 #include "GL/internal/dri_interface.h"
72
73 #define need_GL_ARB_multisample
74 #define need_GL_ARB_texture_compression
75 #define need_GL_ARB_vertex_buffer_object
76 #define need_GL_ARB_vertex_program
77 #define need_GL_EXT_fog_coord
78 #define need_GL_EXT_multi_draw_arrays
79 #define need_GL_EXT_secondary_color
80 #if 0
81 #define need_GL_EXT_paletted_texture
82 #endif
83 #define need_GL_NV_vertex_program
84 #include "extension_helper.h"
85
86 /* MGA configuration
87 */
88 #include "xmlpool.h"
89
90 PUBLIC const char __driConfigOptions[] =
91 DRI_CONF_BEGIN
92 DRI_CONF_SECTION_PERFORMANCE
93 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
94 DRI_CONF_SECTION_END
95 DRI_CONF_SECTION_QUALITY
96 DRI_CONF_TEXTURE_DEPTH(DRI_CONF_TEXTURE_DEPTH_FB)
97 DRI_CONF_COLOR_REDUCTION(DRI_CONF_COLOR_REDUCTION_DITHER)
98 DRI_CONF_SECTION_END
99 DRI_CONF_SECTION_SOFTWARE
100 DRI_CONF_ARB_VERTEX_PROGRAM(true)
101 DRI_CONF_NV_VERTEX_PROGRAM(true)
102 DRI_CONF_SECTION_END
103 DRI_CONF_SECTION_DEBUG
104 DRI_CONF_NO_RAST(false)
105 DRI_CONF_SECTION_END
106 DRI_CONF_END;
107 static const GLuint __driNConfigOptions = 6;
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 = (*dri_interface->createContextModes)( 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 const __DRIextension *mgaExtensions[] = {
197 &driSwapControlExtension.base,
198 NULL
199 };
200
201 static GLboolean
202 mgaInitDriver(__DRIscreenPrivate *sPriv)
203 {
204 mgaScreenPrivate *mgaScreen;
205 MGADRIPtr serverInfo = (MGADRIPtr)sPriv->pDevPriv;
206 PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension =
207 (PFNGLXSCRENABLEEXTENSIONPROC) (*dri_interface->getProcAddress("glxEnableExtension"));
208
209 if (sPriv->devPrivSize != sizeof(MGADRIRec)) {
210 fprintf(stderr,"\nERROR! sizeof(MGADRIRec) does not match passed size from device driver\n");
211 return GL_FALSE;
212 }
213
214 /* Allocate the private area */
215 mgaScreen = (mgaScreenPrivate *)MALLOC(sizeof(mgaScreenPrivate));
216 if (!mgaScreen) {
217 __driUtilMessage("Couldn't malloc screen struct");
218 return GL_FALSE;
219 }
220
221 mgaScreen->sPriv = sPriv;
222 sPriv->private = (void *)mgaScreen;
223
224 if (sPriv->drm_version.minor >= 1) {
225 int ret;
226 drm_mga_getparam_t gp;
227
228 gp.param = MGA_PARAM_IRQ_NR;
229 gp.value = &mgaScreen->irq;
230 mgaScreen->irq = 0;
231
232 ret = drmCommandWriteRead( sPriv->fd, DRM_MGA_GETPARAM,
233 &gp, sizeof(gp));
234 if (ret) {
235 fprintf(stderr, "drmMgaGetParam (MGA_PARAM_IRQ_NR): %d\n", ret);
236 FREE(mgaScreen);
237 sPriv->private = NULL;
238 return GL_FALSE;
239 }
240 }
241
242 sPriv->extensions = mgaExtensions;
243
244 if ( glx_enable_extension != NULL ) {
245 (*glx_enable_extension)( sPriv->psc, "GLX_MESA_swap_frame_usage" );
246 (*glx_enable_extension)( sPriv->psc, "GLX_SGI_make_current_read" );
247 (*glx_enable_extension)( sPriv->psc, "GLX_SGI_video_sync" );
248 }
249
250 if (serverInfo->chipset != MGA_CARD_TYPE_G200 &&
251 serverInfo->chipset != MGA_CARD_TYPE_G400) {
252 FREE(mgaScreen);
253 sPriv->private = NULL;
254 __driUtilMessage("Unrecognized chipset");
255 return GL_FALSE;
256 }
257
258
259 mgaScreen->chipset = serverInfo->chipset;
260 mgaScreen->cpp = serverInfo->cpp;
261
262 mgaScreen->agpMode = serverInfo->agpMode;
263
264 mgaScreen->frontPitch = serverInfo->frontPitch;
265 mgaScreen->frontOffset = serverInfo->frontOffset;
266 mgaScreen->backOffset = serverInfo->backOffset;
267 mgaScreen->backPitch = serverInfo->backPitch;
268 mgaScreen->depthOffset = serverInfo->depthOffset;
269 mgaScreen->depthPitch = serverInfo->depthPitch;
270
271
272 /* The only reason that the MMIO region needs to be accessable and the
273 * primary DMA region base address needs to be known is so that the driver
274 * can busy wait for certain DMA operations to complete (see
275 * mgaWaitForFrameCompletion in mgaioctl.c).
276 *
277 * Starting with MGA DRM version 3.2, these are completely unneeded as
278 * there is a new, in-kernel mechanism for handling the wait.
279 */
280
281 if (mgaScreen->sPriv->drm_version.minor < 2) {
282 mgaScreen->mmio.handle = serverInfo->registers.handle;
283 mgaScreen->mmio.size = serverInfo->registers.size;
284 if ( drmMap( sPriv->fd,
285 mgaScreen->mmio.handle, mgaScreen->mmio.size,
286 &mgaScreen->mmio.map ) < 0 ) {
287 FREE( mgaScreen );
288 sPriv->private = NULL;
289 __driUtilMessage( "Couldn't map MMIO registers" );
290 return GL_FALSE;
291 }
292
293 mgaScreen->primary.handle = serverInfo->primary.handle;
294 mgaScreen->primary.size = serverInfo->primary.size;
295 }
296 else {
297 (void) memset( & mgaScreen->primary, 0, sizeof( mgaScreen->primary ) );
298 (void) memset( & mgaScreen->mmio, 0, sizeof( mgaScreen->mmio ) );
299 }
300
301 mgaScreen->textureOffset[MGA_CARD_HEAP] = serverInfo->textureOffset;
302 mgaScreen->textureOffset[MGA_AGP_HEAP] = (serverInfo->agpTextureOffset |
303 PDEA_pagpxfer_enable | 1);
304
305 mgaScreen->textureSize[MGA_CARD_HEAP] = serverInfo->textureSize;
306 mgaScreen->textureSize[MGA_AGP_HEAP] = serverInfo->agpTextureSize;
307
308
309 /* The texVirtual array stores the base addresses in the CPU's address
310 * space of the texture memory pools. The base address of the on-card
311 * memory pool is calculated as an offset of the base of video memory. The
312 * AGP texture pool has to be mapped into the processes address space by
313 * the DRM.
314 */
315
316 mgaScreen->texVirtual[MGA_CARD_HEAP] = (char *)(mgaScreen->sPriv->pFB +
317 serverInfo->textureOffset);
318
319 if ( serverInfo->agpTextureSize > 0 ) {
320 if (drmMap(sPriv->fd, serverInfo->agpTextureOffset,
321 serverInfo->agpTextureSize,
322 (drmAddress *)&mgaScreen->texVirtual[MGA_AGP_HEAP]) != 0) {
323 FREE(mgaScreen);
324 sPriv->private = NULL;
325 __driUtilMessage("Couldn't map agptexture region");
326 return GL_FALSE;
327 }
328 }
329
330
331 /* For calculating setupdma addresses.
332 */
333
334 mgaScreen->bufs = drmMapBufs(sPriv->fd);
335 if (!mgaScreen->bufs) {
336 FREE(mgaScreen);
337 sPriv->private = NULL;
338 __driUtilMessage("Couldn't map dma buffers");
339 return GL_FALSE;
340 }
341 mgaScreen->sarea_priv_offset = serverInfo->sarea_priv_offset;
342
343 /* parse information in __driConfigOptions */
344 driParseOptionInfo (&mgaScreen->optionCache,
345 __driConfigOptions, __driNConfigOptions);
346
347 return GL_TRUE;
348 }
349
350
351 static void
352 mgaDestroyScreen(__DRIscreenPrivate *sPriv)
353 {
354 mgaScreenPrivate *mgaScreen = (mgaScreenPrivate *) sPriv->private;
355
356 if (MGA_DEBUG&DEBUG_VERBOSE_DRI)
357 fprintf(stderr, "mgaDestroyScreen\n");
358
359 drmUnmapBufs(mgaScreen->bufs);
360
361
362 /* free all option information */
363 driDestroyOptionInfo (&mgaScreen->optionCache);
364
365 FREE(mgaScreen);
366 sPriv->private = NULL;
367 }
368
369
370 extern const struct tnl_pipeline_stage _mga_render_stage;
371
372 static const struct tnl_pipeline_stage *mga_pipeline[] = {
373 &_tnl_vertex_transform_stage,
374 &_tnl_normal_transform_stage,
375 &_tnl_lighting_stage,
376 &_tnl_fog_coordinate_stage,
377 &_tnl_texgen_stage,
378 &_tnl_texture_transform_stage,
379 &_tnl_vertex_program_stage,
380
381 /* REMOVE: point attenuation stage */
382 #if 0
383 &_mga_render_stage, /* ADD: unclipped rastersetup-to-dma */
384 /* Need new ioctl for wacceptseq */
385 #endif
386 &_tnl_render_stage,
387 0,
388 };
389
390
391 static const struct dri_extension g400_extensions[] =
392 {
393 { "GL_ARB_multitexture", NULL },
394 { "GL_ARB_texture_env_add", NULL },
395 { "GL_ARB_texture_env_combine", NULL },
396 { "GL_ARB_texture_env_crossbar", NULL },
397 { "GL_EXT_texture_env_combine", NULL },
398 { "GL_EXT_texture_edge_clamp", NULL },
399 { "GL_ATI_texture_env_combine3", NULL },
400 { NULL, NULL }
401 };
402
403 static const struct dri_extension card_extensions[] =
404 {
405 { "GL_ARB_multisample", GL_ARB_multisample_functions },
406 { "GL_ARB_texture_compression", GL_ARB_texture_compression_functions },
407 { "GL_ARB_texture_rectangle", NULL },
408 { "GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions },
409 { "GL_EXT_blend_logic_op", NULL },
410 { "GL_EXT_fog_coord", GL_EXT_fog_coord_functions },
411 { "GL_EXT_multi_draw_arrays", GL_EXT_multi_draw_arrays_functions },
412 /* paletted_textures currently doesn't work, but we could fix them later */
413 #if defined( need_GL_EXT_paletted_texture )
414 { "GL_EXT_shared_texture_palette", NULL },
415 { "GL_EXT_paletted_texture", GL_EXT_paletted_texture_functions },
416 #endif
417 { "GL_EXT_secondary_color", GL_EXT_secondary_color_functions },
418 { "GL_EXT_stencil_wrap", NULL },
419 { "GL_MESA_ycbcr_texture", NULL },
420 { "GL_SGIS_generate_mipmap", NULL },
421 { NULL, NULL }
422 };
423
424 static const struct dri_extension ARB_vp_extension[] = {
425 { "GL_ARB_vertex_program", GL_ARB_vertex_program_functions },
426 { NULL, NULL }
427 };
428
429 static const struct dri_extension NV_vp_extensions[] = {
430 { "GL_NV_vertex_program", GL_NV_vertex_program_functions },
431 { "GL_NV_vertex_program1_1", NULL },
432 { NULL, NULL }
433 };
434
435 static const struct dri_debug_control debug_control[] =
436 {
437 { "fall", DEBUG_VERBOSE_FALLBACK },
438 { "tex", DEBUG_VERBOSE_TEXTURE },
439 { "ioctl", DEBUG_VERBOSE_IOCTL },
440 { "verb", DEBUG_VERBOSE_MSG },
441 { "dri", DEBUG_VERBOSE_DRI },
442 { NULL, 0 }
443 };
444
445
446 static GLboolean
447 mgaCreateContext( const __GLcontextModes *mesaVis,
448 __DRIcontextPrivate *driContextPriv,
449 void *sharedContextPrivate )
450 {
451 int i;
452 unsigned maxlevels;
453 GLcontext *ctx, *shareCtx;
454 mgaContextPtr mmesa;
455 __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
456 mgaScreenPrivate *mgaScreen = (mgaScreenPrivate *)sPriv->private;
457 drm_mga_sarea_t *saPriv = (drm_mga_sarea_t *)(((char*)sPriv->pSAREA)+
458 mgaScreen->sarea_priv_offset);
459 struct dd_function_table functions;
460
461 if (MGA_DEBUG&DEBUG_VERBOSE_DRI)
462 fprintf(stderr, "mgaCreateContext\n");
463
464 /* allocate mga context */
465 mmesa = (mgaContextPtr) CALLOC(sizeof(mgaContext));
466 if (!mmesa) {
467 return GL_FALSE;
468 }
469
470 /* Init default driver functions then plug in our Radeon-specific functions
471 * (the texture functions are especially important)
472 */
473 _mesa_init_driver_functions( &functions );
474 mgaInitDriverFuncs( &functions );
475 mgaInitTextureFuncs( &functions );
476 mgaInitIoctlFuncs( &functions );
477
478 /* Allocate the Mesa context */
479 if (sharedContextPrivate)
480 shareCtx = ((mgaContextPtr) sharedContextPrivate)->glCtx;
481 else
482 shareCtx = NULL;
483 mmesa->glCtx = _mesa_create_context(mesaVis, shareCtx,
484 &functions, (void *) mmesa);
485 if (!mmesa->glCtx) {
486 FREE(mmesa);
487 return GL_FALSE;
488 }
489 driContextPriv->driverPrivate = mmesa;
490
491 /* Init mga state */
492 mmesa->hHWContext = driContextPriv->hHWContext;
493 mmesa->driFd = sPriv->fd;
494 mmesa->driHwLock = &sPriv->pSAREA->lock;
495
496 mmesa->mgaScreen = mgaScreen;
497 mmesa->driScreen = sPriv;
498 mmesa->sarea = (void *)saPriv;
499
500 /* Parse configuration files */
501 driParseConfigFiles (&mmesa->optionCache, &mgaScreen->optionCache,
502 sPriv->myNum, "mga");
503
504 (void) memset( mmesa->texture_heaps, 0, sizeof( mmesa->texture_heaps ) );
505 make_empty_list( & mmesa->swapped );
506
507 mmesa->nr_heaps = mgaScreen->texVirtual[MGA_AGP_HEAP] ? 2 : 1;
508 for ( i = 0 ; i < mmesa->nr_heaps ; i++ ) {
509 mmesa->texture_heaps[i] = driCreateTextureHeap( i, mmesa,
510 mgaScreen->textureSize[i],
511 6,
512 MGA_NR_TEX_REGIONS,
513 (drmTextureRegionPtr)mmesa->sarea->texList[i],
514 &mmesa->sarea->texAge[i],
515 &mmesa->swapped,
516 sizeof( mgaTextureObject_t ),
517 (destroy_texture_object_t *) mgaDestroyTexObj );
518 }
519
520 /* Set the maximum texture size small enough that we can guarentee
521 * that both texture units can bind a maximal texture and have them
522 * on the card at once.
523 */
524 ctx = mmesa->glCtx;
525 if ( mgaScreen->chipset == MGA_CARD_TYPE_G200 ) {
526 ctx->Const.MaxTextureUnits = 1;
527 ctx->Const.MaxTextureImageUnits = 1;
528 ctx->Const.MaxTextureCoordUnits = 1;
529 maxlevels = G200_TEX_MAXLEVELS;
530
531 }
532 else {
533 ctx->Const.MaxTextureUnits = 2;
534 ctx->Const.MaxTextureImageUnits = 2;
535 ctx->Const.MaxTextureCoordUnits = 2;
536 maxlevels = G400_TEX_MAXLEVELS;
537 }
538
539 driCalculateMaxTextureLevels( mmesa->texture_heaps,
540 mmesa->nr_heaps,
541 & ctx->Const,
542 4,
543 11, /* max 2D texture size is 2048x2048 */
544 0, /* 3D textures unsupported. */
545 0, /* cube textures unsupported. */
546 11, /* max texture rect size is 2048x2048 */
547 maxlevels,
548 GL_FALSE,
549 0 );
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 _vbo_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 (*dri_interface->getUST)( & mmesa->swap_ust );
658
659 if (driQueryOptionb(&mmesa->optionCache, "no_rast")) {
660 fprintf(stderr, "disabling 3D acceleration\n");
661 FALLBACK(mmesa->glCtx, MGA_FALLBACK_DISABLE, 1);
662 }
663
664 return GL_TRUE;
665 }
666
667 static void
668 mgaDestroyContext(__DRIcontextPrivate *driContextPriv)
669 {
670 mgaContextPtr mmesa = (mgaContextPtr) driContextPriv->driverPrivate;
671
672 if (MGA_DEBUG&DEBUG_VERBOSE_DRI)
673 fprintf( stderr, "[%s:%d] mgaDestroyContext start\n",
674 __FILE__, __LINE__ );
675
676 assert(mmesa); /* should never be null */
677 if (mmesa) {
678 GLboolean release_texture_heaps;
679
680
681 release_texture_heaps = (mmesa->glCtx->Shared->RefCount == 1);
682 _swsetup_DestroyContext( mmesa->glCtx );
683 _tnl_DestroyContext( mmesa->glCtx );
684 _vbo_DestroyContext( mmesa->glCtx );
685 _swrast_DestroyContext( mmesa->glCtx );
686
687 mgaFreeVB( mmesa->glCtx );
688
689 /* free the Mesa context */
690 mmesa->glCtx->DriverCtx = NULL;
691 _mesa_destroy_context(mmesa->glCtx);
692
693 if ( release_texture_heaps ) {
694 /* This share group is about to go away, free our private
695 * texture object data.
696 */
697 int i;
698
699 for ( i = 0 ; i < mmesa->nr_heaps ; i++ ) {
700 driDestroyTextureHeap( mmesa->texture_heaps[ i ] );
701 mmesa->texture_heaps[ i ] = NULL;
702 }
703
704 assert( is_empty_list( & mmesa->swapped ) );
705 }
706
707 /* free the option cache */
708 driDestroyOptionCache (&mmesa->optionCache);
709
710 FREE(mmesa);
711 }
712
713 if (MGA_DEBUG&DEBUG_VERBOSE_DRI)
714 fprintf( stderr, "[%s:%d] mgaDestroyContext done\n",
715 __FILE__, __LINE__ );
716 }
717
718
719 static GLboolean
720 mgaCreateBuffer( __DRIscreenPrivate *driScrnPriv,
721 __DRIdrawablePrivate *driDrawPriv,
722 const __GLcontextModes *mesaVis,
723 GLboolean isPixmap )
724 {
725 mgaScreenPrivate *screen = (mgaScreenPrivate *) driScrnPriv->private;
726
727 if (isPixmap) {
728 return GL_FALSE; /* not implemented */
729 }
730 else {
731 GLboolean swStencil = (mesaVis->stencilBits > 0 &&
732 mesaVis->depthBits != 24);
733
734 #if 0
735 driDrawPriv->driverPrivate = (void *)
736 _mesa_create_framebuffer(mesaVis,
737 GL_FALSE, /* software depth buffer? */
738 swStencil,
739 mesaVis->accumRedBits > 0,
740 mesaVis->alphaBits > 0 );
741 #else
742 struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis);
743
744 {
745 driRenderbuffer *frontRb
746 = driNewRenderbuffer(GL_RGBA,
747 NULL,
748 screen->cpp,
749 screen->frontOffset, screen->frontPitch,
750 driDrawPriv);
751 mgaSetSpanFunctions(frontRb, mesaVis);
752 _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base);
753 }
754
755 if (mesaVis->doubleBufferMode) {
756 driRenderbuffer *backRb
757 = driNewRenderbuffer(GL_RGBA,
758 NULL,
759 screen->cpp,
760 screen->backOffset, screen->backPitch,
761 driDrawPriv);
762 mgaSetSpanFunctions(backRb, mesaVis);
763 _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base);
764 }
765
766 if (mesaVis->depthBits == 16) {
767 driRenderbuffer *depthRb
768 = driNewRenderbuffer(GL_DEPTH_COMPONENT16,
769 NULL,
770 screen->cpp,
771 screen->depthOffset, screen->depthPitch,
772 driDrawPriv);
773 mgaSetSpanFunctions(depthRb, mesaVis);
774 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
775 }
776 else if (mesaVis->depthBits == 24) {
777 /* XXX is this right? */
778 if (mesaVis->stencilBits) {
779 driRenderbuffer *depthRb
780 = driNewRenderbuffer(GL_DEPTH_COMPONENT24,
781 NULL,
782 screen->cpp,
783 screen->depthOffset, screen->depthPitch,
784 driDrawPriv);
785 mgaSetSpanFunctions(depthRb, mesaVis);
786 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
787 }
788 else {
789 driRenderbuffer *depthRb
790 = driNewRenderbuffer(GL_DEPTH_COMPONENT32,
791 NULL,
792 screen->cpp,
793 screen->depthOffset, screen->depthPitch,
794 driDrawPriv);
795 mgaSetSpanFunctions(depthRb, mesaVis);
796 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
797 }
798 }
799 else if (mesaVis->depthBits == 32) {
800 driRenderbuffer *depthRb
801 = driNewRenderbuffer(GL_DEPTH_COMPONENT32,
802 NULL,
803 screen->cpp,
804 screen->depthOffset, screen->depthPitch,
805 driDrawPriv);
806 mgaSetSpanFunctions(depthRb, mesaVis);
807 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
808 }
809
810 if (mesaVis->stencilBits > 0 && !swStencil) {
811 driRenderbuffer *stencilRb
812 = driNewRenderbuffer(GL_STENCIL_INDEX8_EXT,
813 NULL,
814 screen->cpp,
815 screen->depthOffset, screen->depthPitch,
816 driDrawPriv);
817 mgaSetSpanFunctions(stencilRb, mesaVis);
818 _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &stencilRb->Base);
819 }
820
821 _mesa_add_soft_renderbuffers(fb,
822 GL_FALSE, /* color */
823 GL_FALSE, /* depth */
824 swStencil,
825 mesaVis->accumRedBits > 0,
826 GL_FALSE, /* alpha */
827 GL_FALSE /* aux */);
828 driDrawPriv->driverPrivate = (void *) fb;
829 #endif
830
831 return (driDrawPriv->driverPrivate != NULL);
832 }
833 }
834
835
836 static void
837 mgaDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
838 {
839 _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)));
840 }
841
842 static void
843 mgaSwapBuffers(__DRIdrawablePrivate *dPriv)
844 {
845 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
846 mgaContextPtr mmesa;
847 GLcontext *ctx;
848 mmesa = (mgaContextPtr) dPriv->driContextPriv->driverPrivate;
849 ctx = mmesa->glCtx;
850
851 if (ctx->Visual.doubleBufferMode) {
852 _mesa_notifySwapBuffers( ctx );
853 mgaCopyBuffer( dPriv );
854 }
855 } else {
856 /* XXX this shouldn't be an error but we can't handle it for now */
857 _mesa_problem(NULL, "%s: drawable has no context!\n", __FUNCTION__);
858 }
859 }
860
861 static GLboolean
862 mgaUnbindContext(__DRIcontextPrivate *driContextPriv)
863 {
864 mgaContextPtr mmesa = (mgaContextPtr) driContextPriv->driverPrivate;
865 if (mmesa)
866 mmesa->dirty = ~0;
867
868 return GL_TRUE;
869 }
870
871 /* This looks buggy to me - the 'b' variable isn't used anywhere...
872 * Hmm - It seems that the drawable is already hooked in to
873 * driDrawablePriv.
874 *
875 * But why are we doing context initialization here???
876 */
877 static GLboolean
878 mgaMakeCurrent(__DRIcontextPrivate *driContextPriv,
879 __DRIdrawablePrivate *driDrawPriv,
880 __DRIdrawablePrivate *driReadPriv)
881 {
882 if (driContextPriv) {
883 mgaContextPtr mmesa = (mgaContextPtr) driContextPriv->driverPrivate;
884
885 if (mmesa->driDrawable != driDrawPriv) {
886 driDrawableInitVBlank( driDrawPriv, mmesa->vblank_flags,
887 &mmesa->vbl_seq );
888 mmesa->driDrawable = driDrawPriv;
889 mmesa->dirty = ~0;
890 mmesa->dirty_cliprects = (MGA_FRONT|MGA_BACK);
891 }
892
893 mmesa->driReadable = driReadPriv;
894
895 _mesa_make_current(mmesa->glCtx,
896 (GLframebuffer *) driDrawPriv->driverPrivate,
897 (GLframebuffer *) driReadPriv->driverPrivate);
898 }
899 else {
900 _mesa_make_current(NULL, NULL, NULL);
901 }
902
903 return GL_TRUE;
904 }
905
906
907 void mgaGetLock( mgaContextPtr mmesa, GLuint flags )
908 {
909 __DRIdrawablePrivate *dPriv = mmesa->driDrawable;
910 drm_mga_sarea_t *sarea = mmesa->sarea;
911 int me = mmesa->hHWContext;
912 int i;
913
914 drmGetLock(mmesa->driFd, mmesa->hHWContext, flags);
915
916 DRI_VALIDATE_DRAWABLE_INFO( mmesa->driScreen, dPriv );
917 if (*(dPriv->pStamp) != mmesa->lastStamp) {
918 mmesa->lastStamp = *(dPriv->pStamp);
919 mmesa->SetupNewInputs |= VERT_BIT_POS;
920 mmesa->dirty_cliprects = (MGA_FRONT|MGA_BACK);
921 mgaUpdateRects( mmesa, (MGA_FRONT|MGA_BACK) );
922 driUpdateFramebufferSize(mmesa->glCtx, dPriv);
923 }
924
925 mmesa->dirty |= MGA_UPLOAD_CONTEXT | MGA_UPLOAD_CLIPRECTS;
926
927 mmesa->sarea->dirty |= MGA_UPLOAD_CONTEXT;
928
929 if (sarea->ctxOwner != me) {
930 mmesa->dirty |= (MGA_UPLOAD_CONTEXT | MGA_UPLOAD_TEX0 |
931 MGA_UPLOAD_TEX1 | MGA_UPLOAD_PIPE);
932 sarea->ctxOwner=me;
933 }
934
935 for ( i = 0 ; i < mmesa->nr_heaps ; i++ ) {
936 DRI_AGE_TEXTURES( mmesa->texture_heaps[ i ] );
937 }
938 }
939
940
941 static const struct __DriverAPIRec mgaAPI = {
942 .DestroyScreen = mgaDestroyScreen,
943 .CreateContext = mgaCreateContext,
944 .DestroyContext = mgaDestroyContext,
945 .CreateBuffer = mgaCreateBuffer,
946 .DestroyBuffer = mgaDestroyBuffer,
947 .SwapBuffers = mgaSwapBuffers,
948 .MakeCurrent = mgaMakeCurrent,
949 .UnbindContext = mgaUnbindContext,
950 .GetSwapInfo = getSwapInfo,
951 .GetMSC = driGetMSC32,
952 .WaitForMSC = driWaitForMSC32,
953 .WaitForSBC = NULL,
954 .SwapBuffersMSC = NULL
955 };
956
957
958 /**
959 * This is the driver specific part of the createNewScreen entry point.
960 *
961 * \todo maybe fold this into intelInitDriver
962 *
963 * \return the __GLcontextModes supported by this driver
964 */
965 __GLcontextModes *__driDriverInitScreen(__DRIscreenPrivate *psp)
966 {
967 static const __DRIversion ddx_expected = { 1, 2, 0 };
968 static const __DRIversion dri_expected = { 4, 0, 0 };
969 static const __DRIversion drm_expected = { 3, 0, 0 };
970 MGADRIPtr dri_priv = (MGADRIPtr) psp->pDevPriv;
971
972 psp->DriverAPI = mgaAPI;
973 if ( ! driCheckDriDdxDrmVersions2( "MGA",
974 &psp->dri_version, & dri_expected,
975 &psp->ddx_version, & ddx_expected,
976 &psp->drm_version, & drm_expected ) )
977 return NULL;
978
979
980 /* Calling driInitExtensions here, with a NULL context pointer,
981 * does not actually enable the extensions. It just makes sure
982 * that all the dispatch offsets for all the extensions that
983 * *might* be enables are known. This is needed because the
984 * dispatch offsets need to be known when _mesa_context_create is
985 * called, but we can't enable the extensions until we have a
986 * context pointer.
987 *
988 * Hello chicken. Hello egg. How are you two today?
989 */
990
991 driInitExtensions( NULL, card_extensions, GL_FALSE );
992 driInitExtensions( NULL, g400_extensions, GL_FALSE );
993 driInitSingleExtension( NULL, ARB_vp_extension );
994 driInitExtensions( NULL, NV_vp_extensions, GL_FALSE );
995
996 if (!mgaInitDriver(psp))
997 return NULL;
998
999 return mgaFillInModes( dri_priv->cpp * 8,
1000 (dri_priv->cpp == 2) ? 16 : 24,
1001 (dri_priv->cpp == 2) ? 0 : 8,
1002 (dri_priv->backOffset != dri_priv->depthOffset) );
1003 }
1004
1005
1006 /**
1007 * Get information about previous buffer swaps.
1008 */
1009 static int
1010 getSwapInfo( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo )
1011 {
1012 mgaContextPtr mmesa;
1013
1014 if ( (dPriv == NULL) || (dPriv->driContextPriv == NULL)
1015 || (dPriv->driContextPriv->driverPrivate == NULL)
1016 || (sInfo == NULL) ) {
1017 return -1;
1018 }
1019
1020 mmesa = (mgaContextPtr) dPriv->driContextPriv->driverPrivate;
1021 sInfo->swap_count = mmesa->swap_count;
1022 sInfo->swap_ust = mmesa->swap_ust;
1023 sInfo->swap_missed_count = mmesa->swap_missed_count;
1024
1025 sInfo->swap_missed_usage = (sInfo->swap_missed_count != 0)
1026 ? driCalculateSwapUsage( dPriv, 0, mmesa->swap_missed_ust )
1027 : 0.0;
1028
1029 return 0;
1030 }