2 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
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:
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
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.
28 #include "main/mtypes.h"
29 #include "main/enums.h"
30 #include "main/macros.h"
33 #include "main/state.h"
36 #include "savagecontext.h"
38 #include "savagestate.h"
39 #include "savagetex.h"
40 #include "savagetris.h"
41 #include "savageioctl.h"
42 #include "savage_bci.h"
44 #include "swrast/swrast.h"
47 #include "swrast_setup/swrast_setup.h"
51 /* Savage4, ProSavage[DDR], SuperSavage watermarks */
64 /* Savage3D/MX/IX watermarks */
77 static void savageBlendFunc_s4(struct gl_context *);
78 static void savageBlendFunc_s3d(struct gl_context *);
80 static INLINE GLuint savagePackColor(GLuint format,
86 return SAVAGEPACKCOLOR8888(r,g,b,a);
88 return SAVAGEPACKCOLOR565(r,g,b);
96 static void savageDDAlphaFunc_s4(struct gl_context *ctx, GLenum func, GLfloat ref)
98 savageBlendFunc_s4(ctx);
100 static void savageDDAlphaFunc_s3d(struct gl_context *ctx, GLenum func, GLfloat ref)
102 savageBlendFunc_s3d(ctx);
105 static void savageDDBlendEquationSeparate(struct gl_context *ctx,
106 GLenum modeRGB, GLenum modeA)
108 assert( modeRGB == modeA );
110 /* BlendEquation sets ColorLogicOpEnabled in an unexpected
113 FALLBACK( ctx, SAVAGE_FALLBACK_LOGICOP,
114 (ctx->Color.ColorLogicOpEnabled &&
115 ctx->Color.LogicOp != GL_COPY));
117 /* Can only do blend addition, not min, max, subtract, etc. */
118 FALLBACK( ctx, SAVAGE_FALLBACK_BLEND_EQ,
119 modeRGB != GL_FUNC_ADD);
123 static void savageBlendFunc_s4(struct gl_context *ctx)
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;
130 /* set up draw control register (including blending, alpha
131 * test, and shading model)
134 imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites = GL_FALSE;
139 if(ctx->Color.BlendEnabled){
140 switch (ctx->Color.Blend[0].DstRGB)
143 imesa->regs.s4.drawLocalCtrl.ni.dstAlphaMode = DAM_Zero;
147 imesa->regs.s4.drawLocalCtrl.ni.dstAlphaMode = DAM_One;
148 imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites = GL_TRUE;
152 imesa->regs.s4.drawLocalCtrl.ni.dstAlphaMode = DAM_SrcClr;
153 imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites = GL_TRUE;
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;
162 imesa->regs.s4.drawLocalCtrl.ni.dstAlphaMode = DAM_SrcAlpha;
163 imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites = GL_TRUE;
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;
172 if (imesa->glCtx->Visual.alphaBits == 0)
174 imesa->regs.s4.drawLocalCtrl.ni.dstAlphaMode = DAM_One;
178 imesa->regs.s4.drawLocalCtrl.ni.dstAlphaMode= DAM_DstAlpha;
180 imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites = GL_TRUE;
183 case GL_ONE_MINUS_DST_ALPHA:
184 if (imesa->glCtx->Visual.alphaBits == 0)
186 imesa->regs.s4.drawLocalCtrl.ni.dstAlphaMode = DAM_Zero;
190 imesa->regs.s4.drawLocalCtrl.ni.dstAlphaMode=DAM_1DstAlpha;
191 imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites= GL_TRUE;
196 switch (ctx->Color.Blend[0].SrcRGB)
199 imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode = SAM_Zero;
203 imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode = SAM_One;
207 imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode = SAM_DstClr;
208 imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites = GL_TRUE;
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;
217 imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode = SAM_SrcAlpha;
220 case GL_ONE_MINUS_SRC_ALPHA:
221 imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode = SAM_1SrcAlpha;
225 if (imesa->glCtx->Visual.alphaBits == 0)
227 imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode = SAM_One;
231 imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode= SAM_DstAlpha;
232 imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites= GL_TRUE;
236 case GL_ONE_MINUS_DST_ALPHA:
237 if (imesa->glCtx->Visual.alphaBits == 0)
239 imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode = SAM_Zero;
243 imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode=SAM_1DstAlpha;
244 imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites= GL_TRUE;
251 imesa->regs.s4.drawLocalCtrl.ni.dstAlphaMode = DAM_Zero;
252 imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode = SAM_One;
257 if(ctx->Color.AlphaEnabled)
262 CLAMPED_FLOAT_TO_UBYTE(alphaRef,ctx->Color.AlphaRef);
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;
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;
282 imesa->regs.s4.drawCtrl1.ni.alphaTestEn = GL_FALSE;
285 /* Set/Reset Z-after-alpha*/
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;*/
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;
298 static void savageBlendFunc_s3d(struct gl_context *ctx)
300 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
301 uint32_t drawCtrl = imesa->regs.s3d.drawCtrl.ui;
302 uint32_t zBufCtrl = imesa->regs.s3d.zBufCtrl.ui;
304 /* set up draw control register (including blending, alpha
305 * test, dithering, and shading model)
308 imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = 0;
313 if(ctx->Color.BlendEnabled){
314 switch (ctx->Color.Blend[0].DstRGB)
317 imesa->regs.s3d.drawCtrl.ni.dstAlphaMode = DAM_Zero;
321 imesa->regs.s3d.drawCtrl.ni.dstAlphaMode = DAM_One;
322 imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE;
326 imesa->regs.s3d.drawCtrl.ni.dstAlphaMode = DAM_SrcClr;
327 imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE;
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;
336 imesa->regs.s3d.drawCtrl.ni.dstAlphaMode = DAM_SrcAlpha;
337 imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE;
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;
346 if (imesa->glCtx->Visual.alphaBits == 0)
348 imesa->regs.s3d.drawCtrl.ni.dstAlphaMode = DAM_One;
352 imesa->regs.s3d.drawCtrl.ni.dstAlphaMode = DAM_DstAlpha;
354 imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE;
357 case GL_ONE_MINUS_DST_ALPHA:
358 if (imesa->glCtx->Visual.alphaBits == 0)
360 imesa->regs.s3d.drawCtrl.ni.dstAlphaMode = DAM_Zero;
364 imesa->regs.s3d.drawCtrl.ni.dstAlphaMode = DAM_1DstAlpha;
365 imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE;
370 switch (ctx->Color.Blend[0].SrcRGB)
373 imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_Zero;
377 imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_One;
381 imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_DstClr;
382 imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE;
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;
391 imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_SrcAlpha;
394 case GL_ONE_MINUS_SRC_ALPHA:
395 imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_1SrcAlpha;
399 if (imesa->glCtx->Visual.alphaBits == 0)
401 imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_One;
405 imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_DstAlpha;
406 imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE;
410 case GL_ONE_MINUS_DST_ALPHA:
411 if (imesa->glCtx->Visual.alphaBits == 0)
413 imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_Zero;
417 imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_1DstAlpha;
418 imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE;
425 imesa->regs.s3d.drawCtrl.ni.dstAlphaMode = DAM_Zero;
426 imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_One;
431 if(ctx->Color.AlphaEnabled)
436 CLAMPED_FLOAT_TO_UBYTE(alphaRef,ctx->Color.AlphaRef);
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;
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;
456 imesa->regs.s3d.drawCtrl.ni.alphaTestEn = GL_FALSE;
459 /* Set/Reset Z-after-alpha*/
461 imesa->regs.s3d.zBufCtrl.ni.wrZafterAlphaTst =
462 imesa->regs.s3d.drawCtrl.ni.alphaTestEn;
464 if (drawCtrl != imesa->regs.s3d.drawCtrl.ui ||
465 zBufCtrl != imesa->regs.s3d.zBufCtrl.ui)
466 imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
469 static void savageDDBlendFuncSeparate_s4( struct gl_context *ctx, GLenum sfactorRGB,
470 GLenum dfactorRGB, GLenum sfactorA,
473 assert (dfactorRGB == dfactorA && sfactorRGB == sfactorA);
474 savageBlendFunc_s4( ctx );
476 static void savageDDBlendFuncSeparate_s3d( struct gl_context *ctx, GLenum sfactorRGB,
477 GLenum dfactorRGB, GLenum sfactorA,
480 assert (dfactorRGB == dfactorA && sfactorRGB == sfactorA);
481 savageBlendFunc_s3d( ctx );
486 static void savageDDDepthFunc_s4(struct gl_context *ctx, GLenum func)
488 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
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 */
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)
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;
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;
518 else if (imesa->glCtx->Stencil._Enabled && imesa->hw_stencil)
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;
529 if (imesa->regs.s4.drawLocalCtrl.ni.drawUpdateEn == GL_FALSE)
531 imesa->regs.s4.zBufCtrl.ni.zCmpFunc = CF_Always;
532 imesa->regs.s4.zBufCtrl.ni.zBufEn = GL_TRUE;
536 /* DRAWUPDATE_REQUIRES_Z_ENABLED*/
538 imesa->regs.s4.zBufCtrl.ni.zBufEn = GL_FALSE;
540 imesa->regs.s4.drawLocalCtrl.ni.zUpdateEn = GL_FALSE;
541 imesa->regs.s4.drawLocalCtrl.ni.flushPdZbufWrites = GL_FALSE;
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;
550 static void savageDDDepthFunc_s3d(struct gl_context *ctx, GLenum func)
552 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
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 */
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)
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;
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;
579 imesa->regs.s3d.drawCtrl.ni.flushPdZbufWrites = GL_TRUE;
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;
589 /* DRAWUPDATE_REQUIRES_Z_ENABLED*/
591 imesa->regs.s3d.zBufCtrl.ni.zBufEn = GL_FALSE;
593 imesa->regs.s3d.zBufCtrl.ni.zUpdateEn = GL_FALSE;
594 imesa->regs.s3d.drawCtrl.ni.flushPdZbufWrites = GL_FALSE;
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;
604 static void savageDDDepthMask_s4(struct gl_context *ctx, GLboolean flag)
606 savageDDDepthFunc_s4(ctx,ctx->Depth.Func);
608 static void savageDDDepthMask_s3d(struct gl_context *ctx, GLboolean flag)
610 savageDDDepthFunc_s3d(ctx,ctx->Depth.Func);
616 /* =============================================================
621 static void savageDDScissor( struct gl_context *ctx, GLint x, GLint y,
622 GLsizei w, GLsizei h )
624 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
626 /* Emit buffered commands with old scissor state. */
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;
639 static void savageDDDrawBuffer(struct gl_context *ctx, GLenum mode )
641 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
642 uint32_t destCtrl = imesa->regs.s4.destCtrl.ui;
644 if (ctx->DrawBuffer->_NumColorDrawBuffers != 1) {
645 FALLBACK( ctx, SAVAGE_FALLBACK_DRAW_BUFFER, GL_TRUE );
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;
654 case BUFFER_BACK_LEFT:
655 imesa->IsDouble = GL_TRUE;
656 imesa->regs.s4.destCtrl.ni.offset = imesa->savageScreen->backOffset>>11;
659 FALLBACK( ctx, SAVAGE_FALLBACK_DRAW_BUFFER, GL_TRUE );
663 imesa->NotFirstFrame = GL_FALSE;
664 savageXMesaSetClipRects(imesa);
665 FALLBACK(ctx, SAVAGE_FALLBACK_DRAW_BUFFER, GL_FALSE);
667 if (destCtrl != imesa->regs.s4.destCtrl.ui)
668 imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
671 static void savageDDReadBuffer(struct gl_context *ctx, GLenum mode )
673 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
677 static void savageDDSetColor(struct gl_context *ctx,
678 GLubyte r, GLubyte g,
679 GLubyte b, GLubyte a )
681 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
682 imesa->MonoColor = savagePackColor( imesa->savageScreen->frontFormat, r, g, b, a );
686 /* =============================================================
687 * Window position and viewport transformation
690 void savageCalcViewport( struct gl_context *ctx )
692 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
693 const GLfloat *v = ctx->Viewport._WindowMap.m;
694 GLfloat *m = imesa->hw_viewport;
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
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);
709 m[MAT_SZ] = - v[MAT_SZ] * imesa->depth_scale;
710 m[MAT_TZ] = 1.0 - v[MAT_TZ] * imesa->depth_scale;
713 imesa->SetupNewInputs = ~0;
716 static void savageViewport( struct gl_context *ctx,
718 GLsizei width, GLsizei height )
720 savageCalcViewport( ctx );
723 static void savageDepthRange( struct gl_context *ctx,
724 GLclampd nearval, GLclampd farval )
726 savageCalcViewport( ctx );
730 /* =============================================================
734 static void savageDDClearColor(struct gl_context *ctx,
735 const GLfloat color[4] )
737 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
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]);
744 imesa->ClearColor = savagePackColor( imesa->savageScreen->frontFormat,
745 c[0], c[1], c[2], c[3] );
748 /* Fallback to swrast for select and feedback.
750 static void savageRenderMode( struct gl_context *ctx, GLenum mode )
752 FALLBACK( ctx, SAVAGE_FALLBACK_RENDERMODE, (mode != GL_RENDER) );
758 /* =============================================================
759 * Culling - the savage isn't quite as clean here as the rest of
760 * its interfaces, but it's not bad.
762 static void savageDDCullFaceFrontFace(struct gl_context *ctx, GLenum unused)
764 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
765 GLuint cullMode=imesa->LcsCullMode;
766 switch (ctx->Polygon.CullFaceMode)
769 switch (ctx->Polygon.FrontFace)
781 switch (ctx->Polygon.FrontFace)
792 imesa->LcsCullMode = cullMode;
793 imesa->new_state |= SAVAGE_NEW_CULL;
795 #endif /* end #if HW_CULL */
797 static void savageUpdateCull( struct gl_context *ctx )
800 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
802 if (ctx->Polygon.CullFlag &&
803 imesa->raster_primitive >= GL_TRIANGLES &&
804 ctx->Polygon.CullFaceMode != GL_FRONT_AND_BACK)
805 cullMode = imesa->LcsCullMode;
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;
814 if (imesa->regs.s3d.drawCtrl.ni.cullMode != cullMode) {
815 imesa->regs.s3d.drawCtrl.ni.cullMode = cullMode;
816 imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
819 #endif /* end #if HW_CULL */
824 /* =============================================================
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.
833 static void savageDDColorMask_s4(struct gl_context *ctx,
834 GLboolean r, GLboolean g,
835 GLboolean b, GLboolean a )
837 savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
838 GLboolean passAny, passAll;
840 if (ctx->Visual.alphaBits) {
841 passAny = b || g || r || a;
842 passAll = r && g && b && a;
844 passAny = b || g || r;
845 passAll = r && g && b;
849 if (!imesa->regs.s4.drawLocalCtrl.ni.drawUpdateEn) {
850 imesa->regs.s4.drawLocalCtrl.ni.drawUpdateEn = GL_TRUE;
851 imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
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;
859 static void savageDDColorMask_s3d(struct gl_context *ctx,
860 GLboolean r, GLboolean g,
861 GLboolean b, GLboolean a )
863 if (ctx->Visual.alphaBits)
864 FALLBACK (ctx, SAVAGE_FALLBACK_COLORMASK, !(r && g && b && a));
866 FALLBACK (ctx, SAVAGE_FALLBACK_COLORMASK, !(r && g && b));
869 static void savageUpdateSpecular_s4(struct gl_context *ctx) {
870 savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
871 uint32_t drawLocalCtrl = imesa->regs.s4.drawLocalCtrl.ui;
873 if (_mesa_need_secondary_color(ctx)) {
874 imesa->regs.s4.drawLocalCtrl.ni.specShadeEn = GL_TRUE;
876 imesa->regs.s4.drawLocalCtrl.ni.specShadeEn = GL_FALSE;
879 if (drawLocalCtrl != imesa->regs.s4.drawLocalCtrl.ui)
880 imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
883 static void savageUpdateSpecular_s3d(struct gl_context *ctx) {
884 savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
885 uint32_t drawCtrl = imesa->regs.s3d.drawCtrl.ui;
887 if (_mesa_need_secondary_color(ctx)) {
888 imesa->regs.s3d.drawCtrl.ni.specShadeEn = GL_TRUE;
890 imesa->regs.s3d.drawCtrl.ni.specShadeEn = GL_FALSE;
893 if (drawCtrl != imesa->regs.s3d.drawCtrl.ui)
894 imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
897 static void savageDDLightModelfv_s4(struct gl_context *ctx, GLenum pname,
898 const GLfloat *param)
900 savageUpdateSpecular_s4 (ctx);
902 static void savageDDLightModelfv_s3d(struct gl_context *ctx, GLenum pname,
903 const GLfloat *param)
905 savageUpdateSpecular_s3d (ctx);
908 static void savageDDShadeModel_s4(struct gl_context *ctx, GLuint mod)
910 savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
911 uint32_t drawLocalCtrl = imesa->regs.s4.drawLocalCtrl.ui;
913 if (mod == GL_SMOOTH)
915 imesa->regs.s4.drawLocalCtrl.ni.flatShadeEn = GL_FALSE;
919 imesa->regs.s4.drawLocalCtrl.ni.flatShadeEn = GL_TRUE;
922 if (drawLocalCtrl != imesa->regs.s4.drawLocalCtrl.ui)
923 imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
925 static void savageDDShadeModel_s3d(struct gl_context *ctx, GLuint mod)
927 savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
928 uint32_t drawCtrl = imesa->regs.s3d.drawCtrl.ui;
930 if (mod == GL_SMOOTH)
932 imesa->regs.s3d.drawCtrl.ni.flatShadeEn = GL_FALSE;
936 imesa->regs.s3d.drawCtrl.ni.flatShadeEn = GL_TRUE;
939 if (drawCtrl != imesa->regs.s3d.drawCtrl.ui)
940 imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
944 /* =============================================================
946 * The fogCtrl register has the same position and the same layout
947 * on savage3d and savage4. No need for two separate functions.
950 static void savageDDFogfv(struct gl_context *ctx, GLenum pname, const GLfloat *param)
952 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
954 uint32_t fogCtrl = imesa->regs.s4.fogCtrl.ui;
956 /*if ((ctx->Fog.Enabled) &&(pname == GL_FOG_COLOR))*/
957 if (ctx->Fog.Enabled)
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;
964 imesa->regs.s4.fogCtrl.ni.fogMode = GL_TRUE;
965 imesa->regs.s4.fogCtrl.ni.fogClr = fogClr;
971 imesa->regs.s4.fogCtrl.ni.fogEn = 0;
972 imesa->regs.s4.fogCtrl.ni.fogMode = 0;
975 if (fogCtrl != imesa->regs.s4.fogCtrl.ui)
976 imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
981 savageDDStencilFuncSeparate(struct gl_context *ctx, GLenum face, GLenum func,
982 GLint ref, GLuint mask)
984 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
986 const uint32_t zBufCtrl = imesa->regs.s4.zBufCtrl.ui;
987 const uint32_t stencilCtrl = imesa->regs.s4.stencilCtrl.ui;
989 imesa->regs.s4.zBufCtrl.ni.stencilRefVal = ctx->Stencil.Ref[0] & 0xff;
990 imesa->regs.s4.stencilCtrl.ni.readMask = ctx->Stencil.ValueMask[0] & 0xff;
992 switch (ctx->Stencil.Function[0])
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;
1006 imesa->regs.s4.stencilCtrl.ni.cmpFunc = a;
1008 if (zBufCtrl != imesa->regs.s4.zBufCtrl.ui ||
1009 stencilCtrl != imesa->regs.s4.stencilCtrl.ui)
1010 imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
1014 savageDDStencilMaskSeparate(struct gl_context *ctx, GLenum face, GLuint mask)
1016 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
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;
1024 static unsigned get_stencil_op_value( GLenum op )
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;
1038 /* Should *never* get here. */
1039 return STENCIL_Keep;
1043 savageDDStencilOpSeparate(struct gl_context *ctx, GLenum face, GLenum fail,
1044 GLenum zfail, GLenum zpass)
1046 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
1047 const uint32_t stencilCtrl = imesa->regs.s4.stencilCtrl.ui;
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] );
1053 if (stencilCtrl != imesa->regs.s4.stencilCtrl.ui)
1054 imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
1058 /* =============================================================
1061 static void savageDDEnable_s4(struct gl_context *ctx, GLenum cap, GLboolean state)
1064 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
1067 /* we should consider the disable case*/
1068 savageBlendFunc_s4(ctx);
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
1075 savageBlendFunc_s4(ctx);
1076 case GL_COLOR_LOGIC_OP:
1078 * For some reason enable(GL_BLEND) affects ColorLogicOpEnabled.
1080 FALLBACK (ctx, SAVAGE_FALLBACK_LOGICOP,
1081 (ctx->Color.ColorLogicOpEnabled &&
1082 ctx->Color.LogicOp != GL_COPY));
1085 savageDDDepthFunc_s4(ctx,ctx->Depth.Func);
1087 case GL_SCISSOR_TEST:
1088 savageDDScissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
1089 ctx->Scissor.Width, ctx->Scissor.Height);
1091 case GL_STENCIL_TEST:
1092 if (!imesa->hw_stencil)
1093 FALLBACK (ctx, SAVAGE_FALLBACK_STENCIL, state);
1095 imesa->regs.s4.stencilCtrl.ni.stencilEn = state;
1096 if (ctx->Stencil._Enabled &&
1097 imesa->regs.s4.zBufCtrl.ni.zBufEn != GL_TRUE)
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;
1104 imesa->dirty |= SAVAGE_UPLOAD_GLOBAL | SAVAGE_UPLOAD_LOCAL;
1108 savageDDFogfv(ctx,0,0);
1114 savageDDCullFaceFrontFace(ctx,0);
1118 imesa->LcsCullMode = BCM_None;
1119 imesa->new_state |= SAVAGE_NEW_CULL;
1126 if ( ctx->Color.DitherFlag )
1128 imesa->regs.s4.drawCtrl1.ni.ditherEn=GL_TRUE;
1131 if (!ctx->Color.DitherFlag )
1133 imesa->regs.s4.drawCtrl1.ni.ditherEn=GL_FALSE;
1135 imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
1139 savageUpdateSpecular_s4 (ctx);
1143 imesa->new_state |= SAVAGE_NEW_TEXTURE;
1146 imesa->new_state |= SAVAGE_NEW_TEXTURE;
1152 static void savageDDEnable_s3d(struct gl_context *ctx, GLenum cap, GLboolean state)
1155 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
1158 /* we should consider the disable case*/
1159 savageBlendFunc_s3d(ctx);
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
1166 savageBlendFunc_s3d(ctx);
1167 case GL_COLOR_LOGIC_OP:
1169 * For some reason enable(GL_BLEND) affects ColorLogicOpEnabled.
1171 FALLBACK (ctx, SAVAGE_FALLBACK_LOGICOP,
1172 (ctx->Color.ColorLogicOpEnabled &&
1173 ctx->Color.LogicOp != GL_COPY));
1176 savageDDDepthFunc_s3d(ctx,ctx->Depth.Func);
1178 case GL_SCISSOR_TEST:
1179 savageDDScissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
1180 ctx->Scissor.Width, ctx->Scissor.Height);
1182 case GL_STENCIL_TEST:
1183 FALLBACK (ctx, SAVAGE_FALLBACK_STENCIL, state);
1186 savageDDFogfv(ctx,0,0);
1192 savageDDCullFaceFrontFace(ctx,0);
1196 imesa->LcsCullMode = BCM_None;
1197 imesa->new_state |= SAVAGE_NEW_CULL;
1204 if ( ctx->Color.DitherFlag )
1206 imesa->regs.s3d.drawCtrl.ni.ditherEn=GL_TRUE;
1209 if (!ctx->Color.DitherFlag )
1211 imesa->regs.s3d.drawCtrl.ni.ditherEn=GL_FALSE;
1213 imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
1217 savageUpdateSpecular_s3d (ctx);
1221 imesa->new_state |= SAVAGE_NEW_TEXTURE;
1224 imesa->new_state |= SAVAGE_NEW_TEXTURE;
1231 void savageDDUpdateHwState( struct gl_context *ctx )
1233 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
1235 if (imesa->new_state) {
1236 savageFlushVertices(imesa);
1237 if (imesa->new_state & SAVAGE_NEW_TEXTURE) {
1238 savageUpdateTextureState( ctx );
1240 if ((imesa->new_state & SAVAGE_NEW_CULL)) {
1241 savageUpdateCull(ctx);
1243 imesa->new_state = 0;
1248 static void savageDDPrintDirty( const char *msg, GLuint state )
1250 fprintf(stderr, "%s (0x%x): %s%s%s%s%s%s\n",
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, " : ""
1264 * Check if global registers were changed
1266 static GLboolean savageGlobalRegChanged (savageContextPtr imesa,
1267 GLuint first, GLuint last) {
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)
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);
1286 static void savageEmitContiguousRegs (savageContextPtr imesa,
1287 GLuint first, GLuint last) {
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);
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)
1314 if (firstChanged != SAVAGE_NR_REGS) {
1315 savageEmitContiguousRegs (imesa, firstChanged+SAVAGE_FIRST_REG,
1316 i-1+SAVAGE_FIRST_REG);
1317 firstChanged = SAVAGE_NR_REGS;
1321 if (firstChanged != SAVAGE_NR_REGS)
1322 savageEmitContiguousRegs (imesa, firstChanged+SAVAGE_FIRST_REG,
1325 static void savageEmitChangedRegChunk (savageContextPtr imesa,
1326 GLuint first, GLuint last) {
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);
1335 static void savageUpdateRegister_s4(savageContextPtr imesa)
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;
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;
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;
1356 imesa->regs.s4.zWatermarks.ni.wLow = S4_ZWLO;
1358 savageEmitChangedRegs (imesa, 0x1e, 0x39);
1362 static void savageUpdateRegister_s3d(savageContextPtr imesa)
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;
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;
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;
1380 imesa->regs.s3d.zWatermarks.ni.wLow = S3D_ZWLO;
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);
1394 void savageEmitOldState( savageContextPtr imesa )
1396 assert(imesa->cmdBuf.write == imesa->cmdBuf.base);
1397 if (imesa->savageScreen->chipset >= S3_SAVAGE4) {
1398 savageEmitOldRegs (imesa, 0x1e, 0x39, GL_TRUE);
1400 savageEmitOldRegs (imesa, 0x18, 0x1c, GL_TRUE);
1401 savageEmitOldRegs (imesa, 0x20, 0x38, GL_FALSE);
1406 /* Push the state into the sarea and/or texture memory.
1408 void savageEmitChangedState( savageContextPtr imesa )
1410 if (SAVAGE_DEBUG & DEBUG_VERBOSE_API)
1411 savageDDPrintDirty( "\n\n\nsavageEmitHwStateLocked", imesa->dirty );
1415 if (SAVAGE_DEBUG & DEBUG_VERBOSE_MSG)
1416 fprintf (stderr, "... emitting state\n");
1417 if (imesa->savageScreen->chipset >= S3_SAVAGE4)
1418 savageUpdateRegister_s4(imesa);
1420 savageUpdateRegister_s3d(imesa);
1427 static void savageDDInitState_s4( savageContextPtr imesa )
1430 imesa->regs.s4.destCtrl.ui = 1<<7;
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;
1440 imesa->regs.s4.zBufCtrl.ni.zExpOffset = 0;
1441 imesa->regs.s4.zBufCtrl.ni.floatZEn = GL_FALSE;
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;
1447 imesa->regs.s4.drawCtrl1.ni.xyOffsetEn = 1;
1450 /* Set DestTexWatermarks_31,30 to 01 always.
1451 *Has no effect if dest. flush is disabled.
1454 imesa->regs.s4.zWatermarks.ui = 0x12000C04;
1455 imesa->regs.s4.destTexWatermarks.ui = 0x40200400;
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;
1470 imesa->regs.s4.drawCtrl0.ni.dPerfAccelEn = GL_TRUE;
1472 /* clrCmpAlphaBlendCtrl is needed to get alphatest and
1473 * alpha blending working properly
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;
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;
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;
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;
1505 imesa->regs.s4.zBufCtrl.ni.stencilRefVal = 0x00;
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;
1515 imesa->LcsCullMode=BCM_None;
1516 imesa->regs.s4.texDescr.ni.palSize = TPS_256;
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;
1530 static void savageDDInitState_s3d( savageContextPtr imesa )
1533 imesa->regs.s3d.destCtrl.ui = 1<<7;
1536 imesa->regs.s3d.zBufCtrl.ni.zCmpFunc = CF_Less;
1538 imesa->regs.s3d.drawCtrl.ni.xyOffsetEn = 1;
1541 /* Set DestTexWatermarks_31,30 to 01 always.
1542 *Has no effect if dest. flush is disabled.
1545 imesa->regs.s3d.zWatermarks.ui = 0x12000C04;
1546 imesa->regs.s3d.destTexWatermarks.ui = 0x40200400;
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;
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
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;
1577 /* no AGP textures available, use local */
1578 imesa->regs.s3d.texAddr.ui = imesa->savageScreen->textureOffset[0]|2;
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;
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;
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;
1594 imesa->LcsCullMode = BCM_None;
1595 imesa->regs.s3d.texDescr.ni.palSize = TPS_256;
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;
1604 imesa->globalRegMask.s3d.fogCtrl.ui = 0;
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;
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;
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);
1624 savageDDInitState_s3d (imesa);
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;
1635 imesa->IsDouble = GL_FALSE;
1636 imesa->toggle = TARGET_FRONT;
1637 imesa->regs.s4.destCtrl.ni.offset =
1638 imesa->savageScreen->frontOffset>>11;
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;
1645 imesa->regs.s4.destCtrl.ni.dstPixFmt = 1;
1646 imesa->regs.s4.destCtrl.ni.dstWidthInTile =
1647 (imesa->savageScreen->width+31)>>5;
1649 imesa->NotFirstFrame = GL_FALSE;
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;
1657 imesa->regs.s4.zBufOffset.ni.zBufWidthInTiles =
1658 (imesa->savageScreen->width+31)>>5;
1659 imesa->regs.s4.zBufOffset.ni.zDepthSelect = 1;
1662 memcpy (imesa->oldRegs.ui, imesa->regs.ui, SAVAGE_NR_REGS*sizeof(uint32_t));
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;
1671 #define INTERESTED (~(NEW_MODELVIEW|NEW_PROJECTION|\
1672 NEW_TEXTURE_MATRIX|\
1673 NEW_USER_CLIP|NEW_CLIENT_STATE))
1675 static void savageDDInvalidateState( struct gl_context *ctx, GLuint new_state )
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;
1685 void savageDDInitStateFuncs(struct gl_context *ctx)
1687 ctx->Driver.UpdateState = savageDDInvalidateState;
1688 ctx->Driver.BlendEquationSeparate = savageDDBlendEquationSeparate;
1689 ctx->Driver.Fogfv = savageDDFogfv;
1690 ctx->Driver.Scissor = savageDDScissor;
1692 ctx->Driver.CullFace = savageDDCullFaceFrontFace;
1693 ctx->Driver.FrontFace = savageDDCullFaceFrontFace;
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;
1702 ctx->Driver.DepthRange = savageDepthRange;
1703 ctx->Driver.Viewport = savageViewport;
1704 ctx->Driver.RenderMode = savageRenderMode;
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;
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;