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