Added an option texture_heaps that allows selecting which texture heaps
[profile/ivi/mesa.git] / src / mesa / drivers / dri / savage / savage_xmesa.c
1 /*
2  * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
3  * Copyright 2001-2003 S3 Graphics, Inc. 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  * the rights to use, copy, modify, merge, publish, distribute, sub license,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the
13  * next paragraph) shall be included in all copies or substantial portions
14  * of the 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  * VIA, S3 GRAPHICS, 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 OTHER
22  * DEALINGS IN THE SOFTWARE.
23  */
24
25
26 #include <X11/Xlibint.h>
27 #include <stdio.h>
28
29 #include "savagecontext.h"
30 #include "context.h"
31 #include "matrix.h"
32
33 #include "simple_list.h"
34
35 #include "utils.h"
36
37 #include "swrast/swrast.h"
38 #include "swrast_setup/swrast_setup.h"
39 #include "tnl/tnl.h"
40 #include "array_cache/acache.h"
41
42 #include "tnl/t_pipeline.h"
43
44 #include "drivers/common/driverfuncs.h"
45
46 #include "savagedd.h"
47 #include "savagestate.h"
48 #include "savagetex.h"
49 #include "savagespan.h"
50 #include "savagetris.h"
51 #include "savageioctl.h"
52 #include "savage_bci.h"
53
54 #include "savage_dri.h"
55
56 #include "texmem.h"
57
58 #include "xmlpool.h"
59
60 /* Driver-specific options
61  */
62 #define SAVAGE_ENABLE_VDMA(def) \
63 DRI_CONF_OPT_BEGIN(enable_vdma,bool,def) \
64         DRI_CONF_DESC(en,"Use DMA for vertex transfers") \
65         DRI_CONF_DESC(de,"Benutze DMA für Vertextransfers") \
66 DRI_CONF_OPT_END
67 #define SAVAGE_ENABLE_FASTPATH(def) \
68 DRI_CONF_OPT_BEGIN(enable_fastpath,bool,def) \
69         DRI_CONF_DESC(en,"Use fast path for unclipped primitives") \
70         DRI_CONF_DESC(de,"Schneller Codepfad für ungeschnittene Polygone") \
71 DRI_CONF_OPT_END
72
73 /* Configuration
74  */
75 PUBLIC const char __driConfigOptions[] =
76 DRI_CONF_BEGIN
77     DRI_CONF_SECTION_QUALITY
78         DRI_CONF_TEXTURE_DEPTH(DRI_CONF_TEXTURE_DEPTH_FB)
79         DRI_CONF_COLOR_REDUCTION(DRI_CONF_COLOR_REDUCTION_DITHER)
80         DRI_CONF_FLOAT_DEPTH(false)
81     DRI_CONF_SECTION_END
82     DRI_CONF_SECTION_PERFORMANCE
83         DRI_CONF_MAX_TEXTURE_UNITS(2,1,2)
84         SAVAGE_ENABLE_VDMA(true)
85         SAVAGE_ENABLE_FASTPATH(true)
86         DRI_CONF_TEXTURE_HEAPS(DRI_CONF_TEXTURE_HEAPS_ALL)
87     DRI_CONF_SECTION_END
88     DRI_CONF_SECTION_DEBUG
89         DRI_CONF_NO_RAST(false)
90     DRI_CONF_SECTION_END
91 DRI_CONF_END;
92 static const GLuint __driNConfigOptions = 8;
93
94 #ifdef USE_NEW_INTERFACE
95 static PFNGLXCREATECONTEXTMODES create_context_modes = NULL;
96 #endif /* USE_NEW_INTERFACE */
97
98 static const struct dri_debug_control debug_control[] =
99 {
100     { "fall",  DEBUG_FALLBACKS },
101     { "api",   DEBUG_VERBOSE_API },
102     { "tex",   DEBUG_VERBOSE_TEX },
103     { "verb",  DEBUG_VERBOSE_MSG },
104     { "dma",   DEBUG_DMA },
105     { "state", DEBUG_STATE },
106     { NULL,    0 }
107 };
108 #ifndef SAVAGE_DEBUG
109 int SAVAGE_DEBUG = 0;
110 #endif
111
112
113 /*For time caculating test*/
114 #if defined(DEBUG_TIME) && DEBUG_TIME
115 struct timeval tv_s,tv_f;
116 unsigned long time_sum=0;
117 struct timeval tv_s1,tv_f1;
118 #endif
119
120 static const char *const card_extensions[] =
121 {
122     "GL_ARB_multitexture",
123     "GL_EXT_texture_lod_bias",
124     "GL_EXT_texture_env_add",
125     NULL
126 };
127
128 extern struct tnl_pipeline_stage _savage_texnorm_stage;
129 extern struct tnl_pipeline_stage _savage_render_stage;
130
131 static const struct tnl_pipeline_stage *savage_pipeline[] = {
132
133    &_tnl_vertex_transform_stage,
134    &_tnl_normal_transform_stage,
135    &_tnl_lighting_stage,
136    &_tnl_fog_coordinate_stage,
137    &_tnl_texgen_stage,
138    &_tnl_texture_transform_stage,
139    &_savage_texnorm_stage,
140    &_savage_render_stage,
141    &_tnl_render_stage,
142    0,
143 };
144
145
146 /* this is first function called in dirver*/
147
148 static GLboolean
149 savageInitDriver(__DRIscreenPrivate *sPriv)
150 {
151   savageScreenPrivate *savageScreen;
152   SAVAGEDRIPtr         gDRIPriv = (SAVAGEDRIPtr)sPriv->pDevPriv;
153
154    /* Allocate the private area */
155    savageScreen = (savageScreenPrivate *)Xmalloc(sizeof(savageScreenPrivate));
156    if (!savageScreen)
157       return GL_FALSE;
158
159    savageScreen->driScrnPriv = sPriv;
160    sPriv->private = (void *)savageScreen;
161
162    savageScreen->chipset=gDRIPriv->chipset; 
163    savageScreen->width=gDRIPriv->width;
164    savageScreen->height=gDRIPriv->height;
165    savageScreen->mem=gDRIPriv->mem;
166    savageScreen->cpp=gDRIPriv->cpp;
167    savageScreen->zpp=gDRIPriv->zpp;
168
169    savageScreen->agpMode=gDRIPriv->agpMode;
170
171    savageScreen->bufferSize=gDRIPriv->bufferSize;
172
173    if (gDRIPriv->cpp == 4) 
174        savageScreen->frontFormat = DV_PF_8888;
175    else
176        savageScreen->frontFormat = DV_PF_565;
177    savageScreen->frontOffset=gDRIPriv->frontOffset;
178    savageScreen->backOffset = gDRIPriv->backOffset; 
179    savageScreen->depthOffset=gDRIPriv->depthOffset;
180
181    savageScreen->textureOffset[SAVAGE_CARD_HEAP] = 
182                                    gDRIPriv->textureOffset;
183    savageScreen->textureSize[SAVAGE_CARD_HEAP] = 
184                                    gDRIPriv->textureSize;
185    savageScreen->logTextureGranularity[SAVAGE_CARD_HEAP] = 
186                                    gDRIPriv->logTextureGranularity;
187
188    savageScreen->textureOffset[SAVAGE_AGP_HEAP] = 
189                                    gDRIPriv->agpTextureHandle;
190    savageScreen->textureSize[SAVAGE_AGP_HEAP] = 
191                                    gDRIPriv->agpTextureSize;
192    savageScreen->logTextureGranularity[SAVAGE_AGP_HEAP] =
193                                    gDRIPriv->logAgpTextureGranularity;
194
195    savageScreen->agpTextures.handle = gDRIPriv->agpTextureHandle;
196    savageScreen->agpTextures.size   = gDRIPriv->agpTextureSize;
197    if (gDRIPriv->agpTextureSize) {
198        if (drmMap(sPriv->fd, 
199                   savageScreen->agpTextures.handle,
200                   savageScreen->agpTextures.size,
201                   (drmAddress *)&(savageScreen->agpTextures.map)) != 0) {
202            Xfree(savageScreen);
203            sPriv->private = NULL;
204            return GL_FALSE;
205        }
206    } else
207        savageScreen->agpTextures.map = NULL;
208
209    savageScreen->texVirtual[SAVAGE_CARD_HEAP] = 
210              (drmAddress)(((unsigned int)sPriv->pFB)+gDRIPriv->textureOffset);
211    savageScreen->texVirtual[SAVAGE_AGP_HEAP] = 
212                         (drmAddress)(savageScreen->agpTextures.map);
213
214    savageScreen->aperture.handle = gDRIPriv->apertureHandle;
215    savageScreen->aperture.size   = gDRIPriv->apertureSize;
216    savageScreen->aperturePitch   = gDRIPriv->aperturePitch;
217    if (drmMap(sPriv->fd, 
218               savageScreen->aperture.handle, 
219               savageScreen->aperture.size, 
220               (drmAddress *)&savageScreen->aperture.map) != 0) 
221    {
222       Xfree(savageScreen);
223       sPriv->private = NULL;
224       return GL_FALSE;
225    }
226
227    savageScreen->bufs = drmMapBufs(sPriv->fd);
228
229    savageScreen->sarea_priv_offset = gDRIPriv->sarea_priv_offset;
230
231    /* parse information in __driConfigOptions */
232    driParseOptionInfo (&savageScreen->optionCache,
233                        __driConfigOptions, __driNConfigOptions);
234
235 #if 0
236    savageDDFastPathInit();
237    savageDDTrifuncInit();
238    savageDDSetupInit();
239 #endif
240    return GL_TRUE;
241 }
242
243 /* Accessed by dlsym from dri_mesa_init.c
244  */
245 static void
246 savageDestroyScreen(__DRIscreenPrivate *sPriv)
247 {
248    savageScreenPrivate *savageScreen = (savageScreenPrivate *)sPriv->private;
249
250    drmUnmapBufs(savageScreen->bufs);
251
252    /* free all option information */
253    driDestroyOptionInfo (&savageScreen->optionCache);
254
255    Xfree(savageScreen);
256    sPriv->private = NULL;
257 }
258
259 #if 0
260 GLvisual *XMesaCreateVisual(Display *dpy,
261                             __DRIscreenPrivate *driScrnPriv,
262                             const XVisualInfo *visinfo,
263                             const __GLXvisualConfig *config)
264 {
265    /* Drivers may change the args to _mesa_create_visual() in order to
266     * setup special visuals.
267     */
268    return _mesa_create_visual( config->rgba,
269                                config->doubleBuffer,
270                                config->stereo,
271                                _mesa_bitcount(visinfo->red_mask),
272                                _mesa_bitcount(visinfo->green_mask),
273                                _mesa_bitcount(visinfo->blue_mask),
274                                config->alphaSize,
275                                0, /* index bits */
276                                config->depthSize,
277                                config->stencilSize,
278                                config->accumRedSize,
279                                config->accumGreenSize,
280                                config->accumBlueSize,
281                                config->accumAlphaSize,
282                                0 /* num samples */ );
283 }
284 #endif
285
286
287 static GLboolean
288 savageCreateContext( const __GLcontextModes *mesaVis,
289                      __DRIcontextPrivate *driContextPriv,
290                      void *sharedContextPrivate )
291 {
292    GLcontext *ctx, *shareCtx;
293    savageContextPtr imesa;
294    __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
295    struct dd_function_table functions;
296    savageScreenPrivate *savageScreen = (savageScreenPrivate *)sPriv->private;
297    drm_savage_sarea_t *saPriv=(drm_savage_sarea_t *)(((char*)sPriv->pSAREA)+
298                                                  savageScreen->sarea_priv_offset);
299    int textureSize[SAVAGE_NR_TEX_HEAPS];
300    int i;
301    imesa = (savageContextPtr)Xcalloc(sizeof(savageContext), 1);
302    if (!imesa) {
303       return GL_FALSE;
304    }
305
306    /* Init default driver functions then plug in savage-specific texture
307     * functions that are needed as early as during context creation. */
308    _mesa_init_driver_functions( &functions );
309    savageDDInitTextureFuncs( &functions );
310
311    /* Allocate the Mesa context */
312    if (sharedContextPrivate)
313       shareCtx = ((savageContextPtr) sharedContextPrivate)->glCtx;
314    else 
315       shareCtx = NULL;
316    ctx = _mesa_create_context(mesaVis, shareCtx, &functions, imesa);
317    if (!ctx) {
318       Xfree(imesa);
319       return GL_FALSE;
320    }
321    driContextPriv->driverPrivate = imesa;
322
323    imesa->cmdBuf.size = SAVAGE_CMDBUF_SIZE;
324    imesa->cmdBuf.base = imesa->cmdBuf.write =
325        malloc(SAVAGE_CMDBUF_SIZE * sizeof(drm_savage_cmd_header_t));
326    if (!imesa->cmdBuf.base)
327        return GL_FALSE;
328
329    /* Parse configuration files */
330    driParseConfigFiles (&imesa->optionCache, &savageScreen->optionCache,
331                         sPriv->myNum, "savage");
332
333    imesa->float_depth = driQueryOptionb(&imesa->optionCache, "float_depth") &&
334        savageScreen->chipset >= S3_SAVAGE4;
335    imesa->no_rast = driQueryOptionb(&imesa->optionCache, "no_rast");
336
337 #if 0
338    ctx->Const.MinLineWidth = 1.0;
339    ctx->Const.MinLineWidthAA = 1.0;
340    ctx->Const.MaxLineWidth = 3.0;
341    ctx->Const.MaxLineWidthAA = 3.0;
342    ctx->Const.LineWidthGranularity = 1.0;
343 #endif
344    
345    /* Dri stuff
346     */
347    imesa->hHWContext = driContextPriv->hHWContext;
348    imesa->driFd = sPriv->fd;
349    imesa->driHwLock = &sPriv->pSAREA->lock;
350    
351    imesa->savageScreen = savageScreen;
352    imesa->driScreen = sPriv;
353    imesa->sarea = saPriv;
354    imesa->glBuffer = NULL;
355    
356    /* DMA buffer */
357
358    for(i=0;i<5;i++)
359    {
360        imesa->apertureBase[i] = ((GLuint)savageScreen->aperture.map + 
361                                  0x01000000 * i );
362    }
363    
364    imesa->aperturePitch = savageScreen->aperturePitch;
365
366    /* change texHeap initialize to support two kind of texture heap*/
367    /* here is some parts of initialization, others in InitDriver() */
368     
369    (void) memset( imesa->textureHeaps, 0, sizeof( imesa->textureHeaps ) );
370    make_empty_list( & imesa->swapped );
371
372    textureSize[SAVAGE_CARD_HEAP] = savageScreen->textureSize[SAVAGE_CARD_HEAP];
373    textureSize[SAVAGE_AGP_HEAP] = savageScreen->textureSize[SAVAGE_AGP_HEAP];
374    imesa->lastTexHeap = savageScreen->texVirtual[SAVAGE_AGP_HEAP] ? 2 : 1;
375    switch(driQueryOptioni (&imesa->optionCache, "texture_heaps")) {
376    case DRI_CONF_TEXTURE_HEAPS_CARD: /* only use card memory, if available */
377        if (textureSize[SAVAGE_CARD_HEAP])
378            imesa->lastTexHeap = 1;
379        break;
380    case DRI_CONF_TEXTURE_HEAPS_GART: /* only use gart memory, if available */
381        if (imesa->lastTexHeap == 2 && textureSize[SAVAGE_AGP_HEAP])
382            textureSize[SAVAGE_CARD_HEAP] = 0;
383        break;
384    /*default: Nothing to do, use all available memory. */
385    }
386    
387    for (i = 0; i < imesa->lastTexHeap; i++) {
388        imesa->textureHeaps[i] = driCreateTextureHeap(
389            i, imesa,
390            textureSize[i],
391            11,                                  /* 2^11 = 2k alignment */
392            SAVAGE_NR_TEX_REGIONS,
393            (drmTextureRegionPtr)imesa->sarea->texList[i],
394             &imesa->sarea->texAge[i],
395             &imesa->swapped,
396             sizeof( savageTexObj ),
397             (destroy_texture_object_t *) savageDestroyTexObj );
398        /* If textureSize[i] == 0 textureHeaps[i] is NULL. This can happen
399         * if there is not enough card memory for a card texture heap. */
400        if (imesa->textureHeaps[i])
401            driSetTextureSwapCounterLocation( imesa->textureHeaps[i],
402                                              & imesa->c_textureSwaps );
403    }
404    imesa->texture_depth = driQueryOptioni (&imesa->optionCache,
405                                            "texture_depth");
406    if (imesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FB)
407        imesa->texture_depth = ( savageScreen->cpp == 4 ) ?
408            DRI_CONF_TEXTURE_DEPTH_32 : DRI_CONF_TEXTURE_DEPTH_16;
409
410    if (savageScreen->chipset >= S3_SAVAGE4)
411        ctx->Const.MaxTextureUnits = 2;
412    else
413        ctx->Const.MaxTextureUnits = 1;
414    if (driQueryOptioni(&imesa->optionCache, "texture_units") <
415        ctx->Const.MaxTextureUnits)
416        ctx->Const.MaxTextureUnits =
417            driQueryOptioni(&imesa->optionCache, "texture_units");
418    ctx->Const.MaxTextureImageUnits = ctx->Const.MaxTextureUnits;
419    ctx->Const.MaxTextureCoordUnits = ctx->Const.MaxTextureUnits;
420
421    driCalculateMaxTextureLevels( imesa->textureHeaps,
422                                  imesa->lastTexHeap,
423                                  & ctx->Const,
424                                  4,
425                                  11, /* max 2D texture size is 2048x2048 */
426                                  0,  /* 3D textures unsupported. */
427                                  0,  /* cube textures unsupported. */
428                                  0,  /* texture rectangles unsupported. */
429                                  12,
430                                  GL_FALSE );
431    if (ctx->Const.MaxTextureLevels <= 6) { /*spec requires at least 64x64*/
432        __driUtilMessage("Not enough texture memory. "
433                         "Falling back to indirect rendering.");
434        Xfree(imesa);
435        return GL_FALSE;
436    }
437
438    imesa->hw_stencil = mesaVis->stencilBits && mesaVis->depthBits == 24;
439    imesa->depth_scale = (imesa->savageScreen->zpp == 2) ?
440        (1.0F/0xffff):(1.0F/0xffffff);
441
442    imesa->bufferSize = savageScreen->bufferSize;
443    imesa->dmaVtxBuf.total = 0;
444    imesa->dmaVtxBuf.used = 0;
445    imesa->dmaVtxBuf.flushed = 0;
446
447    imesa->clientVtxBuf.total = imesa->bufferSize / 4;
448    imesa->clientVtxBuf.used = 0;
449    imesa->clientVtxBuf.flushed = 0;
450    imesa->clientVtxBuf.buf = (u_int32_t *)malloc(imesa->bufferSize);
451
452    imesa->vtxBuf = &imesa->clientVtxBuf;
453
454    imesa->firstElt = -1;
455
456    /* Uninitialized vertex format. Force setting the vertex state in
457     * savageRenderStart.
458     */
459    imesa->vertex_size = 0;
460
461    /* Utah stuff
462     */
463    imesa->new_state = ~0;
464    imesa->new_gl_state = ~0;
465    imesa->RenderIndex = ~0;
466    imesa->dirty = ~0;
467    imesa->lostContext = GL_TRUE;
468    imesa->CurrentTexObj[0] = 0;
469    imesa->CurrentTexObj[1] = 0;
470
471    /* Initialize the software rasterizer and helper modules.
472     */
473    _swrast_CreateContext( ctx );
474    _ac_CreateContext( ctx );
475    _tnl_CreateContext( ctx );
476    
477    _swsetup_CreateContext( ctx );
478
479    /* Install the customized pipeline:
480     */
481    _tnl_destroy_pipeline( ctx );
482    _tnl_install_pipeline( ctx, savage_pipeline );
483    /* DRM versions before 2.1.3 would only render triangle lists. ELTS
484     * support was added in 2.2.0. */
485    if (sPriv->drmMinor < 2) {
486       imesa->enable_fastpath = GL_FALSE;
487       fprintf (stderr,
488                "*** Disabling fast path because your DRM version is buggy "
489                "or doesn't\n*** support ELTS. You need at least Savage DRM "
490                "version 2.2.\n");
491    } else
492       imesa->enable_fastpath = driQueryOptionb(&imesa->optionCache,
493                                                "enable_fastpath");
494    imesa->enable_vdma = driQueryOptionb(&imesa->optionCache, "enable_vdma");
495
496    /* Configure swrast to match hardware characteristics:
497     */
498    _tnl_allow_pixel_fog( ctx, GL_FALSE );
499    _tnl_allow_vertex_fog( ctx, GL_TRUE );
500    _swrast_allow_pixel_fog( ctx, GL_FALSE );
501    _swrast_allow_vertex_fog( ctx, GL_TRUE );
502
503    ctx->DriverCtx = (void *) imesa;
504    imesa->glCtx = ctx;
505
506 #ifndef SAVAGE_DEBUG
507    SAVAGE_DEBUG = driParseDebugString( getenv( "SAVAGE_DEBUG" ),
508                                        debug_control );
509 #endif
510
511    driInitExtensions( ctx, card_extensions, GL_TRUE );
512
513    savageDDInitStateFuncs( ctx );
514    savageDDInitSpanFuncs( ctx );
515    savageDDInitDriverFuncs( ctx );
516    savageDDInitIoctlFuncs( ctx );
517    savageInitTriFuncs( ctx );
518
519    savageDDInitState( imesa );
520
521    driContextPriv->driverPrivate = (void *) imesa;
522
523    return GL_TRUE;
524 }
525
526 static void
527 savageDestroyContext(__DRIcontextPrivate *driContextPriv)
528 {
529    savageContextPtr imesa = (savageContextPtr) driContextPriv->driverPrivate;
530    GLuint i;
531
532    assert (imesa); /* should never be NULL */
533    if (imesa) {
534       savageFlushVertices(imesa);
535       savageReleaseIndexedVerts(imesa);
536       savageFlushCmdBuf(imesa, GL_TRUE); /* release DMA buffer */
537       WAIT_IDLE_EMPTY(imesa);
538
539       for (i = 0; i < imesa->lastTexHeap; i++)
540          driDestroyTextureHeap(imesa->textureHeaps[i]);
541
542       free(imesa->cmdBuf.base);
543       free(imesa->clientVtxBuf.buf);
544
545       _swsetup_DestroyContext(imesa->glCtx );
546       _tnl_DestroyContext( imesa->glCtx );
547       _ac_DestroyContext( imesa->glCtx );
548       _swrast_DestroyContext( imesa->glCtx );
549
550       /* free the Mesa context */
551       imesa->glCtx->DriverCtx = NULL;
552       _mesa_destroy_context(imesa->glCtx);
553
554       /* no longer use vertex_dma_buf*/
555       Xfree(imesa);
556    }
557 }
558
559 static GLboolean
560 savageCreateBuffer( __DRIscreenPrivate *driScrnPriv,
561                     __DRIdrawablePrivate *driDrawPriv,
562                     const __GLcontextModes *mesaVis,
563                     GLboolean isPixmap)
564 {
565    if (isPixmap) {
566       return GL_FALSE; /* not implemented */
567    }
568    else {
569        GLboolean swStencil = mesaVis->stencilBits > 0 && mesaVis->depthBits != 24;
570       driDrawPriv->driverPrivate = (void *) 
571          _mesa_create_framebuffer(mesaVis,
572                                   GL_FALSE,  /* software depth buffer? */
573                                   swStencil,
574                                   mesaVis->accumRedBits > 0,
575                                   mesaVis->alphaBits > 0 );
576
577       return (driDrawPriv->driverPrivate != NULL);
578    }
579 }
580
581 static void
582 savageDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
583 {
584    _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
585 }
586
587 #if 0
588 void XMesaSwapBuffers(__DRIdrawablePrivate *driDrawPriv)
589 {
590    /* XXX should do swap according to the buffer, not the context! */
591    savageContextPtr imesa = savageCtx; 
592
593    FLUSH_VB( imesa->glCtx, "swap buffers" );
594    savageSwapBuffers(imesa);
595 }
596 #endif
597
598 void savageXMesaSetFrontClipRects( savageContextPtr imesa )
599 {
600    __DRIdrawablePrivate *dPriv = imesa->driDrawable;
601
602    imesa->numClipRects = dPriv->numClipRects;
603    imesa->pClipRects = dPriv->pClipRects;
604    imesa->dirty |= SAVAGE_UPLOAD_CLIPRECTS;
605    imesa->drawX = dPriv->x;
606    imesa->drawY = dPriv->y;
607
608    savageEmitDrawingRectangle( imesa );
609 }
610
611
612 void savageXMesaSetBackClipRects( savageContextPtr imesa )
613 {
614    __DRIdrawablePrivate *dPriv = imesa->driDrawable;
615
616    if (dPriv->numBackClipRects == 0) 
617    {
618
619
620       imesa->numClipRects = dPriv->numClipRects;
621       imesa->pClipRects = dPriv->pClipRects;
622       imesa->drawX = dPriv->x;
623       imesa->drawY = dPriv->y;
624    } else {
625
626
627       imesa->numClipRects = dPriv->numBackClipRects;
628       imesa->pClipRects = dPriv->pBackClipRects;
629       imesa->drawX = dPriv->backX;
630       imesa->drawY = dPriv->backY;
631    }
632
633    savageEmitDrawingRectangle( imesa );
634    imesa->dirty |= SAVAGE_UPLOAD_CLIPRECTS;
635
636
637 }
638
639
640 static void savageXMesaWindowMoved( savageContextPtr imesa ) 
641 {
642    if (0)
643       fprintf(stderr, "savageXMesaWindowMoved\n\n");
644
645    switch (imesa->glCtx->Color._DrawDestMask[0]) {
646    case DD_FRONT_LEFT_BIT:
647       savageXMesaSetFrontClipRects( imesa );
648       break;
649    case DD_BACK_LEFT_BIT:
650       savageXMesaSetBackClipRects( imesa );
651       break;
652    default:
653        break;
654    }
655 }
656
657
658 static GLboolean
659 savageUnbindContext(__DRIcontextPrivate *driContextPriv)
660 {
661    savageContextPtr savage = (savageContextPtr) driContextPriv->driverPrivate;
662    if (savage)
663       savage->dirty = ~0;
664
665    return GL_TRUE;
666 }
667
668 #if 0
669 static GLboolean
670 savageOpenFullScreen(__DRIcontextPrivate *driContextPriv)
671 {
672     
673   
674     
675     if (driContextPriv) {
676       savageContextPtr imesa = (savageContextPtr) driContextPriv->driverPrivate;
677       imesa->IsFullScreen = GL_TRUE;
678       imesa->backup_frontOffset = imesa->savageScreen->frontOffset;
679       imesa->backup_backOffset = imesa->savageScreen->backOffset;
680       imesa->backup_frontBitmapDesc = imesa->savageScreen->frontBitmapDesc;
681       imesa->savageScreen->frontBitmapDesc = imesa->savageScreen->backBitmapDesc;      
682       imesa->toggle = TARGET_BACK;
683    }
684
685     return GL_TRUE;
686 }
687
688 static GLboolean
689 savageCloseFullScreen(__DRIcontextPrivate *driContextPriv)
690 {
691     
692     if (driContextPriv) {
693       savageContextPtr imesa = (savageContextPtr) driContextPriv->driverPrivate;
694       WAIT_IDLE_EMPTY(imesa);
695       imesa->IsFullScreen = GL_FALSE;   
696       imesa->savageScreen->frontOffset = imesa->backup_frontOffset;
697       imesa->savageScreen->backOffset = imesa->backup_backOffset;
698       imesa->savageScreen->frontBitmapDesc = imesa->backup_frontBitmapDesc;
699    }
700     return GL_TRUE;
701 }
702 #endif
703
704 static GLboolean
705 savageMakeCurrent(__DRIcontextPrivate *driContextPriv,
706                   __DRIdrawablePrivate *driDrawPriv,
707                   __DRIdrawablePrivate *driReadPriv)
708 {
709    if (driContextPriv) {
710       savageContextPtr imesa = (savageContextPtr) driContextPriv->driverPrivate;
711       
712       imesa->driReadable = driReadPriv;
713       imesa->driDrawable = driDrawPriv;
714       imesa->mesa_drawable = driDrawPriv;
715       imesa->dirty = ~0;
716       
717       _mesa_make_current2(imesa->glCtx,
718                           (GLframebuffer *) driDrawPriv->driverPrivate,
719                           (GLframebuffer *) driReadPriv->driverPrivate);
720       
721       savageXMesaWindowMoved( imesa );
722    }
723    else 
724    {
725       _mesa_make_current(NULL, NULL);
726    }
727    return GL_TRUE;
728 }
729
730
731 void savageGetLock( savageContextPtr imesa, GLuint flags ) 
732 {
733    __DRIdrawablePrivate *dPriv = imesa->driDrawable;
734    __DRIscreenPrivate *sPriv = imesa->driScreen;
735    drm_savage_sarea_t *sarea = imesa->sarea;
736    int me = imesa->hHWContext;
737    int stamp = dPriv->lastStamp; 
738    int heap;
739
740   
741
742    /* We know there has been contention.
743     */
744    drmGetLock(imesa->driFd, imesa->hHWContext, flags);  
745
746
747    /* Note contention for throttling hint
748     */
749    imesa->any_contend = 1;
750
751    /* If the window moved, may need to set a new cliprect now.
752     *
753     * NOTE: This releases and regains the hw lock, so all state
754     * checking must be done *after* this call:
755     */
756    DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv);            
757
758
759   
760
761    /* If we lost context, need to dump all registers to hardware.
762     * Note that we don't care about 2d contexts, even if they perform
763     * accelerated commands, so the DRI locking in the X server is even
764     * more broken than usual.
765     */
766    if (sarea->ctxOwner != me) {
767       imesa->dirty |= (SAVAGE_UPLOAD_LOCAL |
768                        SAVAGE_UPLOAD_GLOBAL |
769                        SAVAGE_UPLOAD_FOGTBL |
770                        SAVAGE_UPLOAD_TEX0 |
771                        SAVAGE_UPLOAD_TEX1 |
772                        SAVAGE_UPLOAD_TEXGLOBAL |
773                        SAVAGE_UPLOAD_CLIPRECTS);
774       imesa->lostContext = GL_TRUE;
775       sarea->ctxOwner = me;
776    }
777
778    for (heap = 0; heap < imesa->lastTexHeap; ++heap) {
779       DRI_AGE_TEXTURES( imesa->textureHeaps[heap] );
780    }
781
782    if (dPriv->lastStamp != stamp)
783       savageXMesaWindowMoved( imesa );
784
785   
786    
787 }
788
789
790
791 static const struct __DriverAPIRec savageAPI = {
792    savageInitDriver,
793    savageDestroyScreen,
794    savageCreateContext,
795    savageDestroyContext,
796    savageCreateBuffer,
797    savageDestroyBuffer,
798    savageSwapBuffers,
799    savageMakeCurrent,
800    savageUnbindContext
801 };
802
803
804
805 #ifndef DRI_NEW_INTERFACE_ONLY
806 /*
807  * This is the (old) bootstrap function for the driver.
808  * The __driCreateScreen name is the symbol that libGL.so fetches.
809  * Return:  pointer to a __DRIscreenPrivate.
810  */
811 void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
812                         int numConfigs, __GLXvisualConfig *config)
813 {
814    __DRIscreenPrivate *psp;
815    psp = __driUtilCreateScreen(dpy, scrn, psc, numConfigs, config, &savageAPI);
816    return (void *) psp;
817 }
818 #endif /* DRI_NEW_INTERFACE_ONLY */
819
820
821
822 #ifdef USE_NEW_INTERFACE
823 static __GLcontextModes *
824 savageFillInModes( unsigned pixel_bits, unsigned depth_bits,
825                    unsigned stencil_bits, GLboolean have_back_buffer )
826 {
827     __GLcontextModes * modes;
828     __GLcontextModes * m;
829     unsigned num_modes;
830     unsigned depth_buffer_factor;
831     unsigned back_buffer_factor;
832     GLenum fb_format;
833     GLenum fb_type;
834
835     /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
836      * enough to add support.  Basically, if a context is created with an
837      * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
838      * will never be used.
839      *
840      * FK: What about drivers that don't use page flipping? Could they
841      * just expose GLX_SWAP_COPY_OML?
842      */
843     static const GLenum back_buffer_modes[] = {
844         GLX_NONE, GLX_SWAP_UNDEFINED_OML /*, GLX_SWAP_COPY_OML */
845     };
846
847     u_int8_t depth_bits_array[2];
848     u_int8_t stencil_bits_array[2];
849
850
851     depth_bits_array[0] = depth_bits;
852     depth_bits_array[1] = depth_bits;
853     
854     /* Just like with the accumulation buffer, always provide some modes
855      * with a stencil buffer.  It will be a sw fallback, but some apps won't
856      * care about that.
857      */
858     stencil_bits_array[0] = 0;
859     stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
860
861     depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 2 : 1;
862     back_buffer_factor  = (have_back_buffer) ? 2 : 1;
863
864     num_modes = depth_buffer_factor * back_buffer_factor * 4;
865
866     if ( pixel_bits == 16 ) {
867         fb_format = GL_RGB;
868         fb_type = GL_UNSIGNED_SHORT_5_6_5;
869     }
870     else {
871         fb_format = GL_BGR;
872         fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
873     }
874
875     modes = (*create_context_modes)( num_modes, sizeof( __GLcontextModes ) );
876     m = modes;
877     if ( ! driFillInModes( & m, fb_format, fb_type,
878                            depth_bits_array, stencil_bits_array, depth_buffer_factor,
879                            back_buffer_modes, back_buffer_factor,
880                            GLX_TRUE_COLOR ) ) {
881         fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
882                  __func__, __LINE__ );
883         return NULL;
884     }
885
886     if ( ! driFillInModes( & m, fb_format, fb_type,
887                            depth_bits_array, stencil_bits_array, depth_buffer_factor,
888                            back_buffer_modes, back_buffer_factor,
889                            GLX_DIRECT_COLOR ) ) {
890         fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
891                  __func__, __LINE__ );
892         return NULL;
893     }
894
895     /* Mark the visual as slow if there are "fake" stencil bits.
896      */
897     for ( m = modes ; m != NULL ; m = m->next ) {
898         if ( (m->stencilBits != 0) && (m->stencilBits != stencil_bits) ) {
899             m->visualRating = GLX_SLOW_CONFIG;
900         }
901     }
902
903     return modes;
904 }
905
906
907 /**
908  * This is the bootstrap function for the driver.  libGL supplies all of the
909  * requisite information about the system, and the driver initializes itself.
910  * This routine also fills in the linked list pointed to by \c driver_modes
911  * with the \c __GLcontextModes that the driver can support for windows or
912  * pbuffers.
913  * 
914  * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on 
915  *         failure.
916  */
917 PUBLIC
918 void * __driCreateNewScreen( __DRInativeDisplay *dpy, int scrn, __DRIscreen *psc,
919                              const __GLcontextModes * modes,
920                              const __DRIversion * ddx_version,
921                              const __DRIversion * dri_version,
922                              const __DRIversion * drm_version,
923                              const __DRIframebuffer * frame_buffer,
924                              drmAddress pSAREA, int fd, 
925                              int internal_api_version,
926                              __GLcontextModes ** driver_modes )
927                              
928 {
929    __DRIscreenPrivate *psp;
930    static const __DRIversion ddx_expected = { 2, 0, 0 };
931    static const __DRIversion dri_expected = { 4, 0, 0 };
932    static const __DRIversion drm_expected = { 2, 0, 0 };
933
934    if ( ! driCheckDriDdxDrmVersions2( "Savage",
935                                       dri_version, & dri_expected,
936                                       ddx_version, & ddx_expected,
937                                       drm_version, & drm_expected ) ) {
938       return NULL;
939    }
940       
941    psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL,
942                                   ddx_version, dri_version, drm_version,
943                                   frame_buffer, pSAREA, fd,
944                                   internal_api_version, &savageAPI);
945    if ( psp != NULL ) {
946       create_context_modes = (PFNGLXCREATECONTEXTMODES)
947           glXGetProcAddress( (const GLubyte *) "__glXCreateContextModes" );
948       if ( create_context_modes != NULL ) {
949          SAVAGEDRIPtr dri_priv = (SAVAGEDRIPtr)psp->pDevPriv;
950          *driver_modes = savageFillInModes( 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    return (void *) psp;
958 }
959 #endif /* USE_NEW_INTERFACE */