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