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