Tizen 2.0 Release
[profile/ivi/osmesa.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_dri.h"
61
62 #include "utils.h"
63 #include "vblank.h"
64
65 #include "drirenderbuffer.h"
66
67 #include "GL/internal/dri_interface.h"
68
69 #define need_GL_ARB_vertex_array_object
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     struct gl_config * 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_ARB_vertex_array_object",    GL_ARB_vertex_array_object_functions },
387    { "GL_EXT_blend_logic_op",         NULL },
388    { "GL_EXT_fog_coord",              GL_EXT_fog_coord_functions },
389    /* paletted_textures currently doesn't work, but we could fix them later */
390 #if defined( need_GL_EXT_paletted_texture )
391    { "GL_EXT_shared_texture_palette", NULL },
392    { "GL_EXT_paletted_texture",       GL_EXT_paletted_texture_functions },
393 #endif
394    { "GL_EXT_secondary_color",        GL_EXT_secondary_color_functions },
395    { "GL_EXT_stencil_wrap",           NULL },
396    { "GL_APPLE_vertex_array_object",  GL_APPLE_vertex_array_object_functions },
397    { "GL_MESA_ycbcr_texture",         NULL },
398    { NULL,                            NULL }
399 };
400
401 static const struct dri_extension ARB_vp_extensions[] = {
402    { "GL_ARB_vertex_program",         GL_ARB_vertex_program_functions },
403    { "GL_EXT_gpu_program_parameters", GL_EXT_gpu_program_parameters_functions },
404    { NULL,                            NULL }
405 };
406
407 static const struct dri_extension NV_vp_extensions[] = {
408    { "GL_NV_vertex_program",          GL_NV_vertex_program_functions },
409    { "GL_NV_vertex_program1_1",       NULL },
410    { NULL,                            NULL }
411 };
412
413 static const struct dri_debug_control debug_control[] =
414 {
415     { "fall",  DEBUG_VERBOSE_FALLBACK },
416     { "tex",   DEBUG_VERBOSE_TEXTURE },
417     { "ioctl", DEBUG_VERBOSE_IOCTL },
418     { "verb",  DEBUG_VERBOSE_MSG },
419     { "dri",   DEBUG_VERBOSE_DRI },
420     { NULL,    0 }
421 };
422
423
424 static GLboolean
425 mgaCreateContext( gl_api api,
426                   const struct gl_config *mesaVis,
427                   __DRIcontext *driContextPriv,
428                   void *sharedContextPrivate )
429 {
430    int i;
431    unsigned   maxlevels;
432    struct gl_context *ctx, *shareCtx;
433    mgaContextPtr mmesa;
434    __DRIscreen *sPriv = driContextPriv->driScreenPriv;
435    mgaScreenPrivate *mgaScreen = (mgaScreenPrivate *)sPriv->private;
436    drm_mga_sarea_t *saPriv = (drm_mga_sarea_t *)(((char*)sPriv->pSAREA)+
437                                               mgaScreen->sarea_priv_offset);
438    struct dd_function_table functions;
439
440    if (MGA_DEBUG&DEBUG_VERBOSE_DRI)
441       fprintf(stderr, "mgaCreateContext\n");
442
443    /* allocate mga context */
444    mmesa = (mgaContextPtr) CALLOC(sizeof(mgaContext));
445    if (!mmesa) {
446       return GL_FALSE;
447    }
448
449    /* Init default driver functions then plug in our Radeon-specific functions
450     * (the texture functions are especially important)
451     */
452    _mesa_init_driver_functions( &functions );
453    mgaInitDriverFuncs( &functions );
454    mgaInitTextureFuncs( &functions );
455    mgaInitIoctlFuncs( &functions );
456
457    /* Allocate the Mesa context */
458    if (sharedContextPrivate)
459       shareCtx = ((mgaContextPtr) sharedContextPrivate)->glCtx;
460    else 
461       shareCtx = NULL;
462    mmesa->glCtx = _mesa_create_context(API_OPENGL, mesaVis, shareCtx,
463                                        &functions, (void *) mmesa);
464    if (!mmesa->glCtx) {
465       FREE(mmesa);
466       return GL_FALSE;
467    }
468    driContextPriv->driverPrivate = mmesa;
469
470    /* Init mga state */
471    mmesa->hHWContext = driContextPriv->hHWContext;
472    mmesa->driFd = sPriv->fd;
473    mmesa->driHwLock = &sPriv->pSAREA->lock;
474
475    mmesa->mgaScreen = mgaScreen;
476    mmesa->driScreen = sPriv;
477    mmesa->sarea = (void *)saPriv;
478
479    /* Parse configuration files */
480    driParseConfigFiles (&mmesa->optionCache, &mgaScreen->optionCache,
481                         sPriv->myNum, "mga");
482
483    (void) memset( mmesa->texture_heaps, 0, sizeof( mmesa->texture_heaps ) );
484    make_empty_list( & mmesa->swapped );
485
486    mmesa->nr_heaps = mgaScreen->texVirtual[MGA_AGP_HEAP] ? 2 : 1;
487    for ( i = 0 ; i < mmesa->nr_heaps ; i++ ) {
488       mmesa->texture_heaps[i] = driCreateTextureHeap( i, mmesa,
489             mgaScreen->textureSize[i],
490             6,
491             MGA_NR_TEX_REGIONS,
492             (drmTextureRegionPtr)mmesa->sarea->texList[i],
493             &mmesa->sarea->texAge[i],
494             &mmesa->swapped,
495             sizeof( mgaTextureObject_t ),
496             (destroy_texture_object_t *) mgaDestroyTexObj );
497    }
498
499    /* Set the maximum texture size small enough that we can guarentee
500     * that both texture units can bind a maximal texture and have them
501     * on the card at once.
502     */
503    ctx = mmesa->glCtx;
504    if ( mgaScreen->chipset == MGA_CARD_TYPE_G200 ) {
505       ctx->Const.MaxTextureUnits = 1;
506       ctx->Const.MaxTextureImageUnits = 1;
507       ctx->Const.MaxTextureCoordUnits = 1;
508       maxlevels = G200_TEX_MAXLEVELS;
509
510    }
511    else {
512       ctx->Const.MaxTextureUnits = 2;
513       ctx->Const.MaxTextureImageUnits = 2;
514       ctx->Const.MaxTextureCoordUnits = 2;
515       maxlevels = G400_TEX_MAXLEVELS;
516    }
517
518    driCalculateMaxTextureLevels( mmesa->texture_heaps,
519                                  mmesa->nr_heaps,
520                                  & ctx->Const,
521                                  4,
522                                  11, /* max 2D texture size is 2048x2048 */
523                                  0,  /* 3D textures unsupported. */
524                                  0,  /* cube textures unsupported. */
525                                  11, /* max texture rect size is 2048x2048 */
526                                  maxlevels,
527                                  GL_FALSE,
528                                  0 );
529
530    ctx->Const.MinLineWidth = 1.0;
531    ctx->Const.MinLineWidthAA = 1.0;
532    ctx->Const.MaxLineWidth = 10.0;
533    ctx->Const.MaxLineWidthAA = 10.0;
534    ctx->Const.LineWidthGranularity = 1.0;
535
536    ctx->Const.MaxDrawBuffers = 1;
537
538    mmesa->texture_depth = driQueryOptioni (&mmesa->optionCache,
539                                            "texture_depth");
540    if (mmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FB)
541       mmesa->texture_depth = ( mesaVis->rgbBits >= 24 ) ?
542          DRI_CONF_TEXTURE_DEPTH_32 : DRI_CONF_TEXTURE_DEPTH_16;
543    mmesa->hw_stencil = mesaVis->stencilBits && mesaVis->depthBits == 24;
544
545    switch (mesaVis->depthBits) {
546    case 16: 
547       mmesa->depth_scale = 1.0/(GLdouble)0xffff; 
548       mmesa->depth_clear_mask = ~0;
549       mmesa->ClearDepth = 0xffff;
550       break;
551    case 24:
552       mmesa->depth_scale = 1.0/(GLdouble)0xffffff;
553       if (mmesa->hw_stencil) {
554          mmesa->depth_clear_mask = 0xffffff00;
555          mmesa->stencil_clear_mask = 0x000000ff;
556       } else
557          mmesa->depth_clear_mask = ~0;
558       mmesa->ClearDepth = 0xffffff00;
559       break;
560    case 32:
561       mmesa->depth_scale = 1.0/(GLdouble)0xffffffff;
562       mmesa->depth_clear_mask = ~0;
563       mmesa->ClearDepth = 0xffffffff;
564       break;
565    };
566
567    mmesa->haveHwStipple = GL_FALSE;
568    mmesa->RenderIndex = -1;             /* impossible value */
569    mmesa->dirty = ~0;
570    mmesa->vertex_format = 0;   
571    mmesa->CurrentTexObj[0] = 0;
572    mmesa->CurrentTexObj[1] = 0;
573    mmesa->tmu_source[0] = 0;
574    mmesa->tmu_source[1] = 1;
575
576    mmesa->texAge[0] = 0;
577    mmesa->texAge[1] = 0;
578    
579    /* Initialize the software rasterizer and helper modules.
580     */
581    _swrast_CreateContext( ctx );
582    _vbo_CreateContext( ctx );
583    _tnl_CreateContext( ctx );
584    
585    _swsetup_CreateContext( ctx );
586
587    /* Install the customized pipeline:
588     */
589    _tnl_destroy_pipeline( ctx );
590    _tnl_install_pipeline( ctx, mga_pipeline );
591
592    /* Configure swrast and T&L to match hardware characteristics:
593     */
594    _swrast_allow_pixel_fog( ctx, GL_FALSE );
595    _swrast_allow_vertex_fog( ctx, GL_TRUE );
596    _tnl_allow_pixel_fog( ctx, GL_FALSE );
597    _tnl_allow_vertex_fog( ctx, GL_TRUE );
598
599    mmesa->primary_offset = mmesa->mgaScreen->primary.handle;
600
601    ctx->DriverCtx = (void *) mmesa;
602    mmesa->glCtx = ctx;
603
604    driInitExtensions( ctx, card_extensions, GL_FALSE );
605
606    if (MGA_IS_G400(MGA_CONTEXT(ctx))) {
607       driInitExtensions( ctx, g400_extensions, GL_FALSE );
608    }
609
610    if ( driQueryOptionb( &mmesa->optionCache, "arb_vertex_program" ) ) {
611       driInitExtensions(ctx, ARB_vp_extensions, GL_FALSE);
612    }
613    
614    if ( driQueryOptionb( &mmesa->optionCache, "nv_vertex_program" ) ) {
615       driInitExtensions( ctx, NV_vp_extensions, GL_FALSE );
616    }
617
618         
619    /* XXX these should really go right after _mesa_init_driver_functions() */
620    mgaDDInitStateFuncs( ctx );
621    mgaDDInitSpanFuncs( ctx );
622    mgaDDInitPixelFuncs( ctx );
623    mgaDDInitTriFuncs( ctx );
624
625    mgaInitVB( ctx );
626    mgaInitState( mmesa );
627
628    driContextPriv->driverPrivate = (void *) mmesa;
629
630 #if DO_DEBUG
631    MGA_DEBUG = driParseDebugString( getenv( "MGA_DEBUG" ),
632                                     debug_control );
633 #endif
634
635    (*sPriv->systemTime->getUST)( & mmesa->swap_ust );
636
637    if (driQueryOptionb(&mmesa->optionCache, "no_rast")) {
638       fprintf(stderr, "disabling 3D acceleration\n");
639       FALLBACK(mmesa->glCtx, MGA_FALLBACK_DISABLE, 1);
640    }
641
642    return GL_TRUE;
643 }
644
645 static void
646 mgaDestroyContext(__DRIcontext *driContextPriv)
647 {
648    mgaContextPtr mmesa = (mgaContextPtr) driContextPriv->driverPrivate;
649
650    if (MGA_DEBUG&DEBUG_VERBOSE_DRI)
651       fprintf( stderr, "[%s:%d] mgaDestroyContext start\n",
652                __FILE__, __LINE__ );
653
654    assert(mmesa); /* should never be null */
655    if (mmesa) {
656       GLboolean   release_texture_heaps;
657
658
659       release_texture_heaps = (mmesa->glCtx->Shared->RefCount == 1);
660       _swsetup_DestroyContext( mmesa->glCtx );
661       _tnl_DestroyContext( mmesa->glCtx );
662       _vbo_DestroyContext( mmesa->glCtx );
663       _swrast_DestroyContext( mmesa->glCtx );
664
665       mgaFreeVB( mmesa->glCtx );
666
667       /* free the Mesa context */
668       mmesa->glCtx->DriverCtx = NULL;
669       _mesa_destroy_context(mmesa->glCtx);
670        
671       if ( release_texture_heaps ) {
672          /* This share group is about to go away, free our private
673           * texture object data.
674           */
675          int i;
676
677          for ( i = 0 ; i < mmesa->nr_heaps ; i++ ) {
678             driDestroyTextureHeap( mmesa->texture_heaps[ i ] );
679             mmesa->texture_heaps[ i ] = NULL;
680          }
681
682          assert( is_empty_list( & mmesa->swapped ) );
683       }
684
685       /* free the option cache */
686       driDestroyOptionCache (&mmesa->optionCache);
687
688       FREE(mmesa);
689    }
690
691    if (MGA_DEBUG&DEBUG_VERBOSE_DRI)
692       fprintf( stderr, "[%s:%d] mgaDestroyContext done\n",
693                __FILE__, __LINE__ );
694 }
695
696
697 static GLboolean
698 mgaCreateBuffer( __DRIscreen *driScrnPriv,
699                  __DRIdrawable *driDrawPriv,
700                  const struct gl_config *mesaVis,
701                  GLboolean isPixmap )
702 {
703    mgaScreenPrivate *screen = (mgaScreenPrivate *) driScrnPriv->private;
704
705    if (isPixmap) {
706       return GL_FALSE; /* not implemented */
707    }
708    else {
709       GLboolean swStencil = (mesaVis->stencilBits > 0 && 
710                              mesaVis->depthBits != 24);
711
712 #if 0
713       driDrawPriv->driverPrivate = (void *) 
714          _mesa_create_framebuffer(mesaVis,
715                                   GL_FALSE,  /* software depth buffer? */
716                                   swStencil,
717                                   mesaVis->accumRedBits > 0,
718                                   mesaVis->alphaBits > 0 );
719 #else
720       struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis);
721
722       {
723          driRenderbuffer *frontRb
724             = driNewRenderbuffer(MESA_FORMAT_ARGB8888,
725                                  NULL,
726                                  screen->cpp,
727                                  screen->frontOffset, screen->frontPitch,
728                                  driDrawPriv);
729          mgaSetSpanFunctions(frontRb, mesaVis);
730          _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base);
731       }
732
733       if (mesaVis->doubleBufferMode) {
734          driRenderbuffer *backRb
735             = driNewRenderbuffer(MESA_FORMAT_ARGB8888,
736                                  NULL,
737                                  screen->cpp,
738                                  screen->backOffset, screen->backPitch,
739                                  driDrawPriv);
740          mgaSetSpanFunctions(backRb, mesaVis);
741          _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base);
742       }
743
744       if (mesaVis->depthBits == 16) {
745          driRenderbuffer *depthRb
746             = driNewRenderbuffer(MESA_FORMAT_Z16,
747                                  NULL,
748                                  screen->cpp,
749                                  screen->depthOffset, screen->depthPitch,
750                                  driDrawPriv);
751          mgaSetSpanFunctions(depthRb, mesaVis);
752          _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
753       }
754       else if (mesaVis->depthBits == 24) {
755          /* XXX is this right? */
756          if (mesaVis->stencilBits) {
757             driRenderbuffer *depthRb
758                = driNewRenderbuffer(MESA_FORMAT_Z24_S8,
759                                     NULL,
760                                     screen->cpp,
761                                     screen->depthOffset, screen->depthPitch,
762                                     driDrawPriv);
763             mgaSetSpanFunctions(depthRb, mesaVis);
764             _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
765          }
766          else {
767             driRenderbuffer *depthRb
768                = driNewRenderbuffer(MESA_FORMAT_Z32,
769                                     NULL,
770                                     screen->cpp,
771                                     screen->depthOffset, screen->depthPitch,
772                                     driDrawPriv);
773             mgaSetSpanFunctions(depthRb, mesaVis);
774             _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
775          }
776       }
777       else if (mesaVis->depthBits == 32) {
778          driRenderbuffer *depthRb
779             = driNewRenderbuffer(MESA_FORMAT_Z32,
780                                  NULL,
781                                  screen->cpp,
782                                  screen->depthOffset, screen->depthPitch,
783                                  driDrawPriv);
784          mgaSetSpanFunctions(depthRb, mesaVis);
785          _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
786       }
787
788       if (mesaVis->stencilBits > 0 && !swStencil) {
789          driRenderbuffer *stencilRb
790             = driNewRenderbuffer(MESA_FORMAT_S8,
791                                  NULL,
792                                  screen->cpp,
793                                  screen->depthOffset, screen->depthPitch,
794                                  driDrawPriv);
795          mgaSetSpanFunctions(stencilRb, mesaVis);
796          _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &stencilRb->Base);
797       }
798
799       _mesa_add_soft_renderbuffers(fb,
800                                    GL_FALSE, /* color */
801                                    GL_FALSE, /* depth */
802                                    swStencil,
803                                    mesaVis->accumRedBits > 0,
804                                    GL_FALSE, /* alpha */
805                                    GL_FALSE /* aux */);
806       driDrawPriv->driverPrivate = (void *) fb;
807 #endif
808
809       return (driDrawPriv->driverPrivate != NULL);
810    }
811 }
812
813
814 static void
815 mgaDestroyBuffer(__DRIdrawable *driDrawPriv)
816 {
817    _mesa_reference_framebuffer((struct gl_framebuffer **)(&(driDrawPriv->driverPrivate)), NULL);
818 }
819
820 static void
821 mgaSwapBuffers(__DRIdrawable *dPriv)
822 {
823    if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
824       mgaContextPtr mmesa;
825       struct gl_context *ctx;
826       mmesa = (mgaContextPtr) dPriv->driContextPriv->driverPrivate;
827       ctx = mmesa->glCtx;
828
829       if (ctx->Visual.doubleBufferMode) {
830          _mesa_notifySwapBuffers( ctx );
831          mgaCopyBuffer( dPriv );
832       }
833    } else {
834       /* XXX this shouldn't be an error but we can't handle it for now */
835       _mesa_problem(NULL, "%s: drawable has no context!\n", __FUNCTION__);
836    }
837 }
838
839 static GLboolean
840 mgaUnbindContext(__DRIcontext *driContextPriv)
841 {
842    mgaContextPtr mmesa = (mgaContextPtr) driContextPriv->driverPrivate;
843    if (mmesa)
844       mmesa->dirty = ~0;
845
846    return GL_TRUE;
847 }
848
849 /* This looks buggy to me - the 'b' variable isn't used anywhere...
850  * Hmm - It seems that the drawable is already hooked in to
851  * driDrawablePriv.
852  *
853  * But why are we doing context initialization here???
854  */
855 static GLboolean
856 mgaMakeCurrent(__DRIcontext *driContextPriv,
857                __DRIdrawable *driDrawPriv,
858                __DRIdrawable *driReadPriv)
859 {
860    if (driContextPriv) {
861       mgaContextPtr mmesa = (mgaContextPtr) driContextPriv->driverPrivate;
862
863       if (mmesa->driDrawable != driDrawPriv) {
864          if (driDrawPriv->swap_interval == (unsigned)-1) {
865             driDrawPriv->vblFlags = (mmesa->mgaScreen->irq == 0)
866                ? VBLANK_FLAG_NO_IRQ
867                : driGetDefaultVBlankFlags(&mmesa->optionCache);
868
869             driDrawableInitVBlank( driDrawPriv );
870          }
871
872          mmesa->driDrawable = driDrawPriv;
873          mmesa->dirty = ~0; 
874          mmesa->dirty_cliprects = (MGA_FRONT|MGA_BACK); 
875       }
876
877       mmesa->driReadable = driReadPriv;
878
879       _mesa_make_current(mmesa->glCtx,
880                          (struct gl_framebuffer *) driDrawPriv->driverPrivate,
881                          (struct gl_framebuffer *) driReadPriv->driverPrivate);
882    }
883    else {
884       _mesa_make_current(NULL, NULL, NULL);
885    }
886
887    return GL_TRUE;
888 }
889
890
891 void mgaGetLock( mgaContextPtr mmesa, GLuint flags )
892 {
893    __DRIdrawable *dPriv = mmesa->driDrawable;
894    drm_mga_sarea_t *sarea = mmesa->sarea;
895    int me = mmesa->hHWContext;
896    int i;
897
898    drmGetLock(mmesa->driFd, mmesa->hHWContext, flags);
899
900    DRI_VALIDATE_DRAWABLE_INFO( mmesa->driScreen, dPriv );
901    if (*(dPriv->pStamp) != mmesa->lastStamp) {
902       mmesa->lastStamp = *(dPriv->pStamp);
903       mmesa->SetupNewInputs |= VERT_BIT_POS;
904       mmesa->dirty_cliprects = (MGA_FRONT|MGA_BACK);
905       mgaUpdateRects( mmesa, (MGA_FRONT|MGA_BACK) );
906       driUpdateFramebufferSize(mmesa->glCtx, dPriv);
907    }
908
909    mmesa->dirty |= MGA_UPLOAD_CONTEXT | MGA_UPLOAD_CLIPRECTS;
910
911    mmesa->sarea->dirty |= MGA_UPLOAD_CONTEXT;
912
913    if (sarea->ctxOwner != me) {
914       mmesa->dirty |= (MGA_UPLOAD_CONTEXT | MGA_UPLOAD_TEX0 |
915                        MGA_UPLOAD_TEX1 | MGA_UPLOAD_PIPE);
916       sarea->ctxOwner=me;
917    }
918
919    for ( i = 0 ; i < mmesa->nr_heaps ; i++ ) {
920       DRI_AGE_TEXTURES( mmesa->texture_heaps[ i ] );
921    }
922 }
923
924
925 /**
926  * This is the driver specific part of the createNewScreen entry point.
927  * 
928  * \todo maybe fold this into intelInitDriver
929  *
930  * \return the struct gl_config supported by this driver
931  */
932 static const __DRIconfig **mgaInitScreen(__DRIscreen *psp)
933 {
934    static const __DRIversion ddx_expected = { 1, 2, 0 };
935    static const __DRIversion dri_expected = { 4, 0, 0 };
936    static const __DRIversion drm_expected = { 3, 0, 0 };
937    MGADRIPtr dri_priv = (MGADRIPtr) psp->pDevPriv;
938
939    if ( ! driCheckDriDdxDrmVersions2( "MGA",
940                                       &psp->dri_version, & dri_expected,
941                                       &psp->ddx_version, & ddx_expected,
942                                       &psp->drm_version, & drm_expected ) )
943       return NULL;
944
945
946    if (!mgaInitDriver(psp))
947        return NULL;
948
949    return mgaFillInModes( psp,
950                           dri_priv->cpp * 8,
951                           (dri_priv->cpp == 2) ? 16 : 24,
952                           (dri_priv->cpp == 2) ? 0  : 8,
953                           (dri_priv->backOffset != dri_priv->depthOffset) );
954 }
955
956
957 /**
958  * Get information about previous buffer swaps.
959  */
960 static int
961 getSwapInfo( __DRIdrawable *dPriv, __DRIswapInfo * sInfo )
962 {
963    mgaContextPtr  mmesa;
964
965    if ( (dPriv == NULL) || (dPriv->driContextPriv == NULL)
966         || (dPriv->driContextPriv->driverPrivate == NULL)
967         || (sInfo == NULL) ) {
968       return -1;
969    }
970
971    mmesa = (mgaContextPtr) dPriv->driContextPriv->driverPrivate;
972    sInfo->swap_count = mmesa->swap_count;
973    sInfo->swap_ust = mmesa->swap_ust;
974    sInfo->swap_missed_count = mmesa->swap_missed_count;
975
976    sInfo->swap_missed_usage = (sInfo->swap_missed_count != 0)
977        ? driCalculateSwapUsage( dPriv, 0, mmesa->swap_missed_ust )
978        : 0.0;
979
980    return 0;
981 }
982
983 const struct __DriverAPIRec driDriverAPI = {
984    .InitScreen      = mgaInitScreen,
985    .DestroyScreen   = mgaDestroyScreen,
986    .CreateContext   = mgaCreateContext,
987    .DestroyContext  = mgaDestroyContext,
988    .CreateBuffer    = mgaCreateBuffer,
989    .DestroyBuffer   = mgaDestroyBuffer,
990    .SwapBuffers     = mgaSwapBuffers,
991    .MakeCurrent     = mgaMakeCurrent,
992    .UnbindContext   = mgaUnbindContext,
993    .GetSwapInfo     = getSwapInfo,
994    .GetDrawableMSC  = driDrawableGetMSC32,
995    .WaitForMSC      = driWaitForMSC32,
996    .WaitForSBC      = NULL,
997    .SwapBuffersMSC  = NULL
998 };
999
1000 /* This is the table of extensions that the loader will dlsym() for. */
1001 PUBLIC const __DRIextension *__driDriverExtensions[] = {
1002     &driCoreExtension.base,
1003     &driLegacyExtension.base,
1004     NULL
1005 };