Merge commit 'origin/gallium-0.1' into gallium-0.2
[mesa.git] / src / mesa / drivers / dri / mga / mga_xmesa.c
1 /*
2 * Copyright 2000-2001 VA Linux Systems, Inc.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * on the rights to use, copy, modify, merge, publish, distribute, sub
9 * license, and/or sell copies of the Software, and to permit persons to whom
10 * the Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 /**
26 * \file mga_xmesa.c
27 * MGA screen and context initialization / creation code.
28 *
29 * \author Keith Whitwell <keith@tungstengraphics.com>
30 */
31
32 #include <stdlib.h>
33 #include <stdint.h>
34 #include "drm.h"
35 #include "mga_drm.h"
36 #include "mga_xmesa.h"
37 #include "main/context.h"
38 #include "main/matrix.h"
39 #include "main/simple_list.h"
40 #include "main/imports.h"
41 #include "main/framebuffer.h"
42 #include "main/renderbuffer.h"
43
44 #include "swrast/swrast.h"
45 #include "swrast_setup/swrast_setup.h"
46 #include "tnl/tnl.h"
47 #include "vbo/vbo.h"
48
49 #include "tnl/t_pipeline.h"
50
51 #include "drivers/common/driverfuncs.h"
52
53 #include "mgadd.h"
54 #include "mgastate.h"
55 #include "mgatex.h"
56 #include "mgaspan.h"
57 #include "mgaioctl.h"
58 #include "mgatris.h"
59 #include "mgavb.h"
60 #include "mgapixel.h"
61 #include "mga_xmesa.h"
62 #include "mga_dri.h"
63
64 #include "utils.h"
65 #include "vblank.h"
66
67 #include "main/extensions.h"
68 #include "drirenderbuffer.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_buffer_object
75 #define need_GL_ARB_vertex_program
76 #define need_GL_EXT_fog_coord
77 #define need_GL_EXT_gpu_program_parameters
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_APPLE_vertex_array_object
84 #define need_GL_NV_vertex_program
85 #include "extension_helper.h"
86
87 /* MGA configuration
88 */
89 #include "xmlpool.h"
90
91 PUBLIC const char __driConfigOptions[] =
92 DRI_CONF_BEGIN
93 DRI_CONF_SECTION_PERFORMANCE
94 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
95 DRI_CONF_SECTION_END
96 DRI_CONF_SECTION_QUALITY
97 DRI_CONF_TEXTURE_DEPTH(DRI_CONF_TEXTURE_DEPTH_FB)
98 DRI_CONF_COLOR_REDUCTION(DRI_CONF_COLOR_REDUCTION_DITHER)
99 DRI_CONF_SECTION_END
100 DRI_CONF_SECTION_SOFTWARE
101 DRI_CONF_ARB_VERTEX_PROGRAM(true)
102 DRI_CONF_NV_VERTEX_PROGRAM(true)
103 DRI_CONF_SECTION_END
104 DRI_CONF_SECTION_DEBUG
105 DRI_CONF_NO_RAST(false)
106 DRI_CONF_SECTION_END
107 DRI_CONF_END;
108 static const GLuint __driNConfigOptions = 6;
109
110 #ifndef MGA_DEBUG
111 int MGA_DEBUG = 0;
112 #endif
113
114 static const __DRIconfig **
115 mgaFillInModes( __DRIscreenPrivate *psp,
116 unsigned pixel_bits, unsigned depth_bits,
117 unsigned stencil_bits, GLboolean have_back_buffer )
118 {
119 __DRIconfig **configs;
120 __GLcontextModes * m;
121 unsigned depth_buffer_factor;
122 unsigned back_buffer_factor;
123 GLenum fb_format;
124 GLenum fb_type;
125 int i;
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 uint8_t depth_bits_array[3];
135 uint8_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 if ( pixel_bits == 16 ) {
154 fb_format = GL_RGB;
155 fb_type = GL_UNSIGNED_SHORT_5_6_5;
156 }
157 else {
158 fb_format = GL_BGR;
159 fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
160 }
161
162 configs = driCreateConfigs(fb_format, fb_type,
163 depth_bits_array, stencil_bits_array,
164 depth_buffer_factor,
165 back_buffer_modes, back_buffer_factor);
166 if (configs == NULL) {
167 fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
168 __func__, __LINE__ );
169 return NULL;
170 }
171
172 /* Mark the visual as slow if there are "fake" stencil bits.
173 */
174 for (i = 0; configs[i]; i++) {
175 m = &configs[i]->modes;
176 if ((m->stencilBits != 0) && (m->stencilBits != stencil_bits)) {
177 m->visualRating = GLX_SLOW_CONFIG;
178 }
179 }
180
181 return (const __DRIconfig **) configs;
182 }
183
184 const __DRIextension *mgaScreenExtensions[] = {
185 &driReadDrawableExtension,
186 &driSwapControlExtension.base,
187 &driFrameTrackingExtension.base,
188 &driMediaStreamCounterExtension.base,
189 NULL
190 };
191
192 static GLboolean
193 mgaInitDriver(__DRIscreenPrivate *sPriv)
194 {
195 mgaScreenPrivate *mgaScreen;
196 MGADRIPtr serverInfo = (MGADRIPtr)sPriv->pDevPriv;
197
198 if (sPriv->devPrivSize != sizeof(MGADRIRec)) {
199 fprintf(stderr,"\nERROR! sizeof(MGADRIRec) does not match passed size from device driver\n");
200 return GL_FALSE;
201 }
202
203 /* Allocate the private area */
204 mgaScreen = (mgaScreenPrivate *)MALLOC(sizeof(mgaScreenPrivate));
205 if (!mgaScreen) {
206 __driUtilMessage("Couldn't malloc screen struct");
207 return GL_FALSE;
208 }
209
210 mgaScreen->sPriv = sPriv;
211 sPriv->private = (void *)mgaScreen;
212
213 if (sPriv->drm_version.minor >= 1) {
214 int ret;
215 drm_mga_getparam_t gp;
216
217 gp.param = MGA_PARAM_IRQ_NR;
218 gp.value = &mgaScreen->irq;
219 mgaScreen->irq = 0;
220
221 ret = drmCommandWriteRead( sPriv->fd, DRM_MGA_GETPARAM,
222 &gp, sizeof(gp));
223 if (ret) {
224 fprintf(stderr, "drmMgaGetParam (MGA_PARAM_IRQ_NR): %d\n", ret);
225 FREE(mgaScreen);
226 sPriv->private = NULL;
227 return GL_FALSE;
228 }
229 }
230
231 sPriv->extensions = mgaScreenExtensions;
232
233 if (serverInfo->chipset != MGA_CARD_TYPE_G200 &&
234 serverInfo->chipset != MGA_CARD_TYPE_G400) {
235 FREE(mgaScreen);
236 sPriv->private = NULL;
237 __driUtilMessage("Unrecognized chipset");
238 return GL_FALSE;
239 }
240
241
242 mgaScreen->chipset = serverInfo->chipset;
243 mgaScreen->cpp = serverInfo->cpp;
244
245 mgaScreen->agpMode = serverInfo->agpMode;
246
247 mgaScreen->frontPitch = serverInfo->frontPitch;
248 mgaScreen->frontOffset = serverInfo->frontOffset;
249 mgaScreen->backOffset = serverInfo->backOffset;
250 mgaScreen->backPitch = serverInfo->backPitch;
251 mgaScreen->depthOffset = serverInfo->depthOffset;
252 mgaScreen->depthPitch = serverInfo->depthPitch;
253
254
255 /* The only reason that the MMIO region needs to be accessable and the
256 * primary DMA region base address needs to be known is so that the driver
257 * can busy wait for certain DMA operations to complete (see
258 * mgaWaitForFrameCompletion in mgaioctl.c).
259 *
260 * Starting with MGA DRM version 3.2, these are completely unneeded as
261 * there is a new, in-kernel mechanism for handling the wait.
262 */
263
264 if (mgaScreen->sPriv->drm_version.minor < 2) {
265 mgaScreen->mmio.handle = serverInfo->registers.handle;
266 mgaScreen->mmio.size = serverInfo->registers.size;
267 if ( drmMap( sPriv->fd,
268 mgaScreen->mmio.handle, mgaScreen->mmio.size,
269 &mgaScreen->mmio.map ) < 0 ) {
270 FREE( mgaScreen );
271 sPriv->private = NULL;
272 __driUtilMessage( "Couldn't map MMIO registers" );
273 return GL_FALSE;
274 }
275
276 mgaScreen->primary.handle = serverInfo->primary.handle;
277 mgaScreen->primary.size = serverInfo->primary.size;
278 }
279 else {
280 (void) memset( & mgaScreen->primary, 0, sizeof( mgaScreen->primary ) );
281 (void) memset( & mgaScreen->mmio, 0, sizeof( mgaScreen->mmio ) );
282 }
283
284 mgaScreen->textureOffset[MGA_CARD_HEAP] = serverInfo->textureOffset;
285 mgaScreen->textureOffset[MGA_AGP_HEAP] = (serverInfo->agpTextureOffset |
286 PDEA_pagpxfer_enable | 1);
287
288 mgaScreen->textureSize[MGA_CARD_HEAP] = serverInfo->textureSize;
289 mgaScreen->textureSize[MGA_AGP_HEAP] = serverInfo->agpTextureSize;
290
291
292 /* The texVirtual array stores the base addresses in the CPU's address
293 * space of the texture memory pools. The base address of the on-card
294 * memory pool is calculated as an offset of the base of video memory. The
295 * AGP texture pool has to be mapped into the processes address space by
296 * the DRM.
297 */
298
299 mgaScreen->texVirtual[MGA_CARD_HEAP] = (char *)(mgaScreen->sPriv->pFB +
300 serverInfo->textureOffset);
301
302 if ( serverInfo->agpTextureSize > 0 ) {
303 if (drmMap(sPriv->fd, serverInfo->agpTextureOffset,
304 serverInfo->agpTextureSize,
305 (drmAddress *)&mgaScreen->texVirtual[MGA_AGP_HEAP]) != 0) {
306 FREE(mgaScreen);
307 sPriv->private = NULL;
308 __driUtilMessage("Couldn't map agptexture region");
309 return GL_FALSE;
310 }
311 }
312
313
314 /* For calculating setupdma addresses.
315 */
316
317 mgaScreen->bufs = drmMapBufs(sPriv->fd);
318 if (!mgaScreen->bufs) {
319 FREE(mgaScreen);
320 sPriv->private = NULL;
321 __driUtilMessage("Couldn't map dma buffers");
322 return GL_FALSE;
323 }
324 mgaScreen->sarea_priv_offset = serverInfo->sarea_priv_offset;
325
326 /* parse information in __driConfigOptions */
327 driParseOptionInfo (&mgaScreen->optionCache,
328 __driConfigOptions, __driNConfigOptions);
329
330 return GL_TRUE;
331 }
332
333
334 static void
335 mgaDestroyScreen(__DRIscreenPrivate *sPriv)
336 {
337 mgaScreenPrivate *mgaScreen = (mgaScreenPrivate *) sPriv->private;
338
339 if (MGA_DEBUG&DEBUG_VERBOSE_DRI)
340 fprintf(stderr, "mgaDestroyScreen\n");
341
342 drmUnmapBufs(mgaScreen->bufs);
343
344
345 /* free all option information */
346 driDestroyOptionInfo (&mgaScreen->optionCache);
347
348 FREE(mgaScreen);
349 sPriv->private = NULL;
350 }
351
352
353 extern const struct tnl_pipeline_stage _mga_render_stage;
354
355 static const struct tnl_pipeline_stage *mga_pipeline[] = {
356 &_tnl_vertex_transform_stage,
357 &_tnl_normal_transform_stage,
358 &_tnl_lighting_stage,
359 &_tnl_fog_coordinate_stage,
360 &_tnl_texgen_stage,
361 &_tnl_texture_transform_stage,
362 &_tnl_vertex_program_stage,
363
364 /* REMOVE: point attenuation stage */
365 #if 0
366 &_mga_render_stage, /* ADD: unclipped rastersetup-to-dma */
367 /* Need new ioctl for wacceptseq */
368 #endif
369 &_tnl_render_stage,
370 0,
371 };
372
373
374 static const struct dri_extension g400_extensions[] =
375 {
376 { "GL_ARB_multitexture", NULL },
377 { "GL_ARB_texture_env_add", NULL },
378 { "GL_ARB_texture_env_combine", NULL },
379 { "GL_ARB_texture_env_crossbar", NULL },
380 { "GL_EXT_texture_env_combine", NULL },
381 { "GL_EXT_texture_edge_clamp", NULL },
382 { "GL_ATI_texture_env_combine3", NULL },
383 { NULL, NULL }
384 };
385
386 static const struct dri_extension card_extensions[] =
387 {
388 { "GL_ARB_multisample", GL_ARB_multisample_functions },
389 { "GL_ARB_texture_compression", GL_ARB_texture_compression_functions },
390 { "GL_ARB_texture_rectangle", NULL },
391 { "GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions },
392 { "GL_EXT_blend_logic_op", NULL },
393 { "GL_EXT_fog_coord", GL_EXT_fog_coord_functions },
394 { "GL_EXT_multi_draw_arrays", GL_EXT_multi_draw_arrays_functions },
395 /* paletted_textures currently doesn't work, but we could fix them later */
396 #if defined( need_GL_EXT_paletted_texture )
397 { "GL_EXT_shared_texture_palette", NULL },
398 { "GL_EXT_paletted_texture", GL_EXT_paletted_texture_functions },
399 #endif
400 { "GL_EXT_secondary_color", GL_EXT_secondary_color_functions },
401 { "GL_EXT_stencil_wrap", NULL },
402 { "GL_APPLE_vertex_array_object", GL_APPLE_vertex_array_object_functions },
403 { "GL_MESA_ycbcr_texture", NULL },
404 { "GL_SGIS_generate_mipmap", NULL },
405 { NULL, NULL }
406 };
407
408 static const struct dri_extension ARB_vp_extensions[] = {
409 { "GL_ARB_vertex_program", GL_ARB_vertex_program_functions },
410 { "GL_EXT_gpu_program_parameters", GL_EXT_gpu_program_parameters_functions },
411 { NULL, NULL }
412 };
413
414 static const struct dri_extension NV_vp_extensions[] = {
415 { "GL_NV_vertex_program", GL_NV_vertex_program_functions },
416 { "GL_NV_vertex_program1_1", NULL },
417 { NULL, NULL }
418 };
419
420 static const struct dri_debug_control debug_control[] =
421 {
422 { "fall", DEBUG_VERBOSE_FALLBACK },
423 { "tex", DEBUG_VERBOSE_TEXTURE },
424 { "ioctl", DEBUG_VERBOSE_IOCTL },
425 { "verb", DEBUG_VERBOSE_MSG },
426 { "dri", DEBUG_VERBOSE_DRI },
427 { NULL, 0 }
428 };
429
430
431 static GLboolean
432 mgaCreateContext( const __GLcontextModes *mesaVis,
433 __DRIcontextPrivate *driContextPriv,
434 void *sharedContextPrivate )
435 {
436 int i;
437 unsigned maxlevels;
438 GLcontext *ctx, *shareCtx;
439 mgaContextPtr mmesa;
440 __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
441 mgaScreenPrivate *mgaScreen = (mgaScreenPrivate *)sPriv->private;
442 drm_mga_sarea_t *saPriv = (drm_mga_sarea_t *)(((char*)sPriv->pSAREA)+
443 mgaScreen->sarea_priv_offset);
444 struct dd_function_table functions;
445
446 if (MGA_DEBUG&DEBUG_VERBOSE_DRI)
447 fprintf(stderr, "mgaCreateContext\n");
448
449 /* allocate mga context */
450 mmesa = (mgaContextPtr) CALLOC(sizeof(mgaContext));
451 if (!mmesa) {
452 return GL_FALSE;
453 }
454
455 /* Init default driver functions then plug in our Radeon-specific functions
456 * (the texture functions are especially important)
457 */
458 _mesa_init_driver_functions( &functions );
459 mgaInitDriverFuncs( &functions );
460 mgaInitTextureFuncs( &functions );
461 mgaInitIoctlFuncs( &functions );
462
463 /* Allocate the Mesa context */
464 if (sharedContextPrivate)
465 shareCtx = ((mgaContextPtr) sharedContextPrivate)->glCtx;
466 else
467 shareCtx = NULL;
468 mmesa->glCtx = _mesa_create_context(mesaVis, shareCtx,
469 &functions, (void *) mmesa);
470 if (!mmesa->glCtx) {
471 FREE(mmesa);
472 return GL_FALSE;
473 }
474 driContextPriv->driverPrivate = mmesa;
475
476 /* Init mga state */
477 mmesa->hHWContext = driContextPriv->hHWContext;
478 mmesa->driFd = sPriv->fd;
479 mmesa->driHwLock = &sPriv->pSAREA->lock;
480
481 mmesa->mgaScreen = mgaScreen;
482 mmesa->driScreen = sPriv;
483 mmesa->sarea = (void *)saPriv;
484
485 /* Parse configuration files */
486 driParseConfigFiles (&mmesa->optionCache, &mgaScreen->optionCache,
487 sPriv->myNum, "mga");
488
489 (void) memset( mmesa->texture_heaps, 0, sizeof( mmesa->texture_heaps ) );
490 make_empty_list( & mmesa->swapped );
491
492 mmesa->nr_heaps = mgaScreen->texVirtual[MGA_AGP_HEAP] ? 2 : 1;
493 for ( i = 0 ; i < mmesa->nr_heaps ; i++ ) {
494 mmesa->texture_heaps[i] = driCreateTextureHeap( i, mmesa,
495 mgaScreen->textureSize[i],
496 6,
497 MGA_NR_TEX_REGIONS,
498 (drmTextureRegionPtr)mmesa->sarea->texList[i],
499 &mmesa->sarea->texAge[i],
500 &mmesa->swapped,
501 sizeof( mgaTextureObject_t ),
502 (destroy_texture_object_t *) mgaDestroyTexObj );
503 }
504
505 /* Set the maximum texture size small enough that we can guarentee
506 * that both texture units can bind a maximal texture and have them
507 * on the card at once.
508 */
509 ctx = mmesa->glCtx;
510 if ( mgaScreen->chipset == MGA_CARD_TYPE_G200 ) {
511 ctx->Const.MaxTextureUnits = 1;
512 ctx->Const.MaxTextureImageUnits = 1;
513 ctx->Const.MaxTextureCoordUnits = 1;
514 maxlevels = G200_TEX_MAXLEVELS;
515
516 }
517 else {
518 ctx->Const.MaxTextureUnits = 2;
519 ctx->Const.MaxTextureImageUnits = 2;
520 ctx->Const.MaxTextureCoordUnits = 2;
521 maxlevels = G400_TEX_MAXLEVELS;
522 }
523
524 driCalculateMaxTextureLevels( mmesa->texture_heaps,
525 mmesa->nr_heaps,
526 & ctx->Const,
527 4,
528 11, /* max 2D texture size is 2048x2048 */
529 0, /* 3D textures unsupported. */
530 0, /* cube textures unsupported. */
531 11, /* max texture rect size is 2048x2048 */
532 maxlevels,
533 GL_FALSE,
534 0 );
535
536 ctx->Const.MinLineWidth = 1.0;
537 ctx->Const.MinLineWidthAA = 1.0;
538 ctx->Const.MaxLineWidth = 10.0;
539 ctx->Const.MaxLineWidthAA = 10.0;
540 ctx->Const.LineWidthGranularity = 1.0;
541
542 mmesa->texture_depth = driQueryOptioni (&mmesa->optionCache,
543 "texture_depth");
544 if (mmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FB)
545 mmesa->texture_depth = ( mesaVis->rgbBits >= 24 ) ?
546 DRI_CONF_TEXTURE_DEPTH_32 : DRI_CONF_TEXTURE_DEPTH_16;
547 mmesa->hw_stencil = mesaVis->stencilBits && mesaVis->depthBits == 24;
548
549 switch (mesaVis->depthBits) {
550 case 16:
551 mmesa->depth_scale = 1.0/(GLdouble)0xffff;
552 mmesa->depth_clear_mask = ~0;
553 mmesa->ClearDepth = 0xffff;
554 break;
555 case 24:
556 mmesa->depth_scale = 1.0/(GLdouble)0xffffff;
557 if (mmesa->hw_stencil) {
558 mmesa->depth_clear_mask = 0xffffff00;
559 mmesa->stencil_clear_mask = 0x000000ff;
560 } else
561 mmesa->depth_clear_mask = ~0;
562 mmesa->ClearDepth = 0xffffff00;
563 break;
564 case 32:
565 mmesa->depth_scale = 1.0/(GLdouble)0xffffffff;
566 mmesa->depth_clear_mask = ~0;
567 mmesa->ClearDepth = 0xffffffff;
568 break;
569 };
570
571 mmesa->haveHwStipple = GL_FALSE;
572 mmesa->RenderIndex = -1; /* impossible value */
573 mmesa->dirty = ~0;
574 mmesa->vertex_format = 0;
575 mmesa->CurrentTexObj[0] = 0;
576 mmesa->CurrentTexObj[1] = 0;
577 mmesa->tmu_source[0] = 0;
578 mmesa->tmu_source[1] = 1;
579
580 mmesa->texAge[0] = 0;
581 mmesa->texAge[1] = 0;
582
583 /* Initialize the software rasterizer and helper modules.
584 */
585 _swrast_CreateContext( ctx );
586 _vbo_CreateContext( ctx );
587 _tnl_CreateContext( ctx );
588
589 _swsetup_CreateContext( ctx );
590
591 /* Install the customized pipeline:
592 */
593 _tnl_destroy_pipeline( ctx );
594 _tnl_install_pipeline( ctx, mga_pipeline );
595
596 /* Configure swrast and T&L to match hardware characteristics:
597 */
598 _swrast_allow_pixel_fog( ctx, GL_FALSE );
599 _swrast_allow_vertex_fog( ctx, GL_TRUE );
600 _tnl_allow_pixel_fog( ctx, GL_FALSE );
601 _tnl_allow_vertex_fog( ctx, GL_TRUE );
602
603 mmesa->primary_offset = mmesa->mgaScreen->primary.handle;
604
605 ctx->DriverCtx = (void *) mmesa;
606 mmesa->glCtx = ctx;
607
608 driInitExtensions( ctx, card_extensions, GL_FALSE );
609
610 if (MGA_IS_G400(MGA_CONTEXT(ctx))) {
611 driInitExtensions( ctx, g400_extensions, GL_FALSE );
612 }
613
614 if ( driQueryOptionb( &mmesa->optionCache, "arb_vertex_program" ) ) {
615 driInitExtensions(ctx, ARB_vp_extensions, GL_FALSE);
616 }
617
618 if ( driQueryOptionb( &mmesa->optionCache, "nv_vertex_program" ) ) {
619 driInitExtensions( ctx, NV_vp_extensions, GL_FALSE );
620 }
621
622
623 /* XXX these should really go right after _mesa_init_driver_functions() */
624 mgaDDInitStateFuncs( ctx );
625 mgaDDInitSpanFuncs( ctx );
626 mgaDDInitPixelFuncs( ctx );
627 mgaDDInitTriFuncs( ctx );
628
629 mgaInitVB( ctx );
630 mgaInitState( mmesa );
631
632 driContextPriv->driverPrivate = (void *) mmesa;
633
634 #if DO_DEBUG
635 MGA_DEBUG = driParseDebugString( getenv( "MGA_DEBUG" ),
636 debug_control );
637 #endif
638
639 (*sPriv->systemTime->getUST)( & mmesa->swap_ust );
640
641 if (driQueryOptionb(&mmesa->optionCache, "no_rast")) {
642 fprintf(stderr, "disabling 3D acceleration\n");
643 FALLBACK(mmesa->glCtx, MGA_FALLBACK_DISABLE, 1);
644 }
645
646 return GL_TRUE;
647 }
648
649 static void
650 mgaDestroyContext(__DRIcontextPrivate *driContextPriv)
651 {
652 mgaContextPtr mmesa = (mgaContextPtr) driContextPriv->driverPrivate;
653
654 if (MGA_DEBUG&DEBUG_VERBOSE_DRI)
655 fprintf( stderr, "[%s:%d] mgaDestroyContext start\n",
656 __FILE__, __LINE__ );
657
658 assert(mmesa); /* should never be null */
659 if (mmesa) {
660 GLboolean release_texture_heaps;
661
662
663 release_texture_heaps = (mmesa->glCtx->Shared->RefCount == 1);
664 _swsetup_DestroyContext( mmesa->glCtx );
665 _tnl_DestroyContext( mmesa->glCtx );
666 _vbo_DestroyContext( mmesa->glCtx );
667 _swrast_DestroyContext( mmesa->glCtx );
668
669 mgaFreeVB( mmesa->glCtx );
670
671 /* free the Mesa context */
672 mmesa->glCtx->DriverCtx = NULL;
673 _mesa_destroy_context(mmesa->glCtx);
674
675 if ( release_texture_heaps ) {
676 /* This share group is about to go away, free our private
677 * texture object data.
678 */
679 int i;
680
681 for ( i = 0 ; i < mmesa->nr_heaps ; i++ ) {
682 driDestroyTextureHeap( mmesa->texture_heaps[ i ] );
683 mmesa->texture_heaps[ i ] = NULL;
684 }
685
686 assert( is_empty_list( & mmesa->swapped ) );
687 }
688
689 /* free the option cache */
690 driDestroyOptionCache (&mmesa->optionCache);
691
692 FREE(mmesa);
693 }
694
695 if (MGA_DEBUG&DEBUG_VERBOSE_DRI)
696 fprintf( stderr, "[%s:%d] mgaDestroyContext done\n",
697 __FILE__, __LINE__ );
698 }
699
700
701 static GLboolean
702 mgaCreateBuffer( __DRIscreenPrivate *driScrnPriv,
703 __DRIdrawablePrivate *driDrawPriv,
704 const __GLcontextModes *mesaVis,
705 GLboolean isPixmap )
706 {
707 mgaScreenPrivate *screen = (mgaScreenPrivate *) driScrnPriv->private;
708
709 if (isPixmap) {
710 return GL_FALSE; /* not implemented */
711 }
712 else {
713 GLboolean swStencil = (mesaVis->stencilBits > 0 &&
714 mesaVis->depthBits != 24);
715
716 #if 0
717 driDrawPriv->driverPrivate = (void *)
718 _mesa_create_framebuffer(mesaVis,
719 GL_FALSE, /* software depth buffer? */
720 swStencil,
721 mesaVis->accumRedBits > 0,
722 mesaVis->alphaBits > 0 );
723 #else
724 struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis);
725
726 {
727 driRenderbuffer *frontRb
728 = driNewRenderbuffer(GL_RGBA,
729 NULL,
730 screen->cpp,
731 screen->frontOffset, screen->frontPitch,
732 driDrawPriv);
733 mgaSetSpanFunctions(frontRb, mesaVis);
734 _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base);
735 }
736
737 if (mesaVis->doubleBufferMode) {
738 driRenderbuffer *backRb
739 = driNewRenderbuffer(GL_RGBA,
740 NULL,
741 screen->cpp,
742 screen->backOffset, screen->backPitch,
743 driDrawPriv);
744 mgaSetSpanFunctions(backRb, mesaVis);
745 _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base);
746 }
747
748 if (mesaVis->depthBits == 16) {
749 driRenderbuffer *depthRb
750 = driNewRenderbuffer(GL_DEPTH_COMPONENT16,
751 NULL,
752 screen->cpp,
753 screen->depthOffset, screen->depthPitch,
754 driDrawPriv);
755 mgaSetSpanFunctions(depthRb, mesaVis);
756 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
757 }
758 else if (mesaVis->depthBits == 24) {
759 /* XXX is this right? */
760 if (mesaVis->stencilBits) {
761 driRenderbuffer *depthRb
762 = driNewRenderbuffer(GL_DEPTH_COMPONENT24,
763 NULL,
764 screen->cpp,
765 screen->depthOffset, screen->depthPitch,
766 driDrawPriv);
767 mgaSetSpanFunctions(depthRb, mesaVis);
768 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
769 }
770 else {
771 driRenderbuffer *depthRb
772 = driNewRenderbuffer(GL_DEPTH_COMPONENT32,
773 NULL,
774 screen->cpp,
775 screen->depthOffset, screen->depthPitch,
776 driDrawPriv);
777 mgaSetSpanFunctions(depthRb, mesaVis);
778 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
779 }
780 }
781 else if (mesaVis->depthBits == 32) {
782 driRenderbuffer *depthRb
783 = driNewRenderbuffer(GL_DEPTH_COMPONENT32,
784 NULL,
785 screen->cpp,
786 screen->depthOffset, screen->depthPitch,
787 driDrawPriv);
788 mgaSetSpanFunctions(depthRb, mesaVis);
789 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
790 }
791
792 if (mesaVis->stencilBits > 0 && !swStencil) {
793 driRenderbuffer *stencilRb
794 = driNewRenderbuffer(GL_STENCIL_INDEX8_EXT,
795 NULL,
796 screen->cpp,
797 screen->depthOffset, screen->depthPitch,
798 driDrawPriv);
799 mgaSetSpanFunctions(stencilRb, mesaVis);
800 _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &stencilRb->Base);
801 }
802
803 _mesa_add_soft_renderbuffers(fb,
804 GL_FALSE, /* color */
805 GL_FALSE, /* depth */
806 swStencil,
807 mesaVis->accumRedBits > 0,
808 GL_FALSE, /* alpha */
809 GL_FALSE /* aux */);
810 driDrawPriv->driverPrivate = (void *) fb;
811 #endif
812
813 return (driDrawPriv->driverPrivate != NULL);
814 }
815 }
816
817
818 static void
819 mgaDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
820 {
821 _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)));
822 }
823
824 static void
825 mgaSwapBuffers(__DRIdrawablePrivate *dPriv)
826 {
827 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
828 mgaContextPtr mmesa;
829 GLcontext *ctx;
830 mmesa = (mgaContextPtr) dPriv->driContextPriv->driverPrivate;
831 ctx = mmesa->glCtx;
832
833 if (ctx->Visual.doubleBufferMode) {
834 _mesa_notifySwapBuffers( ctx );
835 mgaCopyBuffer( dPriv );
836 }
837 } else {
838 /* XXX this shouldn't be an error but we can't handle it for now */
839 _mesa_problem(NULL, "%s: drawable has no context!\n", __FUNCTION__);
840 }
841 }
842
843 static GLboolean
844 mgaUnbindContext(__DRIcontextPrivate *driContextPriv)
845 {
846 mgaContextPtr mmesa = (mgaContextPtr) driContextPriv->driverPrivate;
847 if (mmesa)
848 mmesa->dirty = ~0;
849
850 return GL_TRUE;
851 }
852
853 /* This looks buggy to me - the 'b' variable isn't used anywhere...
854 * Hmm - It seems that the drawable is already hooked in to
855 * driDrawablePriv.
856 *
857 * But why are we doing context initialization here???
858 */
859 static GLboolean
860 mgaMakeCurrent(__DRIcontextPrivate *driContextPriv,
861 __DRIdrawablePrivate *driDrawPriv,
862 __DRIdrawablePrivate *driReadPriv)
863 {
864 if (driContextPriv) {
865 mgaContextPtr mmesa = (mgaContextPtr) driContextPriv->driverPrivate;
866
867 if (mmesa->driDrawable != driDrawPriv) {
868 if (driDrawPriv->swap_interval == (unsigned)-1) {
869 driDrawPriv->vblFlags = (mmesa->mgaScreen->irq == 0)
870 ? VBLANK_FLAG_NO_IRQ
871 : driGetDefaultVBlankFlags(&mmesa->optionCache);
872
873 driDrawableInitVBlank( driDrawPriv );
874 }
875
876 mmesa->driDrawable = driDrawPriv;
877 mmesa->dirty = ~0;
878 mmesa->dirty_cliprects = (MGA_FRONT|MGA_BACK);
879 }
880
881 mmesa->driReadable = driReadPriv;
882
883 _mesa_make_current(mmesa->glCtx,
884 (GLframebuffer *) driDrawPriv->driverPrivate,
885 (GLframebuffer *) driReadPriv->driverPrivate);
886 }
887 else {
888 _mesa_make_current(NULL, NULL, NULL);
889 }
890
891 return GL_TRUE;
892 }
893
894
895 void mgaGetLock( mgaContextPtr mmesa, GLuint flags )
896 {
897 __DRIdrawablePrivate *dPriv = mmesa->driDrawable;
898 drm_mga_sarea_t *sarea = mmesa->sarea;
899 int me = mmesa->hHWContext;
900 int i;
901
902 drmGetLock(mmesa->driFd, mmesa->hHWContext, flags);
903
904 DRI_VALIDATE_DRAWABLE_INFO( mmesa->driScreen, dPriv );
905 if (*(dPriv->pStamp) != mmesa->lastStamp) {
906 mmesa->lastStamp = *(dPriv->pStamp);
907 mmesa->SetupNewInputs |= VERT_BIT_POS;
908 mmesa->dirty_cliprects = (MGA_FRONT|MGA_BACK);
909 mgaUpdateRects( mmesa, (MGA_FRONT|MGA_BACK) );
910 driUpdateFramebufferSize(mmesa->glCtx, dPriv);
911 }
912
913 mmesa->dirty |= MGA_UPLOAD_CONTEXT | MGA_UPLOAD_CLIPRECTS;
914
915 mmesa->sarea->dirty |= MGA_UPLOAD_CONTEXT;
916
917 if (sarea->ctxOwner != me) {
918 mmesa->dirty |= (MGA_UPLOAD_CONTEXT | MGA_UPLOAD_TEX0 |
919 MGA_UPLOAD_TEX1 | MGA_UPLOAD_PIPE);
920 sarea->ctxOwner=me;
921 }
922
923 for ( i = 0 ; i < mmesa->nr_heaps ; i++ ) {
924 DRI_AGE_TEXTURES( mmesa->texture_heaps[ i ] );
925 }
926 }
927
928
929 /**
930 * This is the driver specific part of the createNewScreen entry point.
931 *
932 * \todo maybe fold this into intelInitDriver
933 *
934 * \return the __GLcontextModes supported by this driver
935 */
936 static const __DRIconfig **mgaInitScreen(__DRIscreen *psp)
937 {
938 static const __DRIversion ddx_expected = { 1, 2, 0 };
939 static const __DRIversion dri_expected = { 4, 0, 0 };
940 static const __DRIversion drm_expected = { 3, 0, 0 };
941 MGADRIPtr dri_priv = (MGADRIPtr) psp->pDevPriv;
942
943 if ( ! driCheckDriDdxDrmVersions2( "MGA",
944 &psp->dri_version, & dri_expected,
945 &psp->ddx_version, & ddx_expected,
946 &psp->drm_version, & drm_expected ) )
947 return NULL;
948
949
950 /* Calling driInitExtensions here, with a NULL context pointer,
951 * does not actually enable the extensions. It just makes sure
952 * that all the dispatch offsets for all the extensions that
953 * *might* be enables are known. This is needed because the
954 * dispatch offsets need to be known when _mesa_context_create is
955 * called, but we can't enable the extensions until we have a
956 * context pointer.
957 *
958 * Hello chicken. Hello egg. How are you two today?
959 */
960
961 driInitExtensions( NULL, card_extensions, GL_FALSE );
962 driInitExtensions( NULL, g400_extensions, GL_FALSE );
963 driInitExtensions(NULL, ARB_vp_extensions, GL_FALSE);
964 driInitExtensions( NULL, NV_vp_extensions, GL_FALSE );
965
966 if (!mgaInitDriver(psp))
967 return NULL;
968
969 return mgaFillInModes( psp,
970 dri_priv->cpp * 8,
971 (dri_priv->cpp == 2) ? 16 : 24,
972 (dri_priv->cpp == 2) ? 0 : 8,
973 (dri_priv->backOffset != dri_priv->depthOffset) );
974 }
975
976
977 /**
978 * Get information about previous buffer swaps.
979 */
980 static int
981 getSwapInfo( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo )
982 {
983 mgaContextPtr mmesa;
984
985 if ( (dPriv == NULL) || (dPriv->driContextPriv == NULL)
986 || (dPriv->driContextPriv->driverPrivate == NULL)
987 || (sInfo == NULL) ) {
988 return -1;
989 }
990
991 mmesa = (mgaContextPtr) dPriv->driContextPriv->driverPrivate;
992 sInfo->swap_count = mmesa->swap_count;
993 sInfo->swap_ust = mmesa->swap_ust;
994 sInfo->swap_missed_count = mmesa->swap_missed_count;
995
996 sInfo->swap_missed_usage = (sInfo->swap_missed_count != 0)
997 ? driCalculateSwapUsage( dPriv, 0, mmesa->swap_missed_ust )
998 : 0.0;
999
1000 return 0;
1001 }
1002
1003 const struct __DriverAPIRec driDriverAPI = {
1004 .InitScreen = mgaInitScreen,
1005 .DestroyScreen = mgaDestroyScreen,
1006 .CreateContext = mgaCreateContext,
1007 .DestroyContext = mgaDestroyContext,
1008 .CreateBuffer = mgaCreateBuffer,
1009 .DestroyBuffer = mgaDestroyBuffer,
1010 .SwapBuffers = mgaSwapBuffers,
1011 .MakeCurrent = mgaMakeCurrent,
1012 .UnbindContext = mgaUnbindContext,
1013 .GetSwapInfo = getSwapInfo,
1014 .GetDrawableMSC = driDrawableGetMSC32,
1015 .WaitForMSC = driWaitForMSC32,
1016 .WaitForSBC = NULL,
1017 .SwapBuffersMSC = NULL
1018 };