2 /**************************************************************************
4 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
6 The Weather Channel (TM) funded Tungsten Graphics to develop the
7 initial release of the Radeon 8500 driver under the XFree86 license.
8 This notice must be preserved.
10 Permission is hereby granted, free of charge, to any person obtaining
11 a copy of this software and associated documentation files (the
12 "Software"), to deal in the Software without restriction, including
13 without limitation the rights to use, copy, modify, merge, publish,
14 distribute, sublicense, and/or sell copies of the Software, and to
15 permit persons to whom the Software is furnished to do so, subject to
16 the following conditions:
18 The above copyright notice and this permission notice (including the
19 next paragraph) shall be included in all copies or substantial
20 portions of the Software.
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
25 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
26 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 **************************************************************************/
34 * Keith Whitwell <keith@tungstengraphics.com>
39 #include "api_arrayelt.h"
43 #include "swrast/swrast.h"
44 #include "array_cache/acache.h"
46 #include "tnl/t_pipeline.h"
47 #include "swrast_setup/swrast_setup.h"
50 #include "r200_context.h"
51 #include "r200_ioctl.h"
52 #include "r200_state.h"
55 #include "r200_swtcl.h"
56 #include "r200_vtxfmt.h"
59 /* =============================================================
63 static void r200AlphaFunc( GLcontext *ctx, GLenum func, GLfloat ref )
65 r200ContextPtr rmesa = R200_CONTEXT(ctx);
66 int pp_misc = rmesa->hw.ctx.cmd[CTX_PP_MISC];
69 CLAMPED_FLOAT_TO_UBYTE(refByte, ref);
71 R200_STATECHANGE( rmesa, ctx );
73 pp_misc &= ~(R200_ALPHA_TEST_OP_MASK | R200_REF_ALPHA_MASK);
74 pp_misc |= (refByte & R200_REF_ALPHA_MASK);
78 pp_misc |= R200_ALPHA_TEST_FAIL;
81 pp_misc |= R200_ALPHA_TEST_LESS;
84 pp_misc |= R200_ALPHA_TEST_EQUAL;
87 pp_misc |= R200_ALPHA_TEST_LEQUAL;
90 pp_misc |= R200_ALPHA_TEST_GREATER;
93 pp_misc |= R200_ALPHA_TEST_NEQUAL;
96 pp_misc |= R200_ALPHA_TEST_GEQUAL;
99 pp_misc |= R200_ALPHA_TEST_PASS;
103 rmesa->hw.ctx.cmd[CTX_PP_MISC] = pp_misc;
106 static void r200BlendEquation( GLcontext *ctx, GLenum mode )
108 r200ContextPtr rmesa = R200_CONTEXT(ctx);
109 GLuint b = rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] & ~R200_COMB_FCN_MASK;
114 b |= R200_COMB_FCN_ADD_CLAMP;
117 case GL_FUNC_SUBTRACT:
118 b |= R200_COMB_FCN_SUB_CLAMP;
121 case GL_FUNC_REVERSE_SUBTRACT:
122 b |= R200_COMB_FCN_RSUB_CLAMP;
126 b |= R200_COMB_FCN_MIN;
130 b |= R200_COMB_FCN_MAX;
137 R200_STATECHANGE( rmesa, ctx );
138 rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = b;
139 if ( ctx->Color.ColorLogicOpEnabled ) {
140 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_ROP_ENABLE;
142 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_ROP_ENABLE;
146 static void r200BlendFunc( GLcontext *ctx, GLenum sfactor, GLenum dfactor )
148 r200ContextPtr rmesa = R200_CONTEXT(ctx);
149 GLuint b = rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] &
150 ~(R200_SRC_BLEND_MASK | R200_DST_BLEND_MASK);
152 switch ( ctx->Color.BlendSrcRGB ) {
154 b |= R200_SRC_BLEND_GL_ZERO;
157 b |= R200_SRC_BLEND_GL_ONE;
160 b |= R200_SRC_BLEND_GL_DST_COLOR;
162 case GL_ONE_MINUS_DST_COLOR:
163 b |= R200_SRC_BLEND_GL_ONE_MINUS_DST_COLOR;
166 b |= R200_SRC_BLEND_GL_SRC_COLOR;
168 case GL_ONE_MINUS_SRC_COLOR:
169 b |= R200_SRC_BLEND_GL_ONE_MINUS_SRC_COLOR;
172 b |= R200_SRC_BLEND_GL_SRC_ALPHA;
174 case GL_ONE_MINUS_SRC_ALPHA:
175 b |= R200_SRC_BLEND_GL_ONE_MINUS_SRC_ALPHA;
178 b |= R200_SRC_BLEND_GL_DST_ALPHA;
180 case GL_ONE_MINUS_DST_ALPHA:
181 b |= R200_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA;
183 case GL_SRC_ALPHA_SATURATE:
184 b |= R200_SRC_BLEND_GL_SRC_ALPHA_SATURATE;
186 case GL_CONSTANT_COLOR:
187 b |= R200_SRC_BLEND_GL_CONST_COLOR;
189 case GL_ONE_MINUS_CONSTANT_COLOR:
190 b |= R200_SRC_BLEND_GL_ONE_MINUS_CONST_COLOR;
192 case GL_CONSTANT_ALPHA:
193 b |= R200_SRC_BLEND_GL_CONST_ALPHA;
195 case GL_ONE_MINUS_CONSTANT_ALPHA:
196 b |= R200_SRC_BLEND_GL_ONE_MINUS_CONST_ALPHA;
202 switch ( ctx->Color.BlendDstRGB ) {
204 b |= R200_DST_BLEND_GL_ZERO;
207 b |= R200_DST_BLEND_GL_ONE;
210 b |= R200_DST_BLEND_GL_SRC_COLOR;
212 case GL_ONE_MINUS_SRC_COLOR:
213 b |= R200_DST_BLEND_GL_ONE_MINUS_SRC_COLOR;
216 b |= R200_DST_BLEND_GL_SRC_ALPHA;
218 case GL_ONE_MINUS_SRC_ALPHA:
219 b |= R200_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA;
222 b |= R200_DST_BLEND_GL_DST_COLOR;
224 case GL_ONE_MINUS_DST_COLOR:
225 b |= R200_DST_BLEND_GL_ONE_MINUS_DST_COLOR;
228 b |= R200_DST_BLEND_GL_DST_ALPHA;
230 case GL_ONE_MINUS_DST_ALPHA:
231 b |= R200_DST_BLEND_GL_ONE_MINUS_DST_ALPHA;
233 case GL_CONSTANT_COLOR:
234 b |= R200_DST_BLEND_GL_CONST_COLOR;
236 case GL_ONE_MINUS_CONSTANT_COLOR:
237 b |= R200_DST_BLEND_GL_ONE_MINUS_CONST_COLOR;
239 case GL_CONSTANT_ALPHA:
240 b |= R200_DST_BLEND_GL_CONST_ALPHA;
242 case GL_ONE_MINUS_CONSTANT_ALPHA:
243 b |= R200_DST_BLEND_GL_ONE_MINUS_CONST_ALPHA;
249 R200_STATECHANGE( rmesa, ctx );
250 rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = b;
253 static void r200BlendFuncSeparate( GLcontext *ctx,
254 GLenum sfactorRGB, GLenum dfactorRGB,
255 GLenum sfactorA, GLenum dfactorA )
257 r200BlendFunc( ctx, sfactorRGB, dfactorRGB );
261 /* =============================================================
265 static void r200DepthFunc( GLcontext *ctx, GLenum func )
267 r200ContextPtr rmesa = R200_CONTEXT(ctx);
269 R200_STATECHANGE( rmesa, ctx );
270 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_Z_TEST_MASK;
272 switch ( ctx->Depth.Func ) {
274 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_NEVER;
277 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_LESS;
280 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_EQUAL;
283 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_LEQUAL;
286 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_GREATER;
289 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_NEQUAL;
292 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_GEQUAL;
295 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_ALWAYS;
301 static void r200DepthMask( GLcontext *ctx, GLboolean flag )
303 r200ContextPtr rmesa = R200_CONTEXT(ctx);
304 R200_STATECHANGE( rmesa, ctx );
306 if ( ctx->Depth.Mask ) {
307 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_WRITE_ENABLE;
309 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_Z_WRITE_ENABLE;
314 /* =============================================================
319 static void r200Fogfv( GLcontext *ctx, GLenum pname, const GLfloat *param )
321 r200ContextPtr rmesa = R200_CONTEXT(ctx);
322 union { int i; float f; } c, d;
326 c.i = rmesa->hw.fog.cmd[FOG_C];
327 d.i = rmesa->hw.fog.cmd[FOG_D];
331 if (!ctx->Fog.Enabled)
333 R200_STATECHANGE(rmesa, tcl);
334 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_TCL_FOG_MASK;
335 switch (ctx->Fog.Mode) {
337 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_TCL_FOG_LINEAR;
338 if (ctx->Fog.Start == ctx->Fog.End) {
343 c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start);
344 d.f = -1.0/(ctx->Fog.End-ctx->Fog.Start);
348 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_TCL_FOG_EXP;
350 d.f = -ctx->Fog.Density;
353 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_TCL_FOG_EXP2;
355 d.f = -(ctx->Fog.Density * ctx->Fog.Density);
362 switch (ctx->Fog.Mode) {
365 d.f = -ctx->Fog.Density;
369 d.f = -(ctx->Fog.Density * ctx->Fog.Density);
377 if (ctx->Fog.Mode == GL_LINEAR) {
378 if (ctx->Fog.Start == ctx->Fog.End) {
382 c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start);
383 d.f = -1.0/(ctx->Fog.End-ctx->Fog.Start);
388 R200_STATECHANGE( rmesa, ctx );
389 UNCLAMPED_FLOAT_TO_RGB_CHAN( col, ctx->Fog.Color );
390 i = r200PackColor( 4, col[0], col[1], col[2], 0 );
391 rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] &= ~R200_FOG_COLOR_MASK;
392 rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] |= i;
394 case GL_FOG_COORDINATE_SOURCE_EXT:
402 if (c.i != rmesa->hw.fog.cmd[FOG_C] || d.i != rmesa->hw.fog.cmd[FOG_D]) {
403 R200_STATECHANGE( rmesa, fog );
404 rmesa->hw.fog.cmd[FOG_C] = c.i;
405 rmesa->hw.fog.cmd[FOG_D] = d.i;
410 /* =============================================================
415 static GLboolean intersect_rect( XF86DRIClipRectPtr out,
416 XF86DRIClipRectPtr a,
417 XF86DRIClipRectPtr b )
420 if ( b->x1 > out->x1 ) out->x1 = b->x1;
421 if ( b->y1 > out->y1 ) out->y1 = b->y1;
422 if ( b->x2 < out->x2 ) out->x2 = b->x2;
423 if ( b->y2 < out->y2 ) out->y2 = b->y2;
424 if ( out->x1 >= out->x2 ) return GL_FALSE;
425 if ( out->y1 >= out->y2 ) return GL_FALSE;
430 void r200RecalcScissorRects( r200ContextPtr rmesa )
432 XF86DRIClipRectPtr out;
435 /* Grow cliprect store?
437 if (rmesa->state.scissor.numAllocedClipRects < rmesa->numClipRects) {
438 while (rmesa->state.scissor.numAllocedClipRects < rmesa->numClipRects) {
439 rmesa->state.scissor.numAllocedClipRects += 1; /* zero case */
440 rmesa->state.scissor.numAllocedClipRects *= 2;
443 if (rmesa->state.scissor.pClipRects)
444 FREE(rmesa->state.scissor.pClipRects);
446 rmesa->state.scissor.pClipRects =
447 MALLOC( rmesa->state.scissor.numAllocedClipRects *
448 sizeof(XF86DRIClipRectRec) );
450 if ( rmesa->state.scissor.pClipRects == NULL ) {
451 rmesa->state.scissor.numAllocedClipRects = 0;
456 out = rmesa->state.scissor.pClipRects;
457 rmesa->state.scissor.numClipRects = 0;
459 for ( i = 0 ; i < rmesa->numClipRects ; i++ ) {
460 if ( intersect_rect( out,
461 &rmesa->pClipRects[i],
462 &rmesa->state.scissor.rect ) ) {
463 rmesa->state.scissor.numClipRects++;
470 static void r200UpdateScissor( GLcontext *ctx )
472 r200ContextPtr rmesa = R200_CONTEXT(ctx);
474 if ( rmesa->dri.drawable ) {
475 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
477 int x = ctx->Scissor.X;
478 int y = dPriv->h - ctx->Scissor.Y - ctx->Scissor.Height;
479 int w = ctx->Scissor.X + ctx->Scissor.Width - 1;
480 int h = dPriv->h - ctx->Scissor.Y - 1;
482 rmesa->state.scissor.rect.x1 = x + dPriv->x;
483 rmesa->state.scissor.rect.y1 = y + dPriv->y;
484 rmesa->state.scissor.rect.x2 = w + dPriv->x + 1;
485 rmesa->state.scissor.rect.y2 = h + dPriv->y + 1;
487 r200RecalcScissorRects( rmesa );
492 static void r200Scissor( GLcontext *ctx,
493 GLint x, GLint y, GLsizei w, GLsizei h )
495 r200ContextPtr rmesa = R200_CONTEXT(ctx);
497 if ( ctx->Scissor.Enabled ) {
498 R200_FIREVERTICES( rmesa ); /* don't pipeline cliprect changes */
499 r200UpdateScissor( ctx );
505 /* =============================================================
509 static void r200CullFace( GLcontext *ctx, GLenum unused )
511 r200ContextPtr rmesa = R200_CONTEXT(ctx);
512 GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL];
513 GLuint t = rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL];
515 s |= R200_FFACE_SOLID | R200_BFACE_SOLID;
516 t &= ~(R200_CULL_FRONT | R200_CULL_BACK);
518 if ( ctx->Polygon.CullFlag ) {
519 switch ( ctx->Polygon.CullFaceMode ) {
521 s &= ~R200_FFACE_SOLID;
522 t |= R200_CULL_FRONT;
525 s &= ~R200_BFACE_SOLID;
528 case GL_FRONT_AND_BACK:
529 s &= ~(R200_FFACE_SOLID | R200_BFACE_SOLID);
530 t |= (R200_CULL_FRONT | R200_CULL_BACK);
535 if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) {
536 R200_STATECHANGE(rmesa, set );
537 rmesa->hw.set.cmd[SET_SE_CNTL] = s;
540 if ( rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] != t ) {
541 R200_STATECHANGE(rmesa, tcl );
542 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] = t;
546 static void r200FrontFace( GLcontext *ctx, GLenum mode )
548 r200ContextPtr rmesa = R200_CONTEXT(ctx);
550 R200_STATECHANGE( rmesa, set );
551 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_FFACE_CULL_DIR_MASK;
553 R200_STATECHANGE( rmesa, tcl );
554 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_CULL_FRONT_IS_CCW;
558 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_FFACE_CULL_CW;
561 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_FFACE_CULL_CCW;
562 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_CULL_FRONT_IS_CCW;
567 /* =============================================================
570 static void r200PointSize( GLcontext *ctx, GLfloat size )
572 if (0) fprintf(stderr, "%s: %f\n", __FUNCTION__, size );
575 /* =============================================================
578 static void r200LineWidth( GLcontext *ctx, GLfloat widthf )
580 r200ContextPtr rmesa = R200_CONTEXT(ctx);
582 R200_STATECHANGE( rmesa, lin );
583 R200_STATECHANGE( rmesa, set );
585 /* Line width is stored in U6.4 format.
587 rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] &= ~0xffff;
588 rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] |= (GLuint)(ctx->Line._Width * 16.0);
590 if ( widthf > 1.0 ) {
591 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_WIDELINE_ENABLE;
593 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_WIDELINE_ENABLE;
597 static void r200LineStipple( GLcontext *ctx, GLint factor, GLushort pattern )
599 r200ContextPtr rmesa = R200_CONTEXT(ctx);
601 R200_STATECHANGE( rmesa, lin );
602 rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] =
603 ((((GLuint)factor & 0xff) << 16) | ((GLuint)pattern));
607 /* =============================================================
610 static void r200ColorMask( GLcontext *ctx,
611 GLboolean r, GLboolean g,
612 GLboolean b, GLboolean a )
614 r200ContextPtr rmesa = R200_CONTEXT(ctx);
615 GLuint mask = r200PackColor( rmesa->r200Screen->cpp,
616 ctx->Color.ColorMask[RCOMP],
617 ctx->Color.ColorMask[GCOMP],
618 ctx->Color.ColorMask[BCOMP],
619 ctx->Color.ColorMask[ACOMP] );
621 GLuint flag = rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] & ~R200_PLANE_MASK_ENABLE;
623 if (!(r && g && b && a))
624 flag |= R200_PLANE_MASK_ENABLE;
626 if ( rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] != flag ) {
627 R200_STATECHANGE( rmesa, ctx );
628 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = flag;
631 if ( rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] != mask ) {
632 R200_STATECHANGE( rmesa, msk );
633 rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] = mask;
638 /* =============================================================
642 static void r200PolygonOffset( GLcontext *ctx,
643 GLfloat factor, GLfloat units )
645 r200ContextPtr rmesa = R200_CONTEXT(ctx);
646 GLfloat constant = units * rmesa->state.depth.scale;
651 /* fprintf(stderr, "%s f:%f u:%f\n", __FUNCTION__, factor, constant); */
653 R200_STATECHANGE( rmesa, zbs );
654 rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_FACTOR] = *(GLuint *)&factor;
655 rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_CONSTANT] = *(GLuint *)&constant;
658 static void r200PolygonStipple( GLcontext *ctx, const GLubyte *mask )
660 r200ContextPtr rmesa = R200_CONTEXT(ctx);
662 drmRadeonStipple stipple;
664 /* Must flip pattern upside down.
666 for ( i = 0 ; i < 32 ; i++ ) {
667 rmesa->state.stipple.mask[31 - i] = ((GLuint *) mask)[i];
670 /* TODO: push this into cmd mechanism
672 R200_FIREVERTICES( rmesa );
673 LOCK_HARDWARE( rmesa );
675 /* FIXME: Use window x,y offsets into stipple RAM.
677 stipple.mask = rmesa->state.stipple.mask;
678 drmCommandWrite( rmesa->dri.fd, DRM_RADEON_STIPPLE,
679 &stipple, sizeof(drmRadeonStipple) );
680 UNLOCK_HARDWARE( rmesa );
683 static void r200PolygonMode( GLcontext *ctx, GLenum face, GLenum mode )
685 r200ContextPtr rmesa = R200_CONTEXT(ctx);
686 GLboolean flag = (ctx->_TriangleCaps & DD_TRI_UNFILLED) != 0;
688 /* Can't generally do unfilled via tcl, but some good special
691 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_UNFILLED, flag);
692 if (rmesa->TclFallback) {
693 r200ChooseRenderState( ctx );
694 r200ChooseVertexState( ctx );
699 /* =============================================================
700 * Rendering attributes
702 * We really don't want to recalculate all this every time we bind a
703 * texture. These things shouldn't change all that often, so it makes
704 * sense to break them out of the core texture state update routines.
707 /* Examine lighting and texture state to determine if separate specular
710 static void r200UpdateSpecular( GLcontext *ctx )
712 r200ContextPtr rmesa = R200_CONTEXT(ctx);
713 CARD32 p = rmesa->hw.ctx.cmd[CTX_PP_CNTL];
715 R200_STATECHANGE( rmesa, tcl );
716 R200_STATECHANGE( rmesa, vtx );
718 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] &= ~(3<<R200_VTX_COLOR_0_SHIFT);
719 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] &= ~(3<<R200_VTX_COLOR_1_SHIFT);
720 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] &= ~R200_OUTPUT_COLOR_0;
721 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] &= ~R200_OUTPUT_COLOR_1;
722 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_LIGHTING_ENABLE;
724 p &= ~R200_SPECULAR_ENABLE;
726 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_DIFFUSE_SPECULAR_COMBINE;
729 if (ctx->Light.Enabled &&
730 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) {
731 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
732 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT) |
733 (R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT));
734 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_0;
735 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_1;
736 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHTING_ENABLE;
737 p |= R200_SPECULAR_ENABLE;
738 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &=
739 ~R200_DIFFUSE_SPECULAR_COMBINE;
741 else if (ctx->Light.Enabled) {
742 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
743 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT));
744 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_0;
745 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHTING_ENABLE;
746 } else if (ctx->Fog.ColorSumEnabled ) {
747 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
748 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT) |
749 (R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT));
750 p |= R200_SPECULAR_ENABLE;
752 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
753 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT));
756 if (ctx->Fog.Enabled) {
757 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
758 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT));
759 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_1;
762 if ( rmesa->hw.ctx.cmd[CTX_PP_CNTL] != p ) {
763 R200_STATECHANGE( rmesa, ctx );
764 rmesa->hw.ctx.cmd[CTX_PP_CNTL] = p;
767 /* Update vertex/render formats
769 if (rmesa->TclFallback) {
770 r200ChooseRenderState( ctx );
771 r200ChooseVertexState( ctx );
776 /* =============================================================
781 /* Update on colormaterial, material emmissive/ambient,
782 * lightmodel.globalambient
784 static void update_global_ambient( GLcontext *ctx )
786 r200ContextPtr rmesa = R200_CONTEXT(ctx);
787 float *fcmd = (float *)R200_DB_STATE( glt );
789 /* Need to do more if both emmissive & ambient are PREMULT:
791 if ((rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1] &
792 ((3 << R200_FRONT_EMISSIVE_SOURCE_SHIFT) |
793 (3 << R200_FRONT_AMBIENT_SOURCE_SHIFT))) == 0)
795 COPY_3V( &fcmd[GLT_RED],
796 ctx->Light.Material[0].Emission);
797 ACC_SCALE_3V( &fcmd[GLT_RED],
798 ctx->Light.Model.Ambient,
799 ctx->Light.Material[0].Ambient);
803 COPY_3V( &fcmd[GLT_RED], ctx->Light.Model.Ambient );
806 R200_DB_STATECHANGE(rmesa, &rmesa->hw.glt);
809 /* Update on change to
813 * - colormaterial enabled
814 * - colormaterial bitmask
816 static void update_light_colors( GLcontext *ctx, GLuint p )
818 struct gl_light *l = &ctx->Light.Light[p];
820 /* fprintf(stderr, "%s\n", __FUNCTION__); */
823 r200ContextPtr rmesa = R200_CONTEXT(ctx);
824 float *fcmd = (float *)R200_DB_STATE( lit[p] );
825 GLuint bitmask = ctx->Light.ColorMaterialBitmask;
826 struct gl_material *mat = &ctx->Light.Material[0];
828 COPY_4V( &fcmd[LIT_AMBIENT_RED], l->Ambient );
829 COPY_4V( &fcmd[LIT_DIFFUSE_RED], l->Diffuse );
830 COPY_4V( &fcmd[LIT_SPECULAR_RED], l->Specular );
832 if (!ctx->Light.ColorMaterialEnabled)
835 if ((bitmask & FRONT_AMBIENT_BIT) == 0)
836 SELF_SCALE_3V( &fcmd[LIT_AMBIENT_RED], mat->Ambient );
838 if ((bitmask & FRONT_DIFFUSE_BIT) == 0)
839 SELF_SCALE_3V( &fcmd[LIT_DIFFUSE_RED], mat->Diffuse );
841 if ((bitmask & FRONT_SPECULAR_BIT) == 0)
842 SELF_SCALE_3V( &fcmd[LIT_SPECULAR_RED], mat->Specular );
844 R200_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
848 /* Also fallback for asym colormaterial mode in twoside lighting...
850 static void check_twoside_fallback( GLcontext *ctx )
852 GLboolean fallback = GL_FALSE;
854 if (ctx->Light.Enabled && ctx->Light.Model.TwoSide) {
855 if (memcmp( &ctx->Light.Material[0],
856 &ctx->Light.Material[1],
857 sizeof(struct gl_material)) != 0)
859 else if (ctx->Light.ColorMaterialEnabled &&
860 (ctx->Light.ColorMaterialBitmask & BACK_MATERIAL_BITS) !=
861 ((ctx->Light.ColorMaterialBitmask & FRONT_MATERIAL_BITS)<<1))
865 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_LIGHT_TWOSIDE, fallback );
868 static void r200ColorMaterial( GLcontext *ctx, GLenum face, GLenum mode )
870 if (ctx->Light.ColorMaterialEnabled) {
871 r200ContextPtr rmesa = R200_CONTEXT(ctx);
872 GLuint light_model_ctl1 = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1];
873 GLuint mask = ctx->Light.ColorMaterialBitmask;
875 /* Default to PREMULT:
877 light_model_ctl1 &= ~((0xf << R200_FRONT_EMISSIVE_SOURCE_SHIFT) |
878 (0xf << R200_FRONT_AMBIENT_SOURCE_SHIFT) |
879 (0xf << R200_FRONT_DIFFUSE_SOURCE_SHIFT) |
880 (0xf << R200_FRONT_SPECULAR_SOURCE_SHIFT));
882 if (mask & FRONT_EMISSION_BIT) {
883 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
884 R200_FRONT_EMISSIVE_SOURCE_SHIFT);
887 if (mask & FRONT_AMBIENT_BIT) {
888 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
889 R200_FRONT_AMBIENT_SOURCE_SHIFT);
892 if (mask & FRONT_DIFFUSE_BIT) {
893 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
894 R200_FRONT_DIFFUSE_SOURCE_SHIFT);
897 if (mask & FRONT_SPECULAR_BIT) {
898 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
899 R200_FRONT_SPECULAR_SOURCE_SHIFT);
902 if (light_model_ctl1 != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1]) {
905 R200_STATECHANGE( rmesa, tcl );
906 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1] = light_model_ctl1;
908 for (p = 0 ; p < MAX_LIGHTS; p++)
909 update_light_colors( ctx, p );
910 update_global_ambient( ctx );
914 check_twoside_fallback( ctx );
917 void r200UpdateMaterial( GLcontext *ctx )
919 r200ContextPtr rmesa = R200_CONTEXT(ctx);
920 GLfloat *fcmd = (GLfloat *)R200_DB_STATE( mtl[0] );
924 if (ctx->Light.ColorMaterialEnabled)
925 mask &= ~ctx->Light.ColorMaterialBitmask;
927 if (R200_DEBUG & DEBUG_STATE)
928 fprintf(stderr, "%s\n", __FUNCTION__);
931 if (mask & FRONT_EMISSION_BIT) {
932 fcmd[MTL_EMMISSIVE_RED] = ctx->Light.Material[0].Emission[0];
933 fcmd[MTL_EMMISSIVE_GREEN] = ctx->Light.Material[0].Emission[1];
934 fcmd[MTL_EMMISSIVE_BLUE] = ctx->Light.Material[0].Emission[2];
935 fcmd[MTL_EMMISSIVE_ALPHA] = ctx->Light.Material[0].Emission[3];
937 if (mask & FRONT_AMBIENT_BIT) {
938 fcmd[MTL_AMBIENT_RED] = ctx->Light.Material[0].Ambient[0];
939 fcmd[MTL_AMBIENT_GREEN] = ctx->Light.Material[0].Ambient[1];
940 fcmd[MTL_AMBIENT_BLUE] = ctx->Light.Material[0].Ambient[2];
941 fcmd[MTL_AMBIENT_ALPHA] = ctx->Light.Material[0].Ambient[3];
943 if (mask & FRONT_DIFFUSE_BIT) {
944 fcmd[MTL_DIFFUSE_RED] = ctx->Light.Material[0].Diffuse[0];
945 fcmd[MTL_DIFFUSE_GREEN] = ctx->Light.Material[0].Diffuse[1];
946 fcmd[MTL_DIFFUSE_BLUE] = ctx->Light.Material[0].Diffuse[2];
947 fcmd[MTL_DIFFUSE_ALPHA] = ctx->Light.Material[0].Diffuse[3];
949 if (mask & FRONT_SPECULAR_BIT) {
950 fcmd[MTL_SPECULAR_RED] = ctx->Light.Material[0].Specular[0];
951 fcmd[MTL_SPECULAR_GREEN] = ctx->Light.Material[0].Specular[1];
952 fcmd[MTL_SPECULAR_BLUE] = ctx->Light.Material[0].Specular[2];
953 fcmd[MTL_SPECULAR_ALPHA] = ctx->Light.Material[0].Specular[3];
955 if (mask & FRONT_SHININESS_BIT) {
956 fcmd[MTL_SHININESS] = ctx->Light.Material[0].Shininess;
959 if (R200_DB_STATECHANGE( rmesa, &rmesa->hw.mtl[0] )) {
960 for (p = 0 ; p < MAX_LIGHTS; p++)
961 update_light_colors( ctx, p );
963 check_twoside_fallback( ctx );
964 update_global_ambient( ctx );
966 else if (R200_DEBUG & (DEBUG_PRIMS|DEBUG_STATE))
967 fprintf(stderr, "%s: Elided noop material call\n", __FUNCTION__);
972 * _MESA_NEW_NEED_EYE_COORDS
974 * Uses derived state from mesa:
983 * which are calculated in light.c and are correct for the current
984 * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
985 * and _MESA_NEW_NEED_EYE_COORDS.
987 static void update_light( GLcontext *ctx )
989 r200ContextPtr rmesa = R200_CONTEXT(ctx);
991 /* Have to check these, or have an automatic shortcircuit mechanism
992 * to remove noop statechanges. (Or just do a better job on the
996 GLuint tmp = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0];
998 if (ctx->_NeedEyeCoords)
999 tmp &= ~R200_LIGHT_IN_MODELSPACE;
1001 tmp |= R200_LIGHT_IN_MODELSPACE;
1003 if (tmp != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0])
1005 R200_STATECHANGE( rmesa, tcl );
1006 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] = tmp;
1011 GLfloat *fcmd = (GLfloat *)R200_DB_STATE( eye );
1012 fcmd[EYE_X] = ctx->_EyeZDir[0];
1013 fcmd[EYE_Y] = ctx->_EyeZDir[1];
1014 fcmd[EYE_Z] = - ctx->_EyeZDir[2];
1015 fcmd[EYE_RESCALE_FACTOR] = ctx->_ModelViewInvScale;
1016 R200_DB_STATECHANGE( rmesa, &rmesa->hw.eye );
1021 if (ctx->Light.Enabled) {
1023 for (p = 0 ; p < MAX_LIGHTS; p++) {
1024 if (ctx->Light.Light[p].Enabled) {
1025 struct gl_light *l = &ctx->Light.Light[p];
1026 GLfloat *fcmd = (GLfloat *)R200_DB_STATE( lit[p] );
1028 if (l->EyePosition[3] == 0.0) {
1029 COPY_3FV( &fcmd[LIT_POSITION_X], l->_VP_inf_norm );
1030 COPY_3FV( &fcmd[LIT_DIRECTION_X], l->_h_inf_norm );
1031 fcmd[LIT_POSITION_W] = 0;
1032 fcmd[LIT_DIRECTION_W] = 0;
1034 COPY_4V( &fcmd[LIT_POSITION_X], l->_Position );
1035 fcmd[LIT_DIRECTION_X] = -l->_NormDirection[0];
1036 fcmd[LIT_DIRECTION_Y] = -l->_NormDirection[1];
1037 fcmd[LIT_DIRECTION_Z] = -l->_NormDirection[2];
1038 fcmd[LIT_DIRECTION_W] = 0;
1041 R200_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
1047 static void r200Lightfv( GLcontext *ctx, GLenum light,
1048 GLenum pname, const GLfloat *params )
1050 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1051 GLint p = light - GL_LIGHT0;
1052 struct gl_light *l = &ctx->Light.Light[p];
1053 GLfloat *fcmd = (GLfloat *)rmesa->hw.lit[p].cmd;
1060 update_light_colors( ctx, p );
1063 case GL_SPOT_DIRECTION:
1064 /* picked up in update_light */
1068 /* positions picked up in update_light, but can do flag here */
1069 GLuint flag = (p&1)? R200_LIGHT_1_IS_LOCAL : R200_LIGHT_0_IS_LOCAL;
1070 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1072 R200_STATECHANGE(rmesa, tcl);
1073 if (l->EyePosition[3] != 0.0F)
1074 rmesa->hw.tcl.cmd[idx] |= flag;
1076 rmesa->hw.tcl.cmd[idx] &= ~flag;
1080 case GL_SPOT_EXPONENT:
1081 R200_STATECHANGE(rmesa, lit[p]);
1082 fcmd[LIT_SPOT_EXPONENT] = params[0];
1085 case GL_SPOT_CUTOFF: {
1086 GLuint flag = (p&1) ? R200_LIGHT_1_IS_SPOT : R200_LIGHT_0_IS_SPOT;
1087 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1089 R200_STATECHANGE(rmesa, lit[p]);
1090 fcmd[LIT_SPOT_CUTOFF] = l->_CosCutoff;
1092 R200_STATECHANGE(rmesa, tcl);
1093 if (l->SpotCutoff != 180.0F)
1094 rmesa->hw.tcl.cmd[idx] |= flag;
1096 rmesa->hw.tcl.cmd[idx] &= ~flag;
1101 case GL_CONSTANT_ATTENUATION:
1102 R200_STATECHANGE(rmesa, lit[p]);
1103 fcmd[LIT_ATTEN_CONST] = params[0];
1105 case GL_LINEAR_ATTENUATION:
1106 R200_STATECHANGE(rmesa, lit[p]);
1107 fcmd[LIT_ATTEN_LINEAR] = params[0];
1109 case GL_QUADRATIC_ATTENUATION:
1110 R200_STATECHANGE(rmesa, lit[p]);
1111 fcmd[LIT_ATTEN_QUADRATIC] = params[0];
1122 static void r200LightModelfv( GLcontext *ctx, GLenum pname,
1123 const GLfloat *param )
1125 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1128 case GL_LIGHT_MODEL_AMBIENT:
1129 update_global_ambient( ctx );
1132 case GL_LIGHT_MODEL_LOCAL_VIEWER:
1133 R200_STATECHANGE( rmesa, tcl );
1134 if (ctx->Light.Model.LocalViewer)
1135 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LOCAL_VIEWER;
1137 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_LOCAL_VIEWER;
1140 case GL_LIGHT_MODEL_TWO_SIDE:
1141 R200_STATECHANGE( rmesa, tcl );
1142 if (ctx->Light.Model.TwoSide)
1143 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHT_TWOSIDE;
1145 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_LIGHT_TWOSIDE;
1147 check_twoside_fallback( ctx );
1149 if (rmesa->TclFallback) {
1150 r200ChooseRenderState( ctx );
1151 r200ChooseVertexState( ctx );
1155 case GL_LIGHT_MODEL_COLOR_CONTROL:
1156 r200UpdateSpecular(ctx);
1164 static void r200ShadeModel( GLcontext *ctx, GLenum mode )
1166 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1167 GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL];
1169 s &= ~(R200_DIFFUSE_SHADE_MASK |
1170 R200_ALPHA_SHADE_MASK |
1171 R200_SPECULAR_SHADE_MASK |
1172 R200_FOG_SHADE_MASK);
1176 s |= (R200_DIFFUSE_SHADE_FLAT |
1177 R200_ALPHA_SHADE_FLAT |
1178 R200_SPECULAR_SHADE_FLAT |
1179 R200_FOG_SHADE_FLAT);
1182 s |= (R200_DIFFUSE_SHADE_GOURAUD |
1183 R200_ALPHA_SHADE_GOURAUD |
1184 R200_SPECULAR_SHADE_GOURAUD |
1185 R200_FOG_SHADE_GOURAUD);
1191 if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) {
1192 R200_STATECHANGE( rmesa, set );
1193 rmesa->hw.set.cmd[SET_SE_CNTL] = s;
1198 /* =============================================================
1202 static void r200ClipPlane( GLcontext *ctx, GLenum plane, const GLfloat *eq )
1204 GLint p = (GLint) plane - (GLint) GL_CLIP_PLANE0;
1205 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1206 GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
1208 R200_STATECHANGE( rmesa, ucp[p] );
1209 rmesa->hw.ucp[p].cmd[UCP_X] = ip[0];
1210 rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1];
1211 rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2];
1212 rmesa->hw.ucp[p].cmd[UCP_W] = ip[3];
1215 static void r200UpdateClipPlanes( GLcontext *ctx )
1217 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1220 for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
1221 if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
1222 GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
1224 R200_STATECHANGE( rmesa, ucp[p] );
1225 rmesa->hw.ucp[p].cmd[UCP_X] = ip[0];
1226 rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1];
1227 rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2];
1228 rmesa->hw.ucp[p].cmd[UCP_W] = ip[3];
1234 /* =============================================================
1238 static void r200StencilFunc( GLcontext *ctx, GLenum func,
1239 GLint ref, GLuint mask )
1241 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1242 GLuint refmask = ((ctx->Stencil.Ref[0] << R200_STENCIL_REF_SHIFT) |
1243 (ctx->Stencil.ValueMask[0] << R200_STENCIL_MASK_SHIFT));
1245 R200_STATECHANGE( rmesa, ctx );
1246 R200_STATECHANGE( rmesa, msk );
1248 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_STENCIL_TEST_MASK;
1249 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~(R200_STENCIL_REF_MASK|
1250 R200_STENCIL_VALUE_MASK);
1252 switch ( ctx->Stencil.Function[0] ) {
1254 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_NEVER;
1257 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_LESS;
1260 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_EQUAL;
1263 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_LEQUAL;
1266 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_GREATER;
1269 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_NEQUAL;
1272 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_GEQUAL;
1275 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_ALWAYS;
1279 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |= refmask;
1282 static void r200StencilMask( GLcontext *ctx, GLuint mask )
1284 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1286 R200_STATECHANGE( rmesa, msk );
1287 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~R200_STENCIL_WRITE_MASK;
1288 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |=
1289 (ctx->Stencil.WriteMask[0] << R200_STENCIL_WRITEMASK_SHIFT);
1292 static void r200StencilOp( GLcontext *ctx, GLenum fail,
1293 GLenum zfail, GLenum zpass )
1295 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1297 R200_STATECHANGE( rmesa, ctx );
1298 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~(R200_STENCIL_FAIL_MASK |
1299 R200_STENCIL_ZFAIL_MASK |
1300 R200_STENCIL_ZPASS_MASK);
1302 switch ( ctx->Stencil.FailFunc[0] ) {
1304 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_KEEP;
1307 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_ZERO;
1310 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_REPLACE;
1313 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INC;
1316 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_DEC;
1318 case GL_INCR_WRAP_EXT:
1319 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INC_WRAP;
1321 case GL_DECR_WRAP_EXT:
1322 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_DEC_WRAP;
1325 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INVERT;
1329 switch ( ctx->Stencil.ZFailFunc[0] ) {
1331 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_KEEP;
1334 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_ZERO;
1337 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_REPLACE;
1340 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INC;
1343 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_DEC;
1345 case GL_INCR_WRAP_EXT:
1346 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INC_WRAP;
1348 case GL_DECR_WRAP_EXT:
1349 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_DEC_WRAP;
1352 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INVERT;
1356 switch ( ctx->Stencil.ZPassFunc[0] ) {
1358 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_KEEP;
1361 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_ZERO;
1364 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_REPLACE;
1367 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INC;
1370 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_DEC;
1372 case GL_INCR_WRAP_EXT:
1373 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INC_WRAP;
1375 case GL_DECR_WRAP_EXT:
1376 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_DEC_WRAP;
1379 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INVERT;
1384 static void r200ClearStencil( GLcontext *ctx, GLint s )
1386 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1388 rmesa->state.stencil.clear =
1389 ((GLuint) ctx->Stencil.Clear |
1390 (0xff << R200_STENCIL_MASK_SHIFT) |
1391 (ctx->Stencil.WriteMask[0] << R200_STENCIL_WRITEMASK_SHIFT));
1395 /* =============================================================
1396 * Window position and viewport transformation
1400 * To correctly position primitives:
1402 #define SUBPIXEL_X 0.125
1403 #define SUBPIXEL_Y 0.125
1405 void r200UpdateWindow( GLcontext *ctx )
1407 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1408 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
1409 GLfloat xoffset = (GLfloat)dPriv->x;
1410 GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h;
1411 const GLfloat *v = ctx->Viewport._WindowMap.m;
1413 GLfloat sx = v[MAT_SX];
1414 GLfloat tx = v[MAT_TX] + xoffset + SUBPIXEL_X;
1415 GLfloat sy = - v[MAT_SY];
1416 GLfloat ty = (- v[MAT_TY]) + yoffset + SUBPIXEL_Y;
1417 GLfloat sz = v[MAT_SZ] * rmesa->state.depth.scale;
1418 GLfloat tz = v[MAT_TZ] * rmesa->state.depth.scale;
1420 R200_FIREVERTICES( rmesa );
1421 R200_STATECHANGE( rmesa, vpt );
1423 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XSCALE] = *(GLuint *)&sx;
1424 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = *(GLuint *)&tx;
1425 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YSCALE] = *(GLuint *)&sy;
1426 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = *(GLuint *)&ty;
1427 rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZSCALE] = *(GLuint *)&sz;
1428 rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZOFFSET] = *(GLuint *)&tz;
1433 static void r200Viewport( GLcontext *ctx, GLint x, GLint y,
1434 GLsizei width, GLsizei height )
1436 /* Don't pipeline viewport changes, conflict with window offset
1437 * setting below. Could apply deltas to rescue pipelined viewport
1438 * values, or keep the originals hanging around.
1440 R200_FIREVERTICES( R200_CONTEXT(ctx) );
1441 r200UpdateWindow( ctx );
1444 static void r200DepthRange( GLcontext *ctx, GLclampd nearval,
1447 r200UpdateWindow( ctx );
1450 void r200UpdateViewportOffset( GLcontext *ctx )
1452 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1453 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
1454 GLfloat xoffset = (GLfloat)dPriv->x;
1455 GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h;
1456 const GLfloat *v = ctx->Viewport._WindowMap.m;
1458 GLfloat tx = v[MAT_TX] + xoffset;
1459 GLfloat ty = (- v[MAT_TY]) + yoffset;
1461 if ( rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] != *(GLuint *)&tx ||
1462 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] != *(GLuint *)&ty )
1464 /* Note: this should also modify whatever data the context reset
1467 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = *(GLuint *)&tx;
1468 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = *(GLuint *)&ty;
1470 /* update polygon stipple x/y screen offset */
1473 GLuint m = rmesa->hw.msc.cmd[MSC_RE_MISC];
1475 m &= ~(R200_STIPPLE_X_OFFSET_MASK |
1476 R200_STIPPLE_Y_OFFSET_MASK);
1478 /* add magic offsets, then invert */
1479 stx = 31 - ((rmesa->dri.drawable->x - 1) & R200_STIPPLE_COORD_MASK);
1480 sty = 31 - ((rmesa->dri.drawable->y + rmesa->dri.drawable->h - 1)
1481 & R200_STIPPLE_COORD_MASK);
1483 m |= ((stx << R200_STIPPLE_X_OFFSET_SHIFT) |
1484 (sty << R200_STIPPLE_Y_OFFSET_SHIFT));
1486 if ( rmesa->hw.msc.cmd[MSC_RE_MISC] != m ) {
1487 R200_STATECHANGE( rmesa, msc );
1488 rmesa->hw.msc.cmd[MSC_RE_MISC] = m;
1493 r200UpdateScissor( ctx );
1498 /* =============================================================
1502 static void r200ClearColor( GLcontext *ctx, const GLfloat c[4] )
1504 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1506 CLAMPED_FLOAT_TO_UBYTE(color[0], c[0]);
1507 CLAMPED_FLOAT_TO_UBYTE(color[1], c[1]);
1508 CLAMPED_FLOAT_TO_UBYTE(color[2], c[2]);
1509 CLAMPED_FLOAT_TO_UBYTE(color[3], c[3]);
1510 rmesa->state.color.clear = r200PackColor( rmesa->r200Screen->cpp,
1512 color[2], color[3] );
1516 static void r200RenderMode( GLcontext *ctx, GLenum mode )
1518 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1519 FALLBACK( rmesa, R200_FALLBACK_RENDER_MODE, (mode != GL_RENDER) );
1523 static GLuint r200_rop_tab[] = {
1526 R200_ROP_AND_REVERSE,
1528 R200_ROP_AND_INVERTED,
1535 R200_ROP_OR_REVERSE,
1536 R200_ROP_COPY_INVERTED,
1537 R200_ROP_OR_INVERTED,
1542 static void r200LogicOpCode( GLcontext *ctx, GLenum opcode )
1544 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1545 GLuint rop = (GLuint)opcode - GL_CLEAR;
1549 R200_STATECHANGE( rmesa, msk );
1550 rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = r200_rop_tab[rop];
1554 void r200SetCliprects( r200ContextPtr rmesa, GLenum mode )
1556 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
1560 rmesa->numClipRects = dPriv->numClipRects;
1561 rmesa->pClipRects = (XF86DRIClipRectPtr)dPriv->pClipRects;
1564 /* Can't ignore 2d windows if we are page flipping.
1566 if ( dPriv->numBackClipRects == 0 || rmesa->doPageFlip ) {
1567 rmesa->numClipRects = dPriv->numClipRects;
1568 rmesa->pClipRects = (XF86DRIClipRectPtr)dPriv->pClipRects;
1571 rmesa->numClipRects = dPriv->numBackClipRects;
1572 rmesa->pClipRects = (XF86DRIClipRectPtr)dPriv->pBackClipRects;
1576 fprintf(stderr, "bad mode in r200SetCliprects\n");
1580 if (rmesa->state.scissor.enabled)
1581 r200RecalcScissorRects( rmesa );
1585 static void r200DrawBuffer( GLcontext *ctx, GLenum mode )
1587 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1589 if (R200_DEBUG & DEBUG_DRI)
1590 fprintf(stderr, "%s %s\n", __FUNCTION__,
1591 _mesa_lookup_enum_by_nr( mode ));
1593 R200_FIREVERTICES(rmesa); /* don't pipeline cliprect changes */
1596 * _DrawDestMask is easier to cope with than <mode>.
1598 switch ( ctx->Color._DrawDestMask ) {
1599 case FRONT_LEFT_BIT:
1600 FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_FALSE );
1601 r200SetCliprects( rmesa, GL_FRONT_LEFT );
1604 FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_FALSE );
1605 r200SetCliprects( rmesa, GL_BACK_LEFT );
1608 /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */
1609 FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_TRUE );
1613 /* We want to update the s/w rast state too so that r200SetBuffer()
1616 _swrast_DrawBuffer(ctx, mode);
1618 R200_STATECHANGE( rmesa, ctx );
1619 rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = (rmesa->state.color.drawOffset &
1620 R200_COLOROFFSET_MASK);
1621 rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = rmesa->state.color.drawPitch;
1625 static void r200ReadBuffer( GLcontext *ctx, GLenum mode )
1627 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
1630 /* =============================================================
1631 * State enable/disable
1634 static void r200Enable( GLcontext *ctx, GLenum cap, GLboolean state )
1636 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1639 if ( R200_DEBUG & DEBUG_STATE )
1640 fprintf( stderr, "%s( %s = %s )\n", __FUNCTION__,
1641 _mesa_lookup_enum_by_nr( cap ),
1642 state ? "GL_TRUE" : "GL_FALSE" );
1645 /* Fast track this one...
1653 R200_STATECHANGE( rmesa, ctx );
1655 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ALPHA_TEST_ENABLE;
1657 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ALPHA_TEST_ENABLE;
1662 R200_STATECHANGE( rmesa, ctx );
1664 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_ALPHA_BLEND_ENABLE;
1666 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_ALPHA_BLEND_ENABLE;
1668 if ( ctx->Color.ColorLogicOpEnabled ) {
1669 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_ROP_ENABLE;
1671 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_ROP_ENABLE;
1675 case GL_CLIP_PLANE0:
1676 case GL_CLIP_PLANE1:
1677 case GL_CLIP_PLANE2:
1678 case GL_CLIP_PLANE3:
1679 case GL_CLIP_PLANE4:
1680 case GL_CLIP_PLANE5:
1681 p = cap-GL_CLIP_PLANE0;
1682 R200_STATECHANGE( rmesa, tcl );
1684 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (R200_UCP_ENABLE_0<<p);
1685 r200ClipPlane( ctx, cap, NULL );
1688 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0<<p);
1692 case GL_COLOR_MATERIAL:
1693 r200ColorMaterial( ctx, 0, 0 );
1695 r200UpdateMaterial( ctx );
1699 r200CullFace( ctx, 0 );
1703 R200_STATECHANGE(rmesa, ctx );
1705 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_Z_ENABLE;
1707 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_Z_ENABLE;
1712 R200_STATECHANGE(rmesa, ctx );
1714 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_DITHER_ENABLE;
1716 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_DITHER_ENABLE;
1721 R200_STATECHANGE(rmesa, ctx );
1723 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_FOG_ENABLE;
1724 r200Fogfv( ctx, GL_FOG_MODE, 0 );
1726 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_FOG_ENABLE;
1727 R200_STATECHANGE(rmesa, tcl);
1728 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_TCL_FOG_MASK;
1730 r200UpdateSpecular( ctx ); /* for PK_SPEC */
1741 R200_STATECHANGE(rmesa, tcl);
1742 p = cap - GL_LIGHT0;
1744 flag = (R200_LIGHT_1_ENABLE |
1745 R200_LIGHT_1_ENABLE_AMBIENT |
1746 R200_LIGHT_1_ENABLE_SPECULAR);
1748 flag = (R200_LIGHT_0_ENABLE |
1749 R200_LIGHT_0_ENABLE_AMBIENT |
1750 R200_LIGHT_0_ENABLE_SPECULAR);
1753 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] |= flag;
1755 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] &= ~flag;
1759 update_light_colors( ctx, p );
1763 r200UpdateSpecular(ctx);
1764 check_twoside_fallback( ctx );
1767 case GL_LINE_SMOOTH:
1768 R200_STATECHANGE( rmesa, ctx );
1770 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ANTI_ALIAS_LINE;
1772 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_LINE;
1776 case GL_LINE_STIPPLE:
1777 R200_STATECHANGE( rmesa, set );
1779 rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_PATTERN_ENABLE;
1781 rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_PATTERN_ENABLE;
1785 case GL_COLOR_LOGIC_OP:
1786 R200_STATECHANGE( rmesa, ctx );
1788 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_ROP_ENABLE;
1790 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_ROP_ENABLE;
1795 R200_STATECHANGE( rmesa, tcl );
1797 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_NORMALIZE_NORMALS;
1799 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_NORMALIZE_NORMALS;
1803 /* Pointsize registers on r200 don't seem to do anything. Maybe
1804 * have to pass pointsizes as vertex parameters? In any case,
1805 * setting pointmin == pointsizemax == 1.0, and doing nothing
1806 * for aa is enough to satisfy conform.
1808 case GL_POINT_SMOOTH:
1811 /* These don't really do anything, as we don't use the 3vtx
1815 case GL_POLYGON_OFFSET_POINT:
1816 R200_STATECHANGE( rmesa, set );
1818 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_POINT;
1820 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_POINT;
1824 case GL_POLYGON_OFFSET_LINE:
1825 R200_STATECHANGE( rmesa, set );
1827 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_LINE;
1829 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_LINE;
1834 case GL_POLYGON_OFFSET_FILL:
1835 R200_STATECHANGE( rmesa, set );
1837 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_TRI;
1839 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_TRI;
1843 case GL_POLYGON_SMOOTH:
1844 R200_STATECHANGE( rmesa, ctx );
1846 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ANTI_ALIAS_POLY;
1848 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_POLY;
1852 case GL_POLYGON_STIPPLE:
1853 R200_STATECHANGE(rmesa, set );
1855 rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_STIPPLE_ENABLE;
1857 rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_STIPPLE_ENABLE;
1861 case GL_RESCALE_NORMAL_EXT: {
1862 GLboolean tmp = ctx->_NeedEyeCoords ? state : !state;
1863 R200_STATECHANGE( rmesa, tcl );
1865 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_RESCALE_NORMALS;
1867 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS;
1872 case GL_SCISSOR_TEST:
1873 R200_FIREVERTICES( rmesa );
1874 rmesa->state.scissor.enabled = state;
1875 r200UpdateScissor( ctx );
1878 case GL_STENCIL_TEST:
1879 if ( rmesa->state.stencil.hwBuffer ) {
1880 R200_STATECHANGE( rmesa, ctx );
1882 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_STENCIL_ENABLE;
1884 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_STENCIL_ENABLE;
1887 FALLBACK( rmesa, R200_FALLBACK_STENCIL, state );
1891 case GL_TEXTURE_GEN_Q:
1892 case GL_TEXTURE_GEN_R:
1893 case GL_TEXTURE_GEN_S:
1894 case GL_TEXTURE_GEN_T:
1895 /* Picked up in r200UpdateTextureState.
1897 rmesa->recheck_texgen[ctx->Texture.CurrentUnit] = GL_TRUE;
1900 case GL_COLOR_SUM_EXT:
1901 r200UpdateSpecular ( ctx );
1910 void r200LightingSpaceChange( GLcontext *ctx )
1912 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1915 if (R200_DEBUG & DEBUG_STATE)
1916 fprintf(stderr, "%s %d BEFORE %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
1917 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]);
1919 if (ctx->_NeedEyeCoords)
1920 tmp = ctx->Transform.RescaleNormals;
1922 tmp = !ctx->Transform.RescaleNormals;
1924 R200_STATECHANGE( rmesa, tcl );
1926 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_RESCALE_NORMALS;
1928 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS;
1931 if (R200_DEBUG & DEBUG_STATE)
1932 fprintf(stderr, "%s %d AFTER %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
1933 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]);
1936 /* =============================================================
1937 * Deferred state management - matrices, textures, other?
1943 static void upload_matrix( r200ContextPtr rmesa, GLfloat *src, int idx )
1945 float *dest = ((float *)R200_DB_STATE( mat[idx] ))+MAT_ELT_0;
1949 for (i = 0 ; i < 4 ; i++) {
1953 *dest++ = src[i+12];
1956 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
1959 static void upload_matrix_t( r200ContextPtr rmesa, const GLfloat *src, int idx )
1961 float *dest = ((float *)R200_DB_STATE( mat[idx] ))+MAT_ELT_0;
1962 memcpy(dest, src, 16*sizeof(float));
1963 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
1967 static void update_texturematrix( GLcontext *ctx )
1969 r200ContextPtr rmesa = R200_CONTEXT( ctx );
1970 GLuint tpc = rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0];
1971 GLuint compsel = rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL];
1974 if (R200_DEBUG & DEBUG_STATE)
1975 fprintf(stderr, "%s before COMPSEL: %x\n", __FUNCTION__,
1976 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]);
1978 rmesa->TexMatEnabled = 0;
1979 rmesa->TexMatCompSel = 0;
1981 for (unit = 0 ; unit < 2; unit++) {
1982 if (!ctx->Texture.Unit[unit]._ReallyEnabled)
1985 if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY) {
1986 rmesa->TexMatEnabled |= (R200_TEXGEN_TEXMAT_0_ENABLE|
1987 R200_TEXMAT_0_ENABLE) << unit;
1989 rmesa->TexMatCompSel |= R200_OUTPUT_TEX_0 << unit;
1991 if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) {
1992 /* Need to preconcatenate any active texgen
1993 * obj/eyeplane matrices:
1995 _math_matrix_mul_matrix( &rmesa->tmpmat,
1996 &rmesa->TexGenMatrix[unit],
1997 ctx->TextureMatrixStack[unit].Top );
1998 upload_matrix( rmesa, rmesa->tmpmat.m, R200_MTX_TEX0+unit );
2001 upload_matrix( rmesa, ctx->TextureMatrixStack[unit].Top->m,
2002 R200_MTX_TEX0+unit );
2005 else if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) {
2006 upload_matrix( rmesa, rmesa->TexGenMatrix[unit].m,
2007 R200_MTX_TEX0+unit );
2011 tpc = (rmesa->TexMatEnabled | rmesa->TexGenEnabled);
2012 if (tpc != rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0] ||
2013 rmesa->TexGenInputs != rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_1]) {
2014 R200_STATECHANGE(rmesa, tcg);
2015 rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0] = tpc;
2016 rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_1] = rmesa->TexGenInputs;
2019 compsel &= ~R200_OUTPUT_TEX_MASK;
2020 compsel |= rmesa->TexMatCompSel | rmesa->TexGenCompSel;
2021 if (compsel != rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]) {
2022 R200_STATECHANGE(rmesa, vtx);
2023 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] = compsel;
2029 void r200ValidateState( GLcontext *ctx )
2031 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2032 GLuint new_state = rmesa->NewGLState;
2034 if (new_state & _NEW_TEXTURE) {
2035 r200UpdateTextureState( ctx );
2036 new_state |= rmesa->NewGLState; /* may add TEXTURE_MATRIX */
2039 /* Need an event driven matrix update?
2041 if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION))
2042 upload_matrix( rmesa, ctx->_ModelProjectMatrix.m, R200_MTX_MVP );
2044 /* Need these for lighting (shouldn't upload otherwise)
2046 if (new_state & (_NEW_MODELVIEW)) {
2047 upload_matrix( rmesa, ctx->ModelviewMatrixStack.Top->m, R200_MTX_MV );
2048 upload_matrix_t( rmesa, ctx->ModelviewMatrixStack.Top->inv, R200_MTX_IMV );
2051 /* Does this need to be triggered on eg. modelview for
2052 * texgen-derived objplane/eyeplane matrices?
2054 if (new_state & (_NEW_TEXTURE|_NEW_TEXTURE_MATRIX)) {
2055 update_texturematrix( ctx );
2058 if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW|_MESA_NEW_NEED_EYE_COORDS)) {
2059 update_light( ctx );
2062 /* emit all active clip planes if projection matrix changes.
2064 if (new_state & (_NEW_PROJECTION)) {
2065 if (ctx->Transform.ClipPlanesEnabled)
2066 r200UpdateClipPlanes( ctx );
2070 rmesa->NewGLState = 0;
2074 static void r200InvalidateState( GLcontext *ctx, GLuint new_state )
2076 _swrast_InvalidateState( ctx, new_state );
2077 _swsetup_InvalidateState( ctx, new_state );
2078 _ac_InvalidateState( ctx, new_state );
2079 _tnl_InvalidateState( ctx, new_state );
2080 _ae_invalidate_state( ctx, new_state );
2081 R200_CONTEXT(ctx)->NewGLState |= new_state;
2082 r200VtxfmtInvalidate( ctx );
2085 static void r200WrapRunPipeline( GLcontext *ctx )
2087 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2088 TNLcontext *tnl = TNL_CONTEXT(ctx);
2091 fprintf(stderr, "%s, newstate: %x\n", __FUNCTION__, rmesa->NewGLState);
2095 if (rmesa->NewGLState)
2096 r200ValidateState( ctx );
2098 if (tnl->vb.Material) {
2099 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_TRUE );
2102 /* Run the pipeline.
2104 _tnl_run_pipeline( ctx );
2106 if (tnl->vb.Material) {
2107 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_FALSE );
2108 r200UpdateMaterial( ctx ); /* not needed any more? */
2113 /* Initialize the driver's state functions.
2115 void r200InitStateFuncs( GLcontext *ctx )
2117 ctx->Driver.UpdateState = r200InvalidateState;
2118 ctx->Driver.LightingSpaceChange = r200LightingSpaceChange;
2120 ctx->Driver.DrawBuffer = r200DrawBuffer;
2121 ctx->Driver.ReadBuffer = r200ReadBuffer;
2123 ctx->Driver.AlphaFunc = r200AlphaFunc;
2124 ctx->Driver.BlendEquation = r200BlendEquation;
2125 ctx->Driver.BlendFunc = r200BlendFunc;
2126 ctx->Driver.BlendFuncSeparate = r200BlendFuncSeparate;
2127 ctx->Driver.ClearColor = r200ClearColor;
2128 ctx->Driver.ClearDepth = NULL;
2129 ctx->Driver.ClearIndex = NULL;
2130 ctx->Driver.ClearStencil = r200ClearStencil;
2131 ctx->Driver.ClipPlane = r200ClipPlane;
2132 ctx->Driver.ColorMask = r200ColorMask;
2133 ctx->Driver.CullFace = r200CullFace;
2134 ctx->Driver.DepthFunc = r200DepthFunc;
2135 ctx->Driver.DepthMask = r200DepthMask;
2136 ctx->Driver.DepthRange = r200DepthRange;
2137 ctx->Driver.Enable = r200Enable;
2138 ctx->Driver.Fogfv = r200Fogfv;
2139 ctx->Driver.FrontFace = r200FrontFace;
2140 ctx->Driver.Hint = NULL;
2141 ctx->Driver.IndexMask = NULL;
2142 ctx->Driver.LightModelfv = r200LightModelfv;
2143 ctx->Driver.Lightfv = r200Lightfv;
2144 ctx->Driver.LineStipple = r200LineStipple;
2145 ctx->Driver.LineWidth = r200LineWidth;
2146 ctx->Driver.LogicOpcode = r200LogicOpCode;
2147 ctx->Driver.PolygonMode = r200PolygonMode;
2148 ctx->Driver.PolygonOffset = r200PolygonOffset;
2149 ctx->Driver.PolygonStipple = r200PolygonStipple;
2150 ctx->Driver.PointSize = r200PointSize;
2151 ctx->Driver.RenderMode = r200RenderMode;
2152 ctx->Driver.Scissor = r200Scissor;
2153 ctx->Driver.ShadeModel = r200ShadeModel;
2154 ctx->Driver.StencilFunc = r200StencilFunc;
2155 ctx->Driver.StencilMask = r200StencilMask;
2156 ctx->Driver.StencilOp = r200StencilOp;
2157 ctx->Driver.Viewport = r200Viewport;
2159 /* Swrast hooks for imaging extensions:
2161 ctx->Driver.CopyColorTable = _swrast_CopyColorTable;
2162 ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable;
2163 ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
2164 ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
2166 TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange = r200UpdateMaterial;
2167 TNL_CONTEXT(ctx)->Driver.RunPipeline = r200WrapRunPipeline;