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