Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / drivers / dri / savage / savagestate.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 <stdio.h>
27
28 #include "main/mtypes.h"
29 #include "main/enums.h"
30 #include "main/macros.h"
31 #include "main/dd.h"
32 #include "main/mm.h"
33 #include "main/state.h"
34
35 #include "savagedd.h"
36 #include "savagecontext.h"
37
38 #include "savagestate.h"
39 #include "savagetex.h"
40 #include "savagetris.h"
41 #include "savageioctl.h"
42 #include "savage_bci.h"
43
44 #include "swrast/swrast.h"
45 #include "vbo/vbo.h"
46 #include "tnl/tnl.h"
47 #include "swrast_setup/swrast_setup.h"
48
49 #include "xmlpool.h"
50
51 /* Savage4, ProSavage[DDR], SuperSavage watermarks */
52 #define S4_ZRLO 24
53 #define S4_ZRHI 24
54 #define S4_ZWLO 0
55 #define S4_ZWHI 0
56
57 #define S4_DRLO 0
58 #define S4_DRHI 0
59 #define S4_DWLO 0
60 #define S4_DWHI 0
61
62 #define S4_TR   15
63
64 /* Savage3D/MX/IX watermarks */
65 #define S3D_ZRLO 8
66 #define S3D_ZRHI 24
67 #define S3D_ZWLO 0
68 #define S3D_ZWHI 24
69
70 #define S3D_DRLO 0
71 #define S3D_DRHI 0
72 #define S3D_DWLO 0
73 #define S3D_DWHI 0
74
75 #define S3D_TR   15
76
77 static void savageBlendFunc_s4(struct gl_context *);
78 static void savageBlendFunc_s3d(struct gl_context *);
79
80 static INLINE GLuint savagePackColor(GLuint format, 
81                                          GLubyte r, GLubyte g, 
82                                          GLubyte b, GLubyte a)
83 {
84     switch (format) {
85         case DV_PF_8888:
86             return SAVAGEPACKCOLOR8888(r,g,b,a);
87         case DV_PF_565:
88             return SAVAGEPACKCOLOR565(r,g,b);
89         default:
90             
91             return 0;
92     }
93 }
94
95
96 static void savageDDAlphaFunc_s4(struct gl_context *ctx, GLenum func, GLfloat ref)
97 {
98     savageBlendFunc_s4(ctx);
99 }
100 static void savageDDAlphaFunc_s3d(struct gl_context *ctx, GLenum func, GLfloat ref)
101 {
102     savageBlendFunc_s3d(ctx);
103 }
104
105 static void savageDDBlendEquationSeparate(struct gl_context *ctx,
106                                           GLenum modeRGB, GLenum modeA)
107 {
108     assert( modeRGB == modeA );
109
110     /* BlendEquation sets ColorLogicOpEnabled in an unexpected 
111      * manner.  
112      */
113     FALLBACK( ctx, SAVAGE_FALLBACK_LOGICOP,
114               (ctx->Color.ColorLogicOpEnabled && 
115                ctx->Color.LogicOp != GL_COPY));
116
117    /* Can only do blend addition, not min, max, subtract, etc. */
118    FALLBACK( ctx, SAVAGE_FALLBACK_BLEND_EQ,
119              modeRGB != GL_FUNC_ADD);
120 }
121
122
123 static void savageBlendFunc_s4(struct gl_context *ctx)
124 {
125     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
126     uint32_t drawLocalCtrl = imesa->regs.s4.drawLocalCtrl.ui;
127     uint32_t drawCtrl0 = imesa->regs.s4.drawCtrl0.ui;
128     uint32_t drawCtrl1 = imesa->regs.s4.drawCtrl1.ui;
129
130     /* set up draw control register (including blending, alpha
131      * test, and shading model)
132      */
133
134     imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites = GL_FALSE;
135
136     /*
137      * blend modes
138      */
139     if(ctx->Color.BlendEnabled){
140         switch (ctx->Color.Blend[0].DstRGB)
141         {
142             case GL_ZERO:
143                 imesa->regs.s4.drawLocalCtrl.ni.dstAlphaMode = DAM_Zero;
144                 break;
145
146             case GL_ONE:
147                 imesa->regs.s4.drawLocalCtrl.ni.dstAlphaMode = DAM_One;
148                 imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites = GL_TRUE;
149                 break;
150
151             case GL_SRC_COLOR:
152                 imesa->regs.s4.drawLocalCtrl.ni.dstAlphaMode = DAM_SrcClr;
153                 imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites = GL_TRUE;
154                 break;
155
156             case GL_ONE_MINUS_SRC_COLOR:
157                 imesa->regs.s4.drawLocalCtrl.ni.dstAlphaMode = DAM_1SrcClr;
158                 imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites = GL_TRUE;
159                 break;
160
161             case GL_SRC_ALPHA:
162                 imesa->regs.s4.drawLocalCtrl.ni.dstAlphaMode = DAM_SrcAlpha;
163                 imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites = GL_TRUE;
164                 break;
165
166             case GL_ONE_MINUS_SRC_ALPHA:
167                 imesa->regs.s4.drawLocalCtrl.ni.dstAlphaMode = DAM_1SrcAlpha;
168                 imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites = GL_TRUE;
169                 break;
170
171             case GL_DST_ALPHA:
172                 if (imesa->glCtx->Visual.alphaBits == 0)
173                 {
174                     imesa->regs.s4.drawLocalCtrl.ni.dstAlphaMode = DAM_One;
175                 }
176                 else
177                 {
178                     imesa->regs.s4.drawLocalCtrl.ni.dstAlphaMode= DAM_DstAlpha;
179                 }
180                 imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites = GL_TRUE;
181                 break;
182
183             case GL_ONE_MINUS_DST_ALPHA:
184                 if (imesa->glCtx->Visual.alphaBits == 0)
185                 {
186                     imesa->regs.s4.drawLocalCtrl.ni.dstAlphaMode = DAM_Zero;
187                 }
188                 else
189                 {
190                     imesa->regs.s4.drawLocalCtrl.ni.dstAlphaMode=DAM_1DstAlpha;
191                     imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites= GL_TRUE;
192                 }
193                 break;
194         }
195
196         switch (ctx->Color.Blend[0].SrcRGB)
197         {
198             case GL_ZERO:
199                 imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode = SAM_Zero;
200                 break;
201
202             case GL_ONE:
203                 imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode = SAM_One;
204                 break;
205
206             case GL_DST_COLOR:
207                 imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode = SAM_DstClr;
208                 imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites = GL_TRUE;
209                 break;
210
211             case GL_ONE_MINUS_DST_COLOR:
212                 imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode = SAM_1DstClr;
213                 imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites = GL_TRUE;
214                 break;
215
216             case GL_SRC_ALPHA:
217                 imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode = SAM_SrcAlpha;
218                 break;
219
220             case GL_ONE_MINUS_SRC_ALPHA:
221                 imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode = SAM_1SrcAlpha;
222                 break;
223
224             case GL_DST_ALPHA:
225                 if (imesa->glCtx->Visual.alphaBits == 0)
226                 {
227                     imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode = SAM_One;
228                 }
229                 else
230                 {
231                     imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode= SAM_DstAlpha;
232                     imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites= GL_TRUE;
233                 }
234                 break;
235
236             case GL_ONE_MINUS_DST_ALPHA:
237                 if (imesa->glCtx->Visual.alphaBits == 0)          
238                 {
239                     imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode = SAM_Zero;
240                 }
241                 else
242                 {
243                     imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode=SAM_1DstAlpha;
244                     imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites= GL_TRUE;
245                 }
246                 break;
247         }
248     }
249     else
250     {
251         imesa->regs.s4.drawLocalCtrl.ni.dstAlphaMode = DAM_Zero;
252         imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode = SAM_One;
253     }
254
255     /* alpha test*/
256
257     if(ctx->Color.AlphaEnabled) 
258     {
259         ACmpFunc a;
260         GLubyte alphaRef;
261
262         CLAMPED_FLOAT_TO_UBYTE(alphaRef,ctx->Color.AlphaRef);
263          
264         switch(ctx->Color.AlphaFunc)  { 
265         case GL_NEVER: a = CF_Never; break;
266         case GL_ALWAYS: a = CF_Always; break;
267         case GL_LESS: a = CF_Less; break; 
268         case GL_LEQUAL: a = CF_LessEqual; break;
269         case GL_EQUAL: a = CF_Equal; break;
270         case GL_GREATER: a = CF_Greater; break;
271         case GL_GEQUAL: a = CF_GreaterEqual; break;
272         case GL_NOTEQUAL: a = CF_NotEqual; break;
273         default:return;
274         }   
275       
276         imesa->regs.s4.drawCtrl1.ni.alphaTestEn = GL_TRUE;
277         imesa->regs.s4.drawCtrl1.ni.alphaTestCmpFunc = a;
278         imesa->regs.s4.drawCtrl0.ni.alphaRefVal = alphaRef;
279     }
280     else
281     {
282         imesa->regs.s4.drawCtrl1.ni.alphaTestEn      = GL_FALSE;
283     }
284
285     /* Set/Reset Z-after-alpha*/
286
287     imesa->regs.s4.drawLocalCtrl.ni.wrZafterAlphaTst =
288         imesa->regs.s4.drawCtrl1.ni.alphaTestEn;
289     /*imesa->regs.s4.drawLocalCtrl.ni.zUpdateEn =
290         ~drawLocalCtrl.ni.wrZafterAlphaTst;*/
291
292     if (drawLocalCtrl != imesa->regs.s4.drawLocalCtrl.ui)
293         imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
294     if (drawCtrl0 != imesa->regs.s4.drawCtrl0.ui ||
295         drawCtrl1 != imesa->regs.s4.drawCtrl1.ui)
296         imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
297 }
298 static void savageBlendFunc_s3d(struct gl_context *ctx)
299 {
300     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
301     uint32_t drawCtrl = imesa->regs.s3d.drawCtrl.ui;
302     uint32_t zBufCtrl = imesa->regs.s3d.zBufCtrl.ui;
303
304     /* set up draw control register (including blending, alpha
305      * test, dithering, and shading model)
306      */
307
308     imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = 0;
309
310     /*
311      * blend modes
312      */
313     if(ctx->Color.BlendEnabled){
314         switch (ctx->Color.Blend[0].DstRGB)
315         {
316             case GL_ZERO:
317                 imesa->regs.s3d.drawCtrl.ni.dstAlphaMode = DAM_Zero;
318                 break;
319
320             case GL_ONE:
321                 imesa->regs.s3d.drawCtrl.ni.dstAlphaMode = DAM_One;
322                 imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE;
323                 break;
324
325             case GL_SRC_COLOR:
326                 imesa->regs.s3d.drawCtrl.ni.dstAlphaMode = DAM_SrcClr;
327                 imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE;
328                 break;
329
330             case GL_ONE_MINUS_SRC_COLOR:
331                 imesa->regs.s3d.drawCtrl.ni.dstAlphaMode = DAM_1SrcClr;
332                 imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE;
333                 break;
334
335             case GL_SRC_ALPHA:
336                 imesa->regs.s3d.drawCtrl.ni.dstAlphaMode = DAM_SrcAlpha;
337                 imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE;
338                 break;
339
340             case GL_ONE_MINUS_SRC_ALPHA:
341                 imesa->regs.s3d.drawCtrl.ni.dstAlphaMode = DAM_1SrcAlpha;
342                 imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE;
343                 break;
344
345             case GL_DST_ALPHA:
346                 if (imesa->glCtx->Visual.alphaBits == 0)
347                 {
348                     imesa->regs.s3d.drawCtrl.ni.dstAlphaMode = DAM_One;
349                 }
350                 else
351                 {
352                     imesa->regs.s3d.drawCtrl.ni.dstAlphaMode = DAM_DstAlpha;
353                 }
354                 imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE;
355                 break;
356
357             case GL_ONE_MINUS_DST_ALPHA:
358                 if (imesa->glCtx->Visual.alphaBits == 0)
359                 {
360                     imesa->regs.s3d.drawCtrl.ni.dstAlphaMode = DAM_Zero;
361                 }
362                 else
363                 {
364                     imesa->regs.s3d.drawCtrl.ni.dstAlphaMode = DAM_1DstAlpha;
365                     imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE;
366                 }
367                 break;
368         }
369
370         switch (ctx->Color.Blend[0].SrcRGB)
371         {
372             case GL_ZERO:
373                 imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_Zero;
374                 break;
375
376             case GL_ONE:
377                 imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_One;
378                 break;
379
380             case GL_DST_COLOR:
381                 imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_DstClr;
382                 imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE;
383                 break;
384
385             case GL_ONE_MINUS_DST_COLOR:
386                 imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_1DstClr;
387                 imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE;
388                 break;
389
390             case GL_SRC_ALPHA:
391                 imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_SrcAlpha;
392                 break;
393
394             case GL_ONE_MINUS_SRC_ALPHA:
395                 imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_1SrcAlpha;
396                 break;
397
398             case GL_DST_ALPHA:
399                 if (imesa->glCtx->Visual.alphaBits == 0)
400                 {
401                     imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_One;
402                 }
403                 else
404                 {
405                     imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_DstAlpha;
406                     imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE;
407                 }
408                 break;
409
410             case GL_ONE_MINUS_DST_ALPHA:
411                 if (imesa->glCtx->Visual.alphaBits == 0)          
412                 {
413                     imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_Zero;
414                 }
415                 else
416                 {
417                     imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_1DstAlpha;
418                     imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE;
419                 }
420                 break;
421         }
422     }
423     else
424     {
425         imesa->regs.s3d.drawCtrl.ni.dstAlphaMode = DAM_Zero;
426         imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_One;
427     }
428
429     /* alpha test*/
430
431     if(ctx->Color.AlphaEnabled) 
432     {
433         ACmpFunc a;
434         GLubyte alphaRef;
435
436         CLAMPED_FLOAT_TO_UBYTE(alphaRef,ctx->Color.AlphaRef);
437          
438         switch(ctx->Color.AlphaFunc)  { 
439         case GL_NEVER: a = CF_Never; break;
440         case GL_ALWAYS: a = CF_Always; break;
441         case GL_LESS: a = CF_Less; break; 
442         case GL_LEQUAL: a = CF_LessEqual; break;
443         case GL_EQUAL: a = CF_Equal; break;
444         case GL_GREATER: a = CF_Greater; break;
445         case GL_GEQUAL: a = CF_GreaterEqual; break;
446         case GL_NOTEQUAL: a = CF_NotEqual; break;
447         default:return;
448         }   
449
450         imesa->regs.s3d.drawCtrl.ni.alphaTestEn = GL_TRUE;
451         imesa->regs.s3d.drawCtrl.ni.alphaTestCmpFunc = a;
452         imesa->regs.s3d.drawCtrl.ni.alphaRefVal = alphaRef;
453     }
454     else
455     {
456         imesa->regs.s3d.drawCtrl.ni.alphaTestEn = GL_FALSE;
457     }
458
459     /* Set/Reset Z-after-alpha*/
460
461     imesa->regs.s3d.zBufCtrl.ni.wrZafterAlphaTst =
462         imesa->regs.s3d.drawCtrl.ni.alphaTestEn;
463
464     if (drawCtrl != imesa->regs.s3d.drawCtrl.ui ||
465         zBufCtrl != imesa->regs.s3d.zBufCtrl.ui)
466         imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
467 }
468
469 static void savageDDBlendFuncSeparate_s4( struct gl_context *ctx, GLenum sfactorRGB, 
470                                           GLenum dfactorRGB, GLenum sfactorA,
471                                           GLenum dfactorA )
472 {
473     assert (dfactorRGB == dfactorA && sfactorRGB == sfactorA);
474     savageBlendFunc_s4( ctx );
475 }
476 static void savageDDBlendFuncSeparate_s3d( struct gl_context *ctx, GLenum sfactorRGB, 
477                                            GLenum dfactorRGB, GLenum sfactorA,
478                                            GLenum dfactorA )
479 {
480     assert (dfactorRGB == dfactorA && sfactorRGB == sfactorA);
481     savageBlendFunc_s3d( ctx );
482 }
483
484
485
486 static void savageDDDepthFunc_s4(struct gl_context *ctx, GLenum func)
487 {
488     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
489     ZCmpFunc zmode;
490     uint32_t drawLocalCtrl = imesa->regs.s4.drawLocalCtrl.ui;
491     uint32_t zBufCtrl = imesa->regs.s4.zBufCtrl.ui;
492     uint32_t zWatermarks = imesa->regs.s4.zWatermarks.ui; /* FIXME: in DRM */
493
494     /* set up z-buffer control register (global)
495      * set up z-buffer offset register (global)
496      * set up z read/write watermarks register (global)
497      */
498
499     switch(func)  { /* reversed (see savageCalcViewport) */
500     case GL_NEVER: zmode = CF_Never; break;
501     case GL_ALWAYS: zmode = CF_Always; break;
502     case GL_LESS: zmode = CF_Greater; break; 
503     case GL_LEQUAL: zmode = CF_GreaterEqual; break;
504     case GL_EQUAL: zmode = CF_Equal; break;
505     case GL_GREATER: zmode = CF_Less; break;
506     case GL_GEQUAL: zmode = CF_LessEqual; break;
507     case GL_NOTEQUAL: zmode = CF_NotEqual; break;
508     default:return;
509     } 
510     if (ctx->Depth.Test)
511     {
512
513         imesa->regs.s4.zBufCtrl.ni.zCmpFunc = zmode;
514         imesa->regs.s4.drawLocalCtrl.ni.zUpdateEn = ctx->Depth.Mask;
515         imesa->regs.s4.drawLocalCtrl.ni.flushPdZbufWrites = GL_TRUE;
516         imesa->regs.s4.zBufCtrl.ni.zBufEn = GL_TRUE;
517     }
518     else if (imesa->glCtx->Stencil._Enabled && imesa->hw_stencil)
519     {
520         /* Need to keep Z on for Stencil. */
521         imesa->regs.s4.zBufCtrl.ni.zCmpFunc = CF_Always;
522         imesa->regs.s4.zBufCtrl.ni.zBufEn   = GL_TRUE;
523         imesa->regs.s4.drawLocalCtrl.ni.zUpdateEn = GL_FALSE;
524         imesa->regs.s4.drawLocalCtrl.ni.flushPdZbufWrites = GL_FALSE;
525     }
526     else
527     {
528
529         if (imesa->regs.s4.drawLocalCtrl.ni.drawUpdateEn == GL_FALSE)
530         {
531             imesa->regs.s4.zBufCtrl.ni.zCmpFunc = CF_Always;
532             imesa->regs.s4.zBufCtrl.ni.zBufEn   = GL_TRUE;
533         }
534         else
535
536             /* DRAWUPDATE_REQUIRES_Z_ENABLED*/
537         {
538             imesa->regs.s4.zBufCtrl.ni.zBufEn         = GL_FALSE;
539         }
540         imesa->regs.s4.drawLocalCtrl.ni.zUpdateEn = GL_FALSE;
541         imesa->regs.s4.drawLocalCtrl.ni.flushPdZbufWrites = GL_FALSE;
542     }
543
544     if (drawLocalCtrl != imesa->regs.s4.drawLocalCtrl.ui)
545         imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
546     if (zBufCtrl != imesa->regs.s4.zBufCtrl.ui ||
547         zWatermarks != imesa->regs.s4.zWatermarks.ui)
548         imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
549 }
550 static void savageDDDepthFunc_s3d(struct gl_context *ctx, GLenum func)
551 {
552     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
553     ZCmpFunc zmode;
554     uint32_t drawCtrl = imesa->regs.s3d.drawCtrl.ui;
555     uint32_t zBufCtrl = imesa->regs.s3d.zBufCtrl.ui;
556     uint32_t zWatermarks = imesa->regs.s3d.zWatermarks.ui; /* FIXME: in DRM */
557
558     /* set up z-buffer control register (global)
559      * set up z-buffer offset register (global)
560      * set up z read/write watermarks register (global)
561      */
562     switch(func)  { /* reversed (see savageCalcViewport) */
563     case GL_NEVER: zmode = CF_Never; break;
564     case GL_ALWAYS: zmode = CF_Always; break;
565     case GL_LESS: zmode = CF_Greater; break; 
566     case GL_LEQUAL: zmode = CF_GreaterEqual; break;
567     case GL_EQUAL: zmode = CF_Equal; break;
568     case GL_GREATER: zmode = CF_Less; break;
569     case GL_GEQUAL: zmode = CF_LessEqual; break;
570     case GL_NOTEQUAL: zmode = CF_NotEqual; break;
571     default:return;
572     } 
573     if (ctx->Depth.Test)
574     {
575         imesa->regs.s3d.zBufCtrl.ni.zBufEn = GL_TRUE;
576         imesa->regs.s3d.zBufCtrl.ni.zCmpFunc = zmode;
577         imesa->regs.s3d.zBufCtrl.ni.zUpdateEn = ctx->Depth.Mask;
578         
579         imesa->regs.s3d.drawCtrl.ni.flushPdZbufWrites = GL_TRUE;
580     }
581     else
582     {
583         if (imesa->regs.s3d.zBufCtrl.ni.drawUpdateEn == GL_FALSE) {
584             imesa->regs.s3d.zBufCtrl.ni.zCmpFunc = CF_Always;
585             imesa->regs.s3d.zBufCtrl.ni.zBufEn = GL_TRUE;
586         }
587         else
588
589             /* DRAWUPDATE_REQUIRES_Z_ENABLED*/
590         {
591             imesa->regs.s3d.zBufCtrl.ni.zBufEn = GL_FALSE;
592         }
593         imesa->regs.s3d.zBufCtrl.ni.zUpdateEn = GL_FALSE;
594         imesa->regs.s3d.drawCtrl.ni.flushPdZbufWrites = GL_FALSE;
595     }
596   
597     if (drawCtrl != imesa->regs.s3d.drawCtrl.ui ||
598         zBufCtrl != imesa->regs.s3d.zBufCtrl.ui)
599         imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
600     if (zWatermarks != imesa->regs.s3d.zWatermarks.ui)
601         imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
602 }
603
604 static void savageDDDepthMask_s4(struct gl_context *ctx, GLboolean flag)
605 {
606     savageDDDepthFunc_s4(ctx,ctx->Depth.Func);
607 }
608 static void savageDDDepthMask_s3d(struct gl_context *ctx, GLboolean flag)
609 {
610     savageDDDepthFunc_s3d(ctx,ctx->Depth.Func);
611 }
612
613
614
615
616 /* =============================================================
617  * Hardware clipping
618  */
619
620
621 static void savageDDScissor( struct gl_context *ctx, GLint x, GLint y, 
622                              GLsizei w, GLsizei h )
623 {
624     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
625
626     /* Emit buffered commands with old scissor state. */
627     FLUSH_BATCH(imesa);
628
629     /* Mirror scissors in private context. */
630     imesa->scissor.enabled = ctx->Scissor.Enabled;
631     imesa->scissor.x = x;
632     imesa->scissor.y = y;
633     imesa->scissor.w = w;
634     imesa->scissor.h = h;
635 }
636
637
638
639 static void savageDDDrawBuffer(struct gl_context *ctx, GLenum mode )
640 {
641     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
642     uint32_t destCtrl = imesa->regs.s4.destCtrl.ui;
643
644     if (ctx->DrawBuffer->_NumColorDrawBuffers != 1) {
645         FALLBACK( ctx, SAVAGE_FALLBACK_DRAW_BUFFER, GL_TRUE );
646         return;
647     }
648
649     switch ( ctx->DrawBuffer->_ColorDrawBufferIndexes[0] ) {
650     case BUFFER_FRONT_LEFT:
651         imesa->IsDouble = GL_FALSE;
652         imesa->regs.s4.destCtrl.ni.offset = imesa->savageScreen->frontOffset>>11;
653         break;
654     case BUFFER_BACK_LEFT:
655         imesa->IsDouble = GL_TRUE;
656         imesa->regs.s4.destCtrl.ni.offset = imesa->savageScreen->backOffset>>11;
657         break;
658     default:
659         FALLBACK( ctx, SAVAGE_FALLBACK_DRAW_BUFFER, GL_TRUE );
660         return;
661     }
662     
663     imesa->NotFirstFrame = GL_FALSE;
664     savageXMesaSetClipRects(imesa);
665     FALLBACK(ctx, SAVAGE_FALLBACK_DRAW_BUFFER, GL_FALSE);
666
667     if (destCtrl != imesa->regs.s4.destCtrl.ui)
668         imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
669 }
670
671 static void savageDDReadBuffer(struct gl_context *ctx, GLenum mode )
672 {
673    /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
674 }
675
676 #if 0
677 static void savageDDSetColor(struct gl_context *ctx, 
678                              GLubyte r, GLubyte g,
679                              GLubyte b, GLubyte a )
680 {
681     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
682     imesa->MonoColor = savagePackColor( imesa->savageScreen->frontFormat, r, g, b, a );
683 }
684 #endif
685
686 /* =============================================================
687  * Window position and viewport transformation
688  */
689
690 void savageCalcViewport( struct gl_context *ctx )
691 {
692    savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
693    const GLfloat *v = ctx->Viewport._WindowMap.m;
694    GLfloat *m = imesa->hw_viewport;
695
696    m[MAT_SX] =   v[MAT_SX];
697    m[MAT_TX] =   v[MAT_TX] + imesa->drawX + SUBPIXEL_X;
698    m[MAT_SY] = - v[MAT_SY];
699    m[MAT_TY] = - v[MAT_TY] + imesa->driDrawable->h + imesa->drawY + SUBPIXEL_Y;
700    /* Depth range is reversed (far: 0, near: 1) so that float depth
701     * compensates for loss of accuracy of far coordinates. */
702    if (imesa->float_depth && imesa->savageScreen->zpp == 2) {
703        /* The Savage 16-bit floating point depth format can't encode
704         * numbers < 2^-16. Make sure all depth values stay greater
705         * than that. */
706        m[MAT_SZ] = - v[MAT_SZ] * imesa->depth_scale * (65535.0/65536.0);
707        m[MAT_TZ] = 1.0 - v[MAT_TZ] * imesa->depth_scale * (65535.0/65536.0);
708    } else {
709        m[MAT_SZ] = - v[MAT_SZ] * imesa->depth_scale;
710        m[MAT_TZ] = 1.0 - v[MAT_TZ] * imesa->depth_scale;
711    }
712
713    imesa->SetupNewInputs = ~0;
714 }
715
716 static void savageViewport( struct gl_context *ctx, 
717                             GLint x, GLint y, 
718                             GLsizei width, GLsizei height )
719 {
720    savageCalcViewport( ctx );
721 }
722
723 static void savageDepthRange( struct gl_context *ctx, 
724                               GLclampd nearval, GLclampd farval )
725 {
726    savageCalcViewport( ctx );
727 }
728
729
730 /* =============================================================
731  * Miscellaneous
732  */
733
734 static void savageDDClearColor(struct gl_context *ctx, 
735                                const GLfloat color[4] )
736 {
737     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
738     GLubyte c[4];
739     CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]);
740     CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]);
741     CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]);
742     CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]);
743
744     imesa->ClearColor = savagePackColor( imesa->savageScreen->frontFormat,
745                                          c[0], c[1], c[2], c[3] );
746 }
747
748 /* Fallback to swrast for select and feedback.
749  */
750 static void savageRenderMode( struct gl_context *ctx, GLenum mode )
751 {
752    FALLBACK( ctx, SAVAGE_FALLBACK_RENDERMODE, (mode != GL_RENDER) );
753 }
754
755
756 #if HW_CULL
757
758 /* =============================================================
759  * Culling - the savage isn't quite as clean here as the rest of
760  *           its interfaces, but it's not bad.
761  */
762 static void savageDDCullFaceFrontFace(struct gl_context *ctx, GLenum unused)
763 {
764     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
765     GLuint cullMode=imesa->LcsCullMode;        
766     switch (ctx->Polygon.CullFaceMode)
767     {
768         case GL_FRONT:
769             switch (ctx->Polygon.FrontFace)
770             {
771                 case GL_CW:
772                     cullMode = BCM_CW;
773                     break;
774                 case GL_CCW:
775                     cullMode = BCM_CCW;
776                     break;
777             }
778             break;
779
780         case GL_BACK:
781             switch (ctx->Polygon.FrontFace)
782             {
783                 case GL_CW:
784                     cullMode = BCM_CCW;
785                     break;
786                 case GL_CCW:
787                     cullMode = BCM_CW;
788                     break;
789             }
790             break;
791     }
792     imesa->LcsCullMode = cullMode;    
793     imesa->new_state |= SAVAGE_NEW_CULL;
794 }
795 #endif /* end #if HW_CULL */
796
797 static void savageUpdateCull( struct gl_context *ctx )
798 {
799 #if HW_CULL
800     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
801     GLuint cullMode;
802     if (ctx->Polygon.CullFlag &&
803         imesa->raster_primitive >= GL_TRIANGLES &&
804         ctx->Polygon.CullFaceMode != GL_FRONT_AND_BACK)
805         cullMode = imesa->LcsCullMode;
806     else
807         cullMode = BCM_None;
808     if (imesa->savageScreen->chipset >= S3_SAVAGE4) {
809         if (imesa->regs.s4.drawCtrl1.ni.cullMode != cullMode) {
810             imesa->regs.s4.drawCtrl1.ni.cullMode = cullMode;
811             imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
812         }
813     } else {
814         if (imesa->regs.s3d.drawCtrl.ni.cullMode != cullMode) {
815             imesa->regs.s3d.drawCtrl.ni.cullMode = cullMode;
816             imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
817         }
818     }
819 #endif /* end  #if HW_CULL */
820 }
821
822
823
824 /* =============================================================
825  * Color masks
826  */
827
828 /* Savage4 can disable draw updates when all channels are
829  * masked. Savage3D has a bit called drawUpdateEn, but it doesn't seem
830  * to have any effect. If only some channels are masked we need a
831  * software fallback on all chips.
832  */
833 static void savageDDColorMask_s4(struct gl_context *ctx, 
834                                  GLboolean r, GLboolean g, 
835                                  GLboolean b, GLboolean a )
836 {
837     savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
838     GLboolean passAny, passAll;
839
840     if (ctx->Visual.alphaBits) {
841         passAny = b || g || r || a;
842         passAll = r && g && b && a;
843     } else {
844         passAny = b || g || r;
845         passAll = r && g && b;
846     }
847
848     if (passAny) {
849         if (!imesa->regs.s4.drawLocalCtrl.ni.drawUpdateEn) {
850             imesa->regs.s4.drawLocalCtrl.ni.drawUpdateEn = GL_TRUE;
851             imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
852         }
853         FALLBACK (ctx, SAVAGE_FALLBACK_COLORMASK, !passAll);
854     } else if (imesa->regs.s4.drawLocalCtrl.ni.drawUpdateEn) {
855         imesa->regs.s4.drawLocalCtrl.ni.drawUpdateEn = GL_FALSE;
856         imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
857     }
858 }
859 static void savageDDColorMask_s3d(struct gl_context *ctx, 
860                                   GLboolean r, GLboolean g, 
861                                   GLboolean b, GLboolean a )
862 {
863     if (ctx->Visual.alphaBits)
864         FALLBACK (ctx, SAVAGE_FALLBACK_COLORMASK, !(r && g && b && a));
865     else
866         FALLBACK (ctx, SAVAGE_FALLBACK_COLORMASK, !(r && g && b));
867 }
868
869 static void savageUpdateSpecular_s4(struct gl_context *ctx) {
870     savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
871     uint32_t drawLocalCtrl = imesa->regs.s4.drawLocalCtrl.ui;
872
873     if (_mesa_need_secondary_color(ctx)) {
874         imesa->regs.s4.drawLocalCtrl.ni.specShadeEn = GL_TRUE;
875     } else {
876         imesa->regs.s4.drawLocalCtrl.ni.specShadeEn = GL_FALSE;
877     }
878
879     if (drawLocalCtrl != imesa->regs.s4.drawLocalCtrl.ui)
880         imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
881 }
882
883 static void savageUpdateSpecular_s3d(struct gl_context *ctx) {
884     savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
885     uint32_t drawCtrl = imesa->regs.s3d.drawCtrl.ui;
886
887     if (_mesa_need_secondary_color(ctx)) {
888         imesa->regs.s3d.drawCtrl.ni.specShadeEn = GL_TRUE;
889     } else {
890         imesa->regs.s3d.drawCtrl.ni.specShadeEn = GL_FALSE;
891     }
892
893     if (drawCtrl != imesa->regs.s3d.drawCtrl.ui)
894         imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
895 }
896
897 static void savageDDLightModelfv_s4(struct gl_context *ctx, GLenum pname, 
898                                     const GLfloat *param)
899 {
900     savageUpdateSpecular_s4 (ctx);
901 }
902 static void savageDDLightModelfv_s3d(struct gl_context *ctx, GLenum pname, 
903                                      const GLfloat *param)
904 {
905     savageUpdateSpecular_s3d (ctx);
906 }
907
908 static void savageDDShadeModel_s4(struct gl_context *ctx, GLuint mod)
909 {
910     savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
911     uint32_t drawLocalCtrl = imesa->regs.s4.drawLocalCtrl.ui;
912
913     if (mod == GL_SMOOTH)  
914     {    
915         imesa->regs.s4.drawLocalCtrl.ni.flatShadeEn = GL_FALSE;
916     }
917     else
918     {
919         imesa->regs.s4.drawLocalCtrl.ni.flatShadeEn = GL_TRUE;
920     }
921
922     if (drawLocalCtrl != imesa->regs.s4.drawLocalCtrl.ui)
923         imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
924 }
925 static void savageDDShadeModel_s3d(struct gl_context *ctx, GLuint mod)
926 {
927     savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
928     uint32_t drawCtrl = imesa->regs.s3d.drawCtrl.ui;
929
930     if (mod == GL_SMOOTH)  
931     {    
932         imesa->regs.s3d.drawCtrl.ni.flatShadeEn = GL_FALSE;
933     }
934     else
935     {
936         imesa->regs.s3d.drawCtrl.ni.flatShadeEn = GL_TRUE;
937     }
938
939     if (drawCtrl != imesa->regs.s3d.drawCtrl.ui)
940         imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
941 }
942
943
944 /* =============================================================
945  * Fog
946  * The fogCtrl register has the same position and the same layout
947  * on savage3d and savage4. No need for two separate functions.
948  */
949
950 static void savageDDFogfv(struct gl_context *ctx, GLenum pname, const GLfloat *param)
951 {
952     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
953     GLuint  fogClr;
954     uint32_t fogCtrl = imesa->regs.s4.fogCtrl.ui;
955
956     /*if ((ctx->Fog.Enabled) &&(pname == GL_FOG_COLOR))*/
957     if (ctx->Fog.Enabled)
958     {
959         fogClr = (((GLubyte)(ctx->Fog.Color[0]*255.0F) << 16) |
960                   ((GLubyte)(ctx->Fog.Color[1]*255.0F) << 8) |
961                   ((GLubyte)(ctx->Fog.Color[2]*255.0F) << 0));
962         imesa->regs.s4.fogCtrl.ni.fogEn  = GL_TRUE;
963         /*cheap fog*/
964         imesa->regs.s4.fogCtrl.ni.fogMode  = GL_TRUE;
965         imesa->regs.s4.fogCtrl.ni.fogClr = fogClr;    
966     }    
967     else
968     {
969         /*No fog*/
970         
971         imesa->regs.s4.fogCtrl.ni.fogEn     = 0;
972         imesa->regs.s4.fogCtrl.ni.fogMode   = 0;
973     }
974
975     if (fogCtrl != imesa->regs.s4.fogCtrl.ui)
976         imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
977 }
978
979
980 static void
981 savageDDStencilFuncSeparate(struct gl_context *ctx, GLenum face, GLenum func,
982                             GLint ref, GLuint mask)
983 {
984     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
985     unsigned a=0;
986     const uint32_t zBufCtrl = imesa->regs.s4.zBufCtrl.ui;
987     const uint32_t stencilCtrl = imesa->regs.s4.stencilCtrl.ui;
988
989     imesa->regs.s4.zBufCtrl.ni.stencilRefVal = ctx->Stencil.Ref[0] & 0xff;
990     imesa->regs.s4.stencilCtrl.ni.readMask  = ctx->Stencil.ValueMask[0] & 0xff;
991
992     switch (ctx->Stencil.Function[0])
993     {
994     case GL_NEVER: a = CF_Never; break;
995     case GL_ALWAYS: a = CF_Always; break;
996     case GL_LESS: a = CF_Less; break; 
997     case GL_LEQUAL: a = CF_LessEqual; break;
998     case GL_EQUAL: a = CF_Equal; break;
999     case GL_GREATER: a = CF_Greater; break;
1000     case GL_GEQUAL: a = CF_GreaterEqual; break;
1001     case GL_NOTEQUAL: a = CF_NotEqual; break;
1002     default:
1003         break;
1004     }
1005
1006     imesa->regs.s4.stencilCtrl.ni.cmpFunc = a;
1007
1008     if (zBufCtrl != imesa->regs.s4.zBufCtrl.ui ||
1009         stencilCtrl != imesa->regs.s4.stencilCtrl.ui)
1010         imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
1011 }
1012
1013 static void
1014 savageDDStencilMaskSeparate(struct gl_context *ctx, GLenum face, GLuint mask)
1015 {
1016     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
1017
1018     if (imesa->regs.s4.stencilCtrl.ni.writeMask != (ctx->Stencil.WriteMask[0] & 0xff)) {
1019         imesa->regs.s4.stencilCtrl.ni.writeMask = (ctx->Stencil.WriteMask[0] & 0xff);
1020         imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
1021     }
1022 }
1023
1024 static unsigned get_stencil_op_value( GLenum op )
1025 {
1026     switch (op)
1027     {
1028     case GL_KEEP:      return STENCIL_Keep;
1029     case GL_ZERO:      return STENCIL_Zero;
1030     case GL_REPLACE:   return STENCIL_Equal;
1031     case GL_INCR:      return STENCIL_IncClamp;
1032     case GL_DECR:      return STENCIL_DecClamp;
1033     case GL_INVERT:    return STENCIL_Invert;
1034     case GL_INCR_WRAP: return STENCIL_Inc;
1035     case GL_DECR_WRAP: return STENCIL_Dec;
1036     }
1037
1038     /* Should *never* get here. */
1039     return STENCIL_Keep;
1040 }
1041
1042 static void
1043 savageDDStencilOpSeparate(struct gl_context *ctx, GLenum face, GLenum fail,
1044                           GLenum zfail, GLenum zpass)
1045 {
1046     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
1047     const uint32_t stencilCtrl = imesa->regs.s4.stencilCtrl.ui;
1048
1049     imesa->regs.s4.stencilCtrl.ni.failOp = get_stencil_op_value( ctx->Stencil.FailFunc[0] );
1050     imesa->regs.s4.stencilCtrl.ni.passZfailOp = get_stencil_op_value( ctx->Stencil.ZFailFunc[0] );
1051     imesa->regs.s4.stencilCtrl.ni.passZpassOp = get_stencil_op_value( ctx->Stencil.ZPassFunc[0] );
1052
1053     if (stencilCtrl != imesa->regs.s4.stencilCtrl.ui)
1054         imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
1055 }
1056
1057
1058 /* =============================================================
1059  */
1060
1061 static void savageDDEnable_s4(struct gl_context *ctx, GLenum cap, GLboolean state)
1062 {
1063    
1064     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
1065     switch(cap) {
1066         case GL_ALPHA_TEST:
1067             /* we should consider the disable case*/
1068             savageBlendFunc_s4(ctx);
1069             break;
1070         case GL_BLEND:
1071             /*add the savageBlendFunc 2001/11/25
1072              * if call no such function, then glDisable(GL_BLEND) will do noting,
1073              *our chip has no disable bit
1074              */ 
1075             savageBlendFunc_s4(ctx);
1076         case GL_COLOR_LOGIC_OP:
1077             /* Fall through: 
1078              * For some reason enable(GL_BLEND) affects ColorLogicOpEnabled.
1079              */
1080             FALLBACK (ctx, SAVAGE_FALLBACK_LOGICOP,
1081                       (ctx->Color.ColorLogicOpEnabled &&
1082                        ctx->Color.LogicOp != GL_COPY));
1083             break;
1084         case GL_DEPTH_TEST:
1085             savageDDDepthFunc_s4(ctx,ctx->Depth.Func);
1086             break;
1087         case GL_SCISSOR_TEST:
1088             savageDDScissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
1089                             ctx->Scissor.Width, ctx->Scissor.Height);
1090             break;
1091         case GL_STENCIL_TEST:
1092             if (!imesa->hw_stencil)
1093                 FALLBACK (ctx, SAVAGE_FALLBACK_STENCIL, state);
1094             else {
1095                 imesa->regs.s4.stencilCtrl.ni.stencilEn = state;
1096                 if (ctx->Stencil._Enabled &&
1097                     imesa->regs.s4.zBufCtrl.ni.zBufEn != GL_TRUE)
1098                 {
1099                     /* Stencil buffer requires Z enabled. */
1100                     imesa->regs.s4.zBufCtrl.ni.zCmpFunc       = CF_Always;
1101                     imesa->regs.s4.zBufCtrl.ni.zBufEn         = GL_TRUE;
1102                     imesa->regs.s4.drawLocalCtrl.ni.zUpdateEn = GL_FALSE;
1103                 }
1104                 imesa->dirty |= SAVAGE_UPLOAD_GLOBAL | SAVAGE_UPLOAD_LOCAL;
1105             }
1106             break;
1107         case GL_FOG:
1108             savageDDFogfv(ctx,0,0);     
1109             break;
1110         case GL_CULL_FACE:
1111 #if HW_CULL
1112             if (state)
1113             {
1114                 savageDDCullFaceFrontFace(ctx,0);
1115             }
1116             else
1117             {
1118                 imesa->LcsCullMode = BCM_None;
1119                 imesa->new_state |= SAVAGE_NEW_CULL;
1120             }
1121 #endif
1122             break;
1123         case GL_DITHER:
1124             if (state)
1125             {
1126                 if ( ctx->Color.DitherFlag )
1127                 {
1128                     imesa->regs.s4.drawCtrl1.ni.ditherEn=GL_TRUE;
1129                 }
1130             }   
1131             if (!ctx->Color.DitherFlag )
1132             {
1133                 imesa->regs.s4.drawCtrl1.ni.ditherEn=GL_FALSE;
1134             }
1135             imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
1136             break;
1137  
1138         case GL_LIGHTING:
1139             savageUpdateSpecular_s4 (ctx);
1140             break;
1141         case GL_TEXTURE_1D:      
1142         case GL_TEXTURE_3D:      
1143             imesa->new_state |= SAVAGE_NEW_TEXTURE;
1144             break;
1145         case GL_TEXTURE_2D:      
1146             imesa->new_state |= SAVAGE_NEW_TEXTURE;
1147             break;
1148         default:
1149             ; 
1150     }    
1151 }
1152 static void savageDDEnable_s3d(struct gl_context *ctx, GLenum cap, GLboolean state)
1153 {
1154    
1155     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
1156     switch(cap) {
1157         case GL_ALPHA_TEST:
1158             /* we should consider the disable case*/
1159             savageBlendFunc_s3d(ctx);
1160             break;
1161         case GL_BLEND:
1162             /*add the savageBlendFunc 2001/11/25
1163              * if call no such function, then glDisable(GL_BLEND) will do noting,
1164              *our chip has no disable bit
1165              */ 
1166             savageBlendFunc_s3d(ctx);
1167         case GL_COLOR_LOGIC_OP:
1168             /* Fall through: 
1169              * For some reason enable(GL_BLEND) affects ColorLogicOpEnabled.
1170              */
1171             FALLBACK (ctx, SAVAGE_FALLBACK_LOGICOP,
1172                       (ctx->Color.ColorLogicOpEnabled &&
1173                        ctx->Color.LogicOp != GL_COPY));
1174             break;
1175         case GL_DEPTH_TEST:
1176             savageDDDepthFunc_s3d(ctx,ctx->Depth.Func);
1177             break;
1178         case GL_SCISSOR_TEST:
1179             savageDDScissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
1180                             ctx->Scissor.Width, ctx->Scissor.Height);
1181             break;
1182         case GL_STENCIL_TEST:
1183             FALLBACK (ctx, SAVAGE_FALLBACK_STENCIL, state);
1184             break;
1185         case GL_FOG:
1186             savageDDFogfv(ctx,0,0);     
1187             break;
1188         case GL_CULL_FACE:
1189 #if HW_CULL
1190             if (state)
1191             {
1192                 savageDDCullFaceFrontFace(ctx,0);
1193             }
1194             else
1195             {
1196                 imesa->LcsCullMode = BCM_None;
1197                 imesa->new_state |= SAVAGE_NEW_CULL;
1198             }
1199 #endif
1200             break;
1201         case GL_DITHER:
1202             if (state)
1203             {
1204                 if ( ctx->Color.DitherFlag )
1205                 {
1206                     imesa->regs.s3d.drawCtrl.ni.ditherEn=GL_TRUE;
1207                 }
1208             }
1209             if (!ctx->Color.DitherFlag )
1210             {
1211                 imesa->regs.s3d.drawCtrl.ni.ditherEn=GL_FALSE;
1212             }
1213             imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
1214             break;
1215  
1216         case GL_LIGHTING:
1217             savageUpdateSpecular_s3d (ctx);
1218             break;
1219         case GL_TEXTURE_1D:      
1220         case GL_TEXTURE_3D:      
1221             imesa->new_state |= SAVAGE_NEW_TEXTURE;
1222             break;
1223         case GL_TEXTURE_2D:      
1224             imesa->new_state |= SAVAGE_NEW_TEXTURE;
1225             break;
1226         default:
1227             ; 
1228     }    
1229 }
1230
1231 void savageDDUpdateHwState( struct gl_context *ctx )
1232 {
1233     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
1234
1235     if (imesa->new_state) {
1236         savageFlushVertices(imesa);
1237         if (imesa->new_state & SAVAGE_NEW_TEXTURE) {
1238             savageUpdateTextureState( ctx );
1239         }
1240         if ((imesa->new_state & SAVAGE_NEW_CULL)) {
1241             savageUpdateCull(ctx);
1242         }
1243         imesa->new_state = 0;
1244     }
1245 }
1246
1247
1248 static void savageDDPrintDirty( const char *msg, GLuint state )
1249 {
1250     fprintf(stderr, "%s (0x%x): %s%s%s%s%s%s\n",           
1251             msg,
1252             (unsigned int) state,
1253             (state & SAVAGE_UPLOAD_LOCAL)      ? "upload-local, " : "",
1254             (state & SAVAGE_UPLOAD_TEX0)       ? "upload-tex0, " : "",
1255             (state & SAVAGE_UPLOAD_TEX1)       ? "upload-tex1, " : "",
1256             (state & SAVAGE_UPLOAD_FOGTBL)     ? "upload-fogtbl, " : "",
1257             (state & SAVAGE_UPLOAD_GLOBAL)     ? "upload-global, " : "",
1258             (state & SAVAGE_UPLOAD_TEXGLOBAL)  ? "upload-texglobal, " : ""
1259             );
1260 }
1261
1262
1263 /**
1264  * Check if global registers were changed
1265  */
1266 static GLboolean savageGlobalRegChanged (savageContextPtr imesa,
1267                                          GLuint first, GLuint last) {
1268     GLuint i;
1269     for (i = first - SAVAGE_FIRST_REG; i <= last - SAVAGE_FIRST_REG; ++i) {
1270         if (((imesa->oldRegs.ui[i] ^ imesa->regs.ui[i]) &
1271              imesa->globalRegMask.ui[i]) != 0)
1272             return GL_TRUE;
1273     }
1274     return GL_FALSE;
1275 }
1276 static void savageEmitOldRegs (savageContextPtr imesa,
1277                                GLuint first, GLuint last, GLboolean global) {
1278     GLuint n = last-first+1;
1279     drm_savage_cmd_header_t *cmd = savageAllocCmdBuf(imesa, n*4);
1280     cmd->state.cmd = SAVAGE_CMD_STATE;
1281     cmd->state.global = global;
1282     cmd->state.count = n;
1283     cmd->state.start = first;
1284     memcpy(cmd+1, &imesa->oldRegs.ui[first-SAVAGE_FIRST_REG], n*4);
1285 }
1286 static void savageEmitContiguousRegs (savageContextPtr imesa,
1287                                       GLuint first, GLuint last) {
1288     GLuint i;
1289     GLuint n = last-first+1;
1290     drm_savage_cmd_header_t *cmd = savageAllocCmdBuf(imesa, n*4);
1291     cmd->state.cmd = SAVAGE_CMD_STATE;
1292     cmd->state.global = savageGlobalRegChanged(imesa, first, last);
1293     cmd->state.count = n;
1294     cmd->state.start = first;
1295     memcpy(cmd+1, &imesa->regs.ui[first-SAVAGE_FIRST_REG], n*4);
1296     /* savageAllocCmdBuf may need to flush the cmd buffer and backup
1297      * the current hardware state. It should see the "old" (current)
1298      * state that has actually been emitted to the hardware. Therefore
1299      * this update is done *after* savageAllocCmdBuf. */
1300     for (i = first - SAVAGE_FIRST_REG; i <= last - SAVAGE_FIRST_REG; ++i)
1301         imesa->oldRegs.ui[i] = imesa->regs.ui[i];
1302     if (SAVAGE_DEBUG & DEBUG_STATE)
1303         fprintf (stderr, "Emitting regs 0x%02x-0x%02x\n", first, last);
1304 }
1305 static void savageEmitChangedRegs (savageContextPtr imesa,
1306                                    GLuint first, GLuint last) {
1307     GLuint i, firstChanged;
1308     firstChanged = SAVAGE_NR_REGS;
1309     for (i = first - SAVAGE_FIRST_REG; i <= last - SAVAGE_FIRST_REG; ++i) {
1310         if (imesa->oldRegs.ui[i] != imesa->regs.ui[i]) {
1311             if (firstChanged == SAVAGE_NR_REGS)
1312                 firstChanged = i;
1313         } else {
1314             if (firstChanged != SAVAGE_NR_REGS) {
1315                 savageEmitContiguousRegs (imesa, firstChanged+SAVAGE_FIRST_REG,
1316                                           i-1+SAVAGE_FIRST_REG);
1317                 firstChanged = SAVAGE_NR_REGS;
1318             }
1319         }
1320     }
1321     if (firstChanged != SAVAGE_NR_REGS)
1322         savageEmitContiguousRegs (imesa, firstChanged+SAVAGE_FIRST_REG,
1323                                   last);
1324 }
1325 static void savageEmitChangedRegChunk (savageContextPtr imesa,
1326                                        GLuint first, GLuint last) {
1327     GLuint i;
1328     for (i = first - SAVAGE_FIRST_REG; i <= last - SAVAGE_FIRST_REG; ++i) {
1329         if (imesa->oldRegs.ui[i] != imesa->regs.ui[i]) {
1330             savageEmitContiguousRegs (imesa, first, last);
1331             break;
1332         }
1333     }
1334 }
1335 static void savageUpdateRegister_s4(savageContextPtr imesa)
1336 {
1337     /* In case the texture image was changed without changing the
1338      * texture address as well, we need to force emitting the texture
1339      * address in order to flush texture cashes. */
1340     if ((imesa->dirty & SAVAGE_UPLOAD_TEX0) &&
1341         imesa->oldRegs.s4.texAddr[0].ui == imesa->regs.s4.texAddr[0].ui)
1342         imesa->oldRegs.s4.texAddr[0].ui = 0xffffffff;
1343     if ((imesa->dirty & SAVAGE_UPLOAD_TEX1) &&
1344         imesa->oldRegs.s4.texAddr[1].ui == imesa->regs.s4.texAddr[1].ui)
1345         imesa->oldRegs.s4.texAddr[1].ui = 0xffffffff;
1346
1347     /* Fix up watermarks */
1348     if (imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites) {
1349         imesa->regs.s4.destTexWatermarks.ni.destWriteLow = 0;
1350         imesa->regs.s4.destTexWatermarks.ni.destFlush = 1;
1351     } else
1352         imesa->regs.s4.destTexWatermarks.ni.destWriteLow = S4_DWLO;
1353     if (imesa->regs.s4.drawLocalCtrl.ni.flushPdZbufWrites)
1354         imesa->regs.s4.zWatermarks.ni.wLow = 0;
1355     else
1356         imesa->regs.s4.zWatermarks.ni.wLow = S4_ZWLO;
1357
1358     savageEmitChangedRegs (imesa, 0x1e, 0x39);
1359
1360     imesa->dirty=0;
1361 }
1362 static void savageUpdateRegister_s3d(savageContextPtr imesa)
1363 {
1364     /* In case the texture image was changed without changing the
1365      * texture address as well, we need to force emitting the texture
1366      * address in order to flush texture cashes. */
1367     if ((imesa->dirty & SAVAGE_UPLOAD_TEX0) &&
1368         imesa->oldRegs.s3d.texAddr.ui == imesa->regs.s3d.texAddr.ui)
1369         imesa->oldRegs.s3d.texAddr.ui = 0xffffffff;
1370
1371     /* Fix up watermarks */
1372     if (imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites) {
1373         imesa->regs.s3d.destTexWatermarks.ni.destWriteLow = 0;
1374         imesa->regs.s3d.destTexWatermarks.ni.destFlush = 1;
1375     } else
1376         imesa->regs.s3d.destTexWatermarks.ni.destWriteLow = S3D_DWLO;
1377     if (imesa->regs.s3d.drawCtrl.ni.flushPdZbufWrites)
1378         imesa->regs.s3d.zWatermarks.ni.wLow = 0;
1379     else
1380         imesa->regs.s3d.zWatermarks.ni.wLow = S3D_ZWLO;
1381
1382
1383     /* the savage3d uses two contiguous ranges of BCI registers:
1384      * 0x18-0x1c and 0x20-0x38. Some texture registers need to be
1385      * emitted in one chunk or we get some funky rendering errors. */
1386     savageEmitChangedRegs (imesa, 0x18, 0x19);
1387     savageEmitChangedRegChunk (imesa, 0x1a, 0x1c);
1388     savageEmitChangedRegs (imesa, 0x20, 0x38);
1389
1390     imesa->dirty=0;
1391 }
1392
1393
1394 void savageEmitOldState( savageContextPtr imesa )
1395 {
1396     assert(imesa->cmdBuf.write == imesa->cmdBuf.base);
1397     if (imesa->savageScreen->chipset >= S3_SAVAGE4) {
1398         savageEmitOldRegs (imesa, 0x1e, 0x39, GL_TRUE);
1399     } else {
1400         savageEmitOldRegs (imesa, 0x18, 0x1c, GL_TRUE);
1401         savageEmitOldRegs (imesa, 0x20, 0x38, GL_FALSE);
1402     }
1403 }
1404
1405
1406 /* Push the state into the sarea and/or texture memory.
1407  */
1408 void savageEmitChangedState( savageContextPtr imesa )
1409 {
1410     if (SAVAGE_DEBUG & DEBUG_VERBOSE_API)
1411         savageDDPrintDirty( "\n\n\nsavageEmitHwStateLocked", imesa->dirty );
1412
1413     if (imesa->dirty)
1414     {
1415         if (SAVAGE_DEBUG & DEBUG_VERBOSE_MSG)
1416             fprintf (stderr, "... emitting state\n");
1417         if (imesa->savageScreen->chipset >= S3_SAVAGE4)
1418             savageUpdateRegister_s4(imesa);
1419         else
1420             savageUpdateRegister_s3d(imesa);
1421      }
1422
1423     imesa->dirty = 0;
1424 }
1425
1426
1427 static void savageDDInitState_s4( savageContextPtr imesa )
1428 {
1429 #if 1
1430     imesa->regs.s4.destCtrl.ui          = 1<<7;
1431 #endif
1432
1433     imesa->regs.s4.zBufCtrl.ni.zCmpFunc = CF_Less;
1434     imesa->regs.s4.zBufCtrl.ni.wToZEn               = GL_TRUE;
1435     if (imesa->float_depth) {
1436         imesa->regs.s4.zBufCtrl.ni.zExpOffset =
1437             imesa->savageScreen->zpp == 2 ? 16 : 32;
1438         imesa->regs.s4.zBufCtrl.ni.floatZEn = GL_TRUE;
1439     } else {
1440         imesa->regs.s4.zBufCtrl.ni.zExpOffset = 0;
1441         imesa->regs.s4.zBufCtrl.ni.floatZEn = GL_FALSE;
1442     }
1443     imesa->regs.s4.texBlendCtrl[0].ui            = TBC_NoTexMap;
1444     imesa->regs.s4.texBlendCtrl[1].ui            = TBC_NoTexMap1;
1445     imesa->regs.s4.drawCtrl0.ui         = 0;
1446 #if 0
1447     imesa->regs.s4.drawCtrl1.ni.xyOffsetEn = 1;
1448 #endif
1449
1450     /* Set DestTexWatermarks_31,30 to 01 always.
1451      *Has no effect if dest. flush is disabled.
1452      */
1453 #if 0
1454     imesa->regs.s4.zWatermarks.ui       = 0x12000C04;
1455     imesa->regs.s4.destTexWatermarks.ui = 0x40200400;
1456 #else
1457     /*imesa->regs.s4.zWatermarks.ui       = 0x16001808;*/
1458     imesa->regs.s4.zWatermarks.ni.rLow  = S4_ZRLO;
1459     imesa->regs.s4.zWatermarks.ni.rHigh = S4_ZRHI;
1460     imesa->regs.s4.zWatermarks.ni.wLow  = S4_ZWLO;
1461     imesa->regs.s4.zWatermarks.ni.wHigh = S4_ZWHI;
1462     /*imesa->regs.s4.destTexWatermarks.ui = 0x4f000000;*/
1463     imesa->regs.s4.destTexWatermarks.ni.destReadLow   = S4_DRLO;
1464     imesa->regs.s4.destTexWatermarks.ni.destReadHigh  = S4_DRHI;
1465     imesa->regs.s4.destTexWatermarks.ni.destWriteLow  = S4_DWLO;
1466     imesa->regs.s4.destTexWatermarks.ni.destWriteHigh = S4_DWHI;
1467     imesa->regs.s4.destTexWatermarks.ni.texRead       = S4_TR;
1468     imesa->regs.s4.destTexWatermarks.ni.destFlush     = 1;
1469 #endif
1470     imesa->regs.s4.drawCtrl0.ni.dPerfAccelEn = GL_TRUE;
1471
1472     /* clrCmpAlphaBlendCtrl is needed to get alphatest and
1473      * alpha blending working properly
1474      */
1475
1476     imesa->regs.s4.texCtrl[0].ni.dBias                 = 0x08;
1477     imesa->regs.s4.texCtrl[1].ni.dBias                 = 0x08;
1478     imesa->regs.s4.texCtrl[0].ni.texXprEn              = GL_TRUE;
1479     imesa->regs.s4.texCtrl[1].ni.texXprEn              = GL_TRUE;
1480     imesa->regs.s4.texCtrl[0].ni.dMax                  = 0x0f;
1481     imesa->regs.s4.texCtrl[1].ni.dMax                  = 0x0f;
1482     /* programm a valid tex address, in case texture state is emitted
1483      * in wrong order. */
1484     if (imesa->lastTexHeap == 2 && imesa->savageScreen->textureSize[1]) {
1485         /* AGP textures available */
1486         imesa->regs.s4.texAddr[0].ui = imesa->savageScreen->textureOffset[1]|3;
1487         imesa->regs.s4.texAddr[1].ui = imesa->savageScreen->textureOffset[1]|3;
1488     } else {
1489         /* no AGP textures available, use local */
1490         imesa->regs.s4.texAddr[0].ui = imesa->savageScreen->textureOffset[0]|2;
1491         imesa->regs.s4.texAddr[1].ui = imesa->savageScreen->textureOffset[0]|2;
1492     }
1493     imesa->regs.s4.drawLocalCtrl.ni.drawUpdateEn     = GL_TRUE;
1494     imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode    = SAM_One;
1495     imesa->regs.s4.drawLocalCtrl.ni.wrZafterAlphaTst = GL_FALSE;
1496     imesa->regs.s4.drawLocalCtrl.ni.flushPdZbufWrites= GL_TRUE;
1497     imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites= GL_TRUE;
1498
1499     imesa->regs.s4.drawLocalCtrl.ni.zUpdateEn= GL_TRUE;
1500     imesa->regs.s4.drawCtrl1.ni.ditherEn = (
1501         driQueryOptioni(&imesa->optionCache, "color_reduction") ==
1502         DRI_CONF_COLOR_REDUCTION_DITHER) ? GL_TRUE : GL_FALSE;
1503     imesa->regs.s4.drawCtrl1.ni.cullMode             = BCM_None;
1504
1505     imesa->regs.s4.zBufCtrl.ni.stencilRefVal      = 0x00;
1506
1507     imesa->regs.s4.stencilCtrl.ni.stencilEn       = GL_FALSE;
1508     imesa->regs.s4.stencilCtrl.ni.cmpFunc         = CF_Always;
1509     imesa->regs.s4.stencilCtrl.ni.failOp          = STENCIL_Keep;
1510     imesa->regs.s4.stencilCtrl.ni.passZfailOp     = STENCIL_Keep;
1511     imesa->regs.s4.stencilCtrl.ni.passZpassOp     = STENCIL_Keep;
1512     imesa->regs.s4.stencilCtrl.ni.writeMask       = 0xff;
1513     imesa->regs.s4.stencilCtrl.ni.readMask        = 0xff;
1514
1515     imesa->LcsCullMode=BCM_None;
1516     imesa->regs.s4.texDescr.ni.palSize               = TPS_256;
1517
1518     /* clear the local registers in the global reg mask */
1519     imesa->globalRegMask.s4.drawLocalCtrl.ui   = 0;
1520     imesa->globalRegMask.s4.texPalAddr.ui      = 0;
1521     imesa->globalRegMask.s4.texCtrl[0].ui      = 0;
1522     imesa->globalRegMask.s4.texCtrl[1].ui      = 0;
1523     imesa->globalRegMask.s4.texAddr[0].ui      = 0;
1524     imesa->globalRegMask.s4.texAddr[1].ui      = 0;
1525     imesa->globalRegMask.s4.texBlendCtrl[0].ui = 0;
1526     imesa->globalRegMask.s4.texBlendCtrl[1].ui = 0;
1527     imesa->globalRegMask.s4.texXprClr.ui       = 0;
1528     imesa->globalRegMask.s4.texDescr.ui        = 0;
1529 }
1530 static void savageDDInitState_s3d( savageContextPtr imesa )
1531 {
1532 #if 1
1533     imesa->regs.s3d.destCtrl.ui           = 1<<7;
1534 #endif
1535
1536     imesa->regs.s3d.zBufCtrl.ni.zCmpFunc  = CF_Less;
1537 #if 0
1538     imesa->regs.s3d.drawCtrl.ni.xyOffsetEn = 1;
1539 #endif
1540
1541     /* Set DestTexWatermarks_31,30 to 01 always.
1542      *Has no effect if dest. flush is disabled.
1543      */
1544 #if 0
1545     imesa->regs.s3d.zWatermarks.ui       = 0x12000C04;
1546     imesa->regs.s3d.destTexWatermarks.ui = 0x40200400;
1547 #else
1548     /*imesa->regs.s3d.zWatermarks.ui       = 0x16001808;*/
1549     imesa->regs.s3d.zWatermarks.ni.rLow  = S3D_ZRLO;
1550     imesa->regs.s3d.zWatermarks.ni.rHigh = S3D_ZRHI;
1551     imesa->regs.s3d.zWatermarks.ni.wLow  = S3D_ZWLO;
1552     imesa->regs.s3d.zWatermarks.ni.wHigh = S3D_ZWHI;
1553     /*imesa->regs.s3d.destTexWatermarks.ui = 0x4f000000;*/
1554     imesa->regs.s3d.destTexWatermarks.ni.destReadLow   = S3D_DRLO;
1555     imesa->regs.s3d.destTexWatermarks.ni.destReadHigh  = S3D_DRHI;
1556     imesa->regs.s3d.destTexWatermarks.ni.destWriteLow  = S3D_DWLO;
1557     imesa->regs.s3d.destTexWatermarks.ni.destWriteHigh = S3D_DWHI;
1558     imesa->regs.s3d.destTexWatermarks.ni.texRead       = S3D_TR;
1559     imesa->regs.s3d.destTexWatermarks.ni.destFlush     = 1;
1560 #endif
1561
1562     imesa->regs.s3d.texCtrl.ni.dBias          = 0x08;
1563     imesa->regs.s3d.texCtrl.ni.texXprEn       = GL_TRUE;
1564     /* texXprEn is needed to get alphatest and alpha blending working
1565      * properly. However, this makes texels with color texXprClr
1566      * completely transparent in some texture environment modes. I
1567      * couldn't find a way to disable this. So choose an arbitrary and
1568      * improbable color. (0 is a bad choice, makes all black texels
1569      * transparent.) */
1570     imesa->regs.s3d.texXprClr.ui              = 0x26ae26ae;
1571     /* programm a valid tex address, in case texture state is emitted
1572      * in wrong order. */
1573     if (imesa->lastTexHeap == 2 && imesa->savageScreen->textureSize[1]) {
1574         /* AGP textures available */
1575         imesa->regs.s3d.texAddr.ui = imesa->savageScreen->textureOffset[1]|3;
1576     } else {
1577         /* no AGP textures available, use local */
1578         imesa->regs.s3d.texAddr.ui = imesa->savageScreen->textureOffset[0]|2;
1579     }
1580
1581     imesa->regs.s3d.zBufCtrl.ni.drawUpdateEn     = GL_TRUE;
1582     imesa->regs.s3d.zBufCtrl.ni.wrZafterAlphaTst = GL_FALSE;
1583     imesa->regs.s3d.zBufCtrl.ni.zUpdateEn        = GL_TRUE;
1584
1585     imesa->regs.s3d.drawCtrl.ni.srcAlphaMode      = SAM_One;
1586     imesa->regs.s3d.drawCtrl.ni.flushPdZbufWrites = GL_TRUE;
1587     imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE;
1588
1589     imesa->regs.s3d.drawCtrl.ni.ditherEn =  (
1590         driQueryOptioni(&imesa->optionCache, "color_reduction") ==
1591         DRI_CONF_COLOR_REDUCTION_DITHER) ? GL_TRUE : GL_FALSE;
1592     imesa->regs.s3d.drawCtrl.ni.cullMode          = BCM_None;
1593
1594     imesa->LcsCullMode = BCM_None;
1595     imesa->regs.s3d.texDescr.ni.palSize          = TPS_256;
1596
1597     /* clear the local registers in the global reg mask */
1598     imesa->globalRegMask.s3d.texPalAddr.ui = 0;
1599     imesa->globalRegMask.s3d.texXprClr.ui  = 0;
1600     imesa->globalRegMask.s3d.texAddr.ui    = 0;
1601     imesa->globalRegMask.s3d.texDescr.ui   = 0;
1602     imesa->globalRegMask.s3d.texCtrl.ui    = 0;
1603
1604     imesa->globalRegMask.s3d.fogCtrl.ui = 0;
1605
1606     /* drawCtrl is local with some exceptions */
1607     imesa->globalRegMask.s3d.drawCtrl.ui = 0;
1608     imesa->globalRegMask.s3d.drawCtrl.ni.cullMode = 0x3;
1609     imesa->globalRegMask.s3d.drawCtrl.ni.alphaTestCmpFunc = 0x7;
1610     imesa->globalRegMask.s3d.drawCtrl.ni.alphaTestEn = 0x1;
1611     imesa->globalRegMask.s3d.drawCtrl.ni.alphaRefVal = 0xff;
1612
1613     /* zBufCtrl is local with some exceptions */
1614     imesa->globalRegMask.s3d.zBufCtrl.ui = 0;
1615     imesa->globalRegMask.s3d.zBufCtrl.ni.zCmpFunc = 0x7;
1616     imesa->globalRegMask.s3d.zBufCtrl.ni.zBufEn = 0x1;
1617 }
1618 void savageDDInitState( savageContextPtr imesa ) {
1619     memset (imesa->regs.ui, 0, SAVAGE_NR_REGS*sizeof(uint32_t));
1620     memset (imesa->globalRegMask.ui, 0xff, SAVAGE_NR_REGS*sizeof(uint32_t));
1621     if (imesa->savageScreen->chipset >= S3_SAVAGE4)
1622         savageDDInitState_s4 (imesa);
1623     else
1624         savageDDInitState_s3d (imesa);
1625
1626     /*fprintf(stderr,"DBflag:%d\n",imesa->glCtx->Visual->DBflag);*/
1627     /* zbufoffset and destctrl have the same position and layout on
1628      * savage4 and savage3d. */
1629     if (imesa->glCtx->Visual.doubleBufferMode) {
1630         imesa->IsDouble = GL_TRUE;
1631         imesa->toggle = TARGET_BACK;
1632         imesa->regs.s4.destCtrl.ni.offset =
1633             imesa->savageScreen->backOffset>>11;
1634     } else {
1635         imesa->IsDouble = GL_FALSE;
1636         imesa->toggle = TARGET_FRONT;
1637         imesa->regs.s4.destCtrl.ni.offset =
1638             imesa->savageScreen->frontOffset>>11;
1639     }
1640     if(imesa->savageScreen->cpp == 2) {
1641         imesa->regs.s4.destCtrl.ni.dstPixFmt = 0;
1642         imesa->regs.s4.destCtrl.ni.dstWidthInTile =
1643             (imesa->savageScreen->width+63)>>6;
1644     } else {
1645         imesa->regs.s4.destCtrl.ni.dstPixFmt = 1;
1646         imesa->regs.s4.destCtrl.ni.dstWidthInTile =
1647             (imesa->savageScreen->width+31)>>5;
1648     }
1649     imesa->NotFirstFrame = GL_FALSE;
1650
1651     imesa->regs.s4.zBufOffset.ni.offset=imesa->savageScreen->depthOffset>>11;
1652     if(imesa->savageScreen->zpp == 2) {
1653         imesa->regs.s4.zBufOffset.ni.zBufWidthInTiles = 
1654             (imesa->savageScreen->width+63)>>6;
1655         imesa->regs.s4.zBufOffset.ni.zDepthSelect = 0;
1656     } else {   
1657         imesa->regs.s4.zBufOffset.ni.zBufWidthInTiles = 
1658             (imesa->savageScreen->width+31)>>5;
1659         imesa->regs.s4.zBufOffset.ni.zDepthSelect = 1;      
1660     }
1661
1662     memcpy (imesa->oldRegs.ui, imesa->regs.ui, SAVAGE_NR_REGS*sizeof(uint32_t));
1663
1664     /* Emit the initial state to the (empty) command buffer. */
1665     assert (imesa->cmdBuf.write == imesa->cmdBuf.base);
1666     savageEmitOldState(imesa);
1667     imesa->cmdBuf.start = imesa->cmdBuf.write;
1668 }
1669
1670
1671 #define INTERESTED (~(NEW_MODELVIEW|NEW_PROJECTION|\
1672                       NEW_TEXTURE_MATRIX|\
1673                       NEW_USER_CLIP|NEW_CLIENT_STATE))
1674
1675 static void savageDDInvalidateState( struct gl_context *ctx, GLuint new_state )
1676 {
1677    _swrast_InvalidateState( ctx, new_state );
1678    _swsetup_InvalidateState( ctx, new_state );
1679    _vbo_InvalidateState( ctx, new_state );
1680    _tnl_InvalidateState( ctx, new_state );
1681    SAVAGE_CONTEXT(ctx)->new_gl_state |= new_state;
1682 }
1683
1684
1685 void savageDDInitStateFuncs(struct gl_context *ctx)
1686 {
1687     ctx->Driver.UpdateState = savageDDInvalidateState;
1688     ctx->Driver.BlendEquationSeparate = savageDDBlendEquationSeparate;
1689     ctx->Driver.Fogfv = savageDDFogfv;
1690     ctx->Driver.Scissor = savageDDScissor;
1691 #if HW_CULL
1692     ctx->Driver.CullFace = savageDDCullFaceFrontFace;
1693     ctx->Driver.FrontFace = savageDDCullFaceFrontFace;
1694 #else
1695     ctx->Driver.CullFace = 0;
1696     ctx->Driver.FrontFace = 0;
1697 #endif /* end #if HW_CULL */
1698     ctx->Driver.DrawBuffer = savageDDDrawBuffer;
1699     ctx->Driver.ReadBuffer = savageDDReadBuffer;
1700     ctx->Driver.ClearColor = savageDDClearColor;
1701
1702     ctx->Driver.DepthRange = savageDepthRange;
1703     ctx->Driver.Viewport = savageViewport;
1704     ctx->Driver.RenderMode = savageRenderMode;
1705
1706     if (SAVAGE_CONTEXT( ctx )->savageScreen->chipset >= S3_SAVAGE4) {
1707         ctx->Driver.Enable = savageDDEnable_s4;
1708         ctx->Driver.AlphaFunc = savageDDAlphaFunc_s4;
1709         ctx->Driver.DepthFunc = savageDDDepthFunc_s4;
1710         ctx->Driver.DepthMask = savageDDDepthMask_s4;
1711         ctx->Driver.BlendFuncSeparate = savageDDBlendFuncSeparate_s4;
1712         ctx->Driver.ColorMask = savageDDColorMask_s4;
1713         ctx->Driver.ShadeModel = savageDDShadeModel_s4;
1714         ctx->Driver.LightModelfv = savageDDLightModelfv_s4;
1715         ctx->Driver.StencilFuncSeparate = savageDDStencilFuncSeparate;
1716         ctx->Driver.StencilMaskSeparate = savageDDStencilMaskSeparate;
1717         ctx->Driver.StencilOpSeparate = savageDDStencilOpSeparate;
1718     } else {
1719         ctx->Driver.Enable = savageDDEnable_s3d;
1720         ctx->Driver.AlphaFunc = savageDDAlphaFunc_s3d;
1721         ctx->Driver.DepthFunc = savageDDDepthFunc_s3d;
1722         ctx->Driver.DepthMask = savageDDDepthMask_s3d;
1723         ctx->Driver.BlendFuncSeparate = savageDDBlendFuncSeparate_s3d;
1724         ctx->Driver.ColorMask = savageDDColorMask_s3d;
1725         ctx->Driver.ShadeModel = savageDDShadeModel_s3d;
1726         ctx->Driver.LightModelfv = savageDDLightModelfv_s3d;
1727         ctx->Driver.StencilFuncSeparate = NULL;
1728         ctx->Driver.StencilMaskSeparate = NULL;
1729         ctx->Driver.StencilOpSeparate = NULL;
1730     }
1731 }