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"
44 #include "swrast/swrast.h"
45 #include "array_cache/acache.h"
47 #include "tnl/t_pipeline.h"
48 #include "swrast_setup/swrast_setup.h"
51 #include "r200_context.h"
52 #include "r200_ioctl.h"
53 #include "r200_state.h"
56 #include "r200_swtcl.h"
57 #include "r200_vtxfmt.h"
60 /* =============================================================
64 static void r200AlphaFunc( GLcontext *ctx, GLenum func, GLfloat ref )
66 r200ContextPtr rmesa = R200_CONTEXT(ctx);
67 int pp_misc = rmesa->hw.ctx.cmd[CTX_PP_MISC];
70 CLAMPED_FLOAT_TO_UBYTE(refByte, ref);
72 R200_STATECHANGE( rmesa, ctx );
74 pp_misc &= ~(R200_ALPHA_TEST_OP_MASK | R200_REF_ALPHA_MASK);
75 pp_misc |= (refByte & R200_REF_ALPHA_MASK);
79 pp_misc |= R200_ALPHA_TEST_FAIL;
82 pp_misc |= R200_ALPHA_TEST_LESS;
85 pp_misc |= R200_ALPHA_TEST_EQUAL;
88 pp_misc |= R200_ALPHA_TEST_LEQUAL;
91 pp_misc |= R200_ALPHA_TEST_GREATER;
94 pp_misc |= R200_ALPHA_TEST_NEQUAL;
97 pp_misc |= R200_ALPHA_TEST_GEQUAL;
100 pp_misc |= R200_ALPHA_TEST_PASS;
104 rmesa->hw.ctx.cmd[CTX_PP_MISC] = pp_misc;
107 static void r200BlendColor( GLcontext *ctx, const GLfloat cf[4] )
110 r200ContextPtr rmesa = R200_CONTEXT(ctx);
111 R200_STATECHANGE( rmesa, ctx );
112 CLAMPED_FLOAT_TO_UBYTE(color[0], cf[0]);
113 CLAMPED_FLOAT_TO_UBYTE(color[1], cf[1]);
114 CLAMPED_FLOAT_TO_UBYTE(color[2], cf[2]);
115 CLAMPED_FLOAT_TO_UBYTE(color[3], cf[3]);
116 if (rmesa->r200Screen->drmSupportsBlendColor)
117 rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCOLOR] = r200PackColor( 4, color[0], color[1], color[2], color[3] );
121 * Calculate the hardware blend factor setting. This same function is used
122 * for source and destination of both alpha and RGB.
125 * The hardware register value for the specified blend factor. This value
126 * will need to be shifted into the correct position for either source or
127 * destination factor.
130 * Since the two cases where source and destination are handled differently
131 * are essentially error cases, they should never happen. Determine if these
132 * cases can be removed.
134 static int blend_factor( GLenum factor, GLboolean is_src )
140 func = R200_BLEND_GL_ZERO;
143 func = R200_BLEND_GL_ONE;
146 func = R200_BLEND_GL_DST_COLOR;
148 case GL_ONE_MINUS_DST_COLOR:
149 func = R200_BLEND_GL_ONE_MINUS_DST_COLOR;
152 func = R200_BLEND_GL_SRC_COLOR;
154 case GL_ONE_MINUS_SRC_COLOR:
155 func = R200_BLEND_GL_ONE_MINUS_SRC_COLOR;
158 func = R200_BLEND_GL_SRC_ALPHA;
160 case GL_ONE_MINUS_SRC_ALPHA:
161 func = R200_BLEND_GL_ONE_MINUS_SRC_ALPHA;
164 func = R200_BLEND_GL_DST_ALPHA;
166 case GL_ONE_MINUS_DST_ALPHA:
167 func = R200_BLEND_GL_ONE_MINUS_DST_ALPHA;
169 case GL_SRC_ALPHA_SATURATE:
170 func = (is_src) ? R200_BLEND_GL_SRC_ALPHA_SATURATE : R200_BLEND_GL_ZERO;
172 case GL_CONSTANT_COLOR:
173 func = R200_BLEND_GL_CONST_COLOR;
175 case GL_ONE_MINUS_CONSTANT_COLOR:
176 func = R200_BLEND_GL_ONE_MINUS_CONST_COLOR;
178 case GL_CONSTANT_ALPHA:
179 func = R200_BLEND_GL_CONST_ALPHA;
181 case GL_ONE_MINUS_CONSTANT_ALPHA:
182 func = R200_BLEND_GL_ONE_MINUS_CONST_ALPHA;
185 func = (is_src) ? R200_BLEND_GL_ONE : R200_BLEND_GL_ZERO;
191 * Sets both the blend equation and the blend function.
192 * This is done in a single
193 * function because some blend equations (i.e., \c GL_MIN and \c GL_MAX)
194 * change the interpretation of the blend function.
195 * Also, make sure that blend function and blend equation are set to their default
196 * value if color blending is not enabled, since at least blend equations GL_MIN
197 * and GL_FUNC_REVERSE_SUBTRACT will cause wrong results otherwise for
200 static void r200_set_blend_state( GLcontext * ctx )
202 r200ContextPtr rmesa = R200_CONTEXT(ctx);
203 GLuint cntl = rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &
204 ~(R200_ROP_ENABLE | R200_ALPHA_BLEND_ENABLE | R200_SEPARATE_ALPHA_ENABLE);
206 int func = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
207 (R200_BLEND_GL_ZERO << R200_DST_BLEND_SHIFT);
208 int eqn = R200_COMB_FCN_ADD_CLAMP;
209 int funcA = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
210 (R200_BLEND_GL_ZERO << R200_DST_BLEND_SHIFT);
211 int eqnA = R200_COMB_FCN_ADD_CLAMP;
213 R200_STATECHANGE( rmesa, ctx );
215 if (rmesa->r200Screen->drmSupportsBlendColor) {
216 if (ctx->Color._LogicOpEnabled) {
217 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl | R200_ROP_ENABLE;
218 rmesa->hw.ctx.cmd[CTX_RB3D_ABLENDCNTL] = eqn | func;
219 rmesa->hw.ctx.cmd[CTX_RB3D_CBLENDCNTL] = eqn | func;
221 } else if (ctx->Color.BlendEnabled) {
222 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl | R200_ALPHA_BLEND_ENABLE | R200_SEPARATE_ALPHA_ENABLE;
225 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl;
226 rmesa->hw.ctx.cmd[CTX_RB3D_ABLENDCNTL] = eqn | func;
227 rmesa->hw.ctx.cmd[CTX_RB3D_CBLENDCNTL] = eqn | func;
232 if (ctx->Color._LogicOpEnabled) {
233 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl | R200_ROP_ENABLE;
234 rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = eqn | func;
236 } else if (ctx->Color.BlendEnabled) {
237 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl | R200_ALPHA_BLEND_ENABLE;
240 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl;
241 rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = eqn | func;
246 func = (blend_factor( ctx->Color.BlendSrcRGB, GL_TRUE ) << R200_SRC_BLEND_SHIFT) |
247 (blend_factor( ctx->Color.BlendDstRGB, GL_FALSE ) << R200_DST_BLEND_SHIFT);
249 switch(ctx->Color.BlendEquationRGB) {
251 eqn = R200_COMB_FCN_ADD_CLAMP;
254 case GL_FUNC_SUBTRACT:
255 eqn = R200_COMB_FCN_SUB_CLAMP;
258 case GL_FUNC_REVERSE_SUBTRACT:
259 eqn = R200_COMB_FCN_RSUB_CLAMP;
263 eqn = R200_COMB_FCN_MIN;
264 func = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
265 (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT);
269 eqn = R200_COMB_FCN_MAX;
270 func = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
271 (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT);
275 fprintf( stderr, "[%s:%u] Invalid RGB blend equation (0x%04x).\n",
276 __func__, __LINE__, ctx->Color.BlendEquationRGB );
280 if (!rmesa->r200Screen->drmSupportsBlendColor) {
281 rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = eqn | func;
285 funcA = (blend_factor( ctx->Color.BlendSrcA, GL_TRUE ) << R200_SRC_BLEND_SHIFT) |
286 (blend_factor( ctx->Color.BlendDstA, GL_FALSE ) << R200_DST_BLEND_SHIFT);
288 switch(ctx->Color.BlendEquationA) {
290 eqnA = R200_COMB_FCN_ADD_CLAMP;
293 case GL_FUNC_SUBTRACT:
294 eqnA = R200_COMB_FCN_SUB_CLAMP;
297 case GL_FUNC_REVERSE_SUBTRACT:
298 eqnA = R200_COMB_FCN_RSUB_CLAMP;
302 eqnA = R200_COMB_FCN_MIN;
303 funcA = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
304 (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT);
308 eqnA = R200_COMB_FCN_MAX;
309 funcA = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
310 (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT);
314 fprintf( stderr, "[%s:%u] Invalid A blend equation (0x%04x).\n",
315 __func__, __LINE__, ctx->Color.BlendEquationA );
319 rmesa->hw.ctx.cmd[CTX_RB3D_ABLENDCNTL] = eqnA | funcA;
320 rmesa->hw.ctx.cmd[CTX_RB3D_CBLENDCNTL] = eqn | func;
324 static void r200BlendEquationSeparate( GLcontext *ctx,
325 GLenum modeRGB, GLenum modeA )
327 r200_set_blend_state( ctx );
330 static void r200BlendFuncSeparate( GLcontext *ctx,
331 GLenum sfactorRGB, GLenum dfactorRGB,
332 GLenum sfactorA, GLenum dfactorA )
334 r200_set_blend_state( ctx );
338 /* =============================================================
342 static void r200DepthFunc( GLcontext *ctx, GLenum func )
344 r200ContextPtr rmesa = R200_CONTEXT(ctx);
346 R200_STATECHANGE( rmesa, ctx );
347 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_Z_TEST_MASK;
349 switch ( ctx->Depth.Func ) {
351 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_NEVER;
354 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_LESS;
357 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_EQUAL;
360 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_LEQUAL;
363 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_GREATER;
366 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_NEQUAL;
369 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_GEQUAL;
372 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_ALWAYS;
378 static void r200DepthMask( GLcontext *ctx, GLboolean flag )
380 r200ContextPtr rmesa = R200_CONTEXT(ctx);
381 R200_STATECHANGE( rmesa, ctx );
383 if ( ctx->Depth.Mask ) {
384 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_WRITE_ENABLE;
386 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_Z_WRITE_ENABLE;
391 /* =============================================================
396 static void r200Fogfv( GLcontext *ctx, GLenum pname, const GLfloat *param )
398 r200ContextPtr rmesa = R200_CONTEXT(ctx);
399 union { int i; float f; } c, d;
403 c.i = rmesa->hw.fog.cmd[FOG_C];
404 d.i = rmesa->hw.fog.cmd[FOG_D];
408 if (!ctx->Fog.Enabled)
410 R200_STATECHANGE(rmesa, tcl);
411 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_TCL_FOG_MASK;
412 switch (ctx->Fog.Mode) {
414 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_TCL_FOG_LINEAR;
415 if (ctx->Fog.Start == ctx->Fog.End) {
420 c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start);
421 d.f = -1.0/(ctx->Fog.End-ctx->Fog.Start);
425 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_TCL_FOG_EXP;
427 d.f = -ctx->Fog.Density;
430 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_TCL_FOG_EXP2;
432 d.f = -(ctx->Fog.Density * ctx->Fog.Density);
439 switch (ctx->Fog.Mode) {
442 d.f = -ctx->Fog.Density;
446 d.f = -(ctx->Fog.Density * ctx->Fog.Density);
454 if (ctx->Fog.Mode == GL_LINEAR) {
455 if (ctx->Fog.Start == ctx->Fog.End) {
459 c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start);
460 d.f = -1.0/(ctx->Fog.End-ctx->Fog.Start);
465 R200_STATECHANGE( rmesa, ctx );
466 UNCLAMPED_FLOAT_TO_RGB_CHAN( col, ctx->Fog.Color );
467 i = r200PackColor( 4, col[0], col[1], col[2], 0 );
468 rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] &= ~R200_FOG_COLOR_MASK;
469 rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] |= i;
471 case GL_FOG_COORD_SRC: {
472 GLuint fmt_0 = rmesa->hw.vtx.cmd[VTX_VTXFMT_0];
473 GLuint out_0 = rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0];
474 GLuint fog = rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR];
476 fog &= ~R200_FOG_USE_MASK;
477 if ( ctx->Fog.FogCoordinateSource == GL_FOG_COORD ) {
478 fog |= R200_FOG_USE_VTX_FOG;
479 fmt_0 |= R200_VTX_DISCRETE_FOG;
480 out_0 |= R200_VTX_DISCRETE_FOG;
483 fog |= R200_FOG_USE_SPEC_ALPHA;
484 fmt_0 &= ~R200_VTX_DISCRETE_FOG;
485 out_0 &= ~R200_VTX_DISCRETE_FOG;
488 if ( fog != rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] ) {
489 R200_STATECHANGE( rmesa, ctx );
490 rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] = fog;
493 if ( (fmt_0 != rmesa->hw.vtx.cmd[VTX_VTXFMT_0])
494 || (out_0 != rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0])) {
495 R200_STATECHANGE( rmesa, vtx );
496 rmesa->hw.vtx.cmd[VTX_VTXFMT_0] = fmt_0;
497 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] = out_0;
506 if (c.i != rmesa->hw.fog.cmd[FOG_C] || d.i != rmesa->hw.fog.cmd[FOG_D]) {
507 R200_STATECHANGE( rmesa, fog );
508 rmesa->hw.fog.cmd[FOG_C] = c.i;
509 rmesa->hw.fog.cmd[FOG_D] = d.i;
514 /* =============================================================
519 static GLboolean intersect_rect( drm_clip_rect_t *out,
524 if ( b->x1 > out->x1 ) out->x1 = b->x1;
525 if ( b->y1 > out->y1 ) out->y1 = b->y1;
526 if ( b->x2 < out->x2 ) out->x2 = b->x2;
527 if ( b->y2 < out->y2 ) out->y2 = b->y2;
528 if ( out->x1 >= out->x2 ) return GL_FALSE;
529 if ( out->y1 >= out->y2 ) return GL_FALSE;
534 void r200RecalcScissorRects( r200ContextPtr rmesa )
536 drm_clip_rect_t *out;
539 /* Grow cliprect store?
541 if (rmesa->state.scissor.numAllocedClipRects < rmesa->numClipRects) {
542 while (rmesa->state.scissor.numAllocedClipRects < rmesa->numClipRects) {
543 rmesa->state.scissor.numAllocedClipRects += 1; /* zero case */
544 rmesa->state.scissor.numAllocedClipRects *= 2;
547 if (rmesa->state.scissor.pClipRects)
548 FREE(rmesa->state.scissor.pClipRects);
550 rmesa->state.scissor.pClipRects =
551 MALLOC( rmesa->state.scissor.numAllocedClipRects *
552 sizeof(drm_clip_rect_t) );
554 if ( rmesa->state.scissor.pClipRects == NULL ) {
555 rmesa->state.scissor.numAllocedClipRects = 0;
560 out = rmesa->state.scissor.pClipRects;
561 rmesa->state.scissor.numClipRects = 0;
563 for ( i = 0 ; i < rmesa->numClipRects ; i++ ) {
564 if ( intersect_rect( out,
565 &rmesa->pClipRects[i],
566 &rmesa->state.scissor.rect ) ) {
567 rmesa->state.scissor.numClipRects++;
574 static void r200UpdateScissor( GLcontext *ctx )
576 r200ContextPtr rmesa = R200_CONTEXT(ctx);
578 if ( rmesa->dri.drawable ) {
579 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
581 int x = ctx->Scissor.X;
582 int y = dPriv->h - ctx->Scissor.Y - ctx->Scissor.Height;
583 int w = ctx->Scissor.X + ctx->Scissor.Width - 1;
584 int h = dPriv->h - ctx->Scissor.Y - 1;
586 rmesa->state.scissor.rect.x1 = x + dPriv->x;
587 rmesa->state.scissor.rect.y1 = y + dPriv->y;
588 rmesa->state.scissor.rect.x2 = w + dPriv->x + 1;
589 rmesa->state.scissor.rect.y2 = h + dPriv->y + 1;
591 r200RecalcScissorRects( rmesa );
596 static void r200Scissor( GLcontext *ctx,
597 GLint x, GLint y, GLsizei w, GLsizei h )
599 r200ContextPtr rmesa = R200_CONTEXT(ctx);
601 if ( ctx->Scissor.Enabled ) {
602 R200_FIREVERTICES( rmesa ); /* don't pipeline cliprect changes */
603 r200UpdateScissor( ctx );
609 /* =============================================================
613 static void r200CullFace( GLcontext *ctx, GLenum unused )
615 r200ContextPtr rmesa = R200_CONTEXT(ctx);
616 GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL];
617 GLuint t = rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL];
619 s |= R200_FFACE_SOLID | R200_BFACE_SOLID;
620 t &= ~(R200_CULL_FRONT | R200_CULL_BACK);
622 if ( ctx->Polygon.CullFlag ) {
623 switch ( ctx->Polygon.CullFaceMode ) {
625 s &= ~R200_FFACE_SOLID;
626 t |= R200_CULL_FRONT;
629 s &= ~R200_BFACE_SOLID;
632 case GL_FRONT_AND_BACK:
633 s &= ~(R200_FFACE_SOLID | R200_BFACE_SOLID);
634 t |= (R200_CULL_FRONT | R200_CULL_BACK);
639 if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) {
640 R200_STATECHANGE(rmesa, set );
641 rmesa->hw.set.cmd[SET_SE_CNTL] = s;
644 if ( rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] != t ) {
645 R200_STATECHANGE(rmesa, tcl );
646 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] = t;
650 static void r200FrontFace( GLcontext *ctx, GLenum mode )
652 r200ContextPtr rmesa = R200_CONTEXT(ctx);
654 R200_STATECHANGE( rmesa, set );
655 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_FFACE_CULL_DIR_MASK;
657 R200_STATECHANGE( rmesa, tcl );
658 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_CULL_FRONT_IS_CCW;
662 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_FFACE_CULL_CW;
665 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_FFACE_CULL_CCW;
666 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_CULL_FRONT_IS_CCW;
671 /* =============================================================
674 static void r200PointSize( GLcontext *ctx, GLfloat size )
676 if (0) fprintf(stderr, "%s: %f\n", __FUNCTION__, size );
679 /* =============================================================
682 static void r200LineWidth( GLcontext *ctx, GLfloat widthf )
684 r200ContextPtr rmesa = R200_CONTEXT(ctx);
686 R200_STATECHANGE( rmesa, lin );
687 R200_STATECHANGE( rmesa, set );
689 /* Line width is stored in U6.4 format.
691 rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] &= ~0xffff;
692 rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] |= (GLuint)(ctx->Line._Width * 16.0);
694 if ( widthf > 1.0 ) {
695 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_WIDELINE_ENABLE;
697 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_WIDELINE_ENABLE;
701 static void r200LineStipple( GLcontext *ctx, GLint factor, GLushort pattern )
703 r200ContextPtr rmesa = R200_CONTEXT(ctx);
705 R200_STATECHANGE( rmesa, lin );
706 rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] =
707 ((((GLuint)factor & 0xff) << 16) | ((GLuint)pattern));
711 /* =============================================================
714 static void r200ColorMask( GLcontext *ctx,
715 GLboolean r, GLboolean g,
716 GLboolean b, GLboolean a )
718 r200ContextPtr rmesa = R200_CONTEXT(ctx);
719 GLuint mask = r200PackColor( rmesa->r200Screen->cpp,
720 ctx->Color.ColorMask[RCOMP],
721 ctx->Color.ColorMask[GCOMP],
722 ctx->Color.ColorMask[BCOMP],
723 ctx->Color.ColorMask[ACOMP] );
725 GLuint flag = rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] & ~R200_PLANE_MASK_ENABLE;
727 if (!(r && g && b && a))
728 flag |= R200_PLANE_MASK_ENABLE;
730 if ( rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] != flag ) {
731 R200_STATECHANGE( rmesa, ctx );
732 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = flag;
735 if ( rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] != mask ) {
736 R200_STATECHANGE( rmesa, msk );
737 rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] = mask;
742 /* =============================================================
746 static void r200PolygonOffset( GLcontext *ctx,
747 GLfloat factor, GLfloat units )
749 r200ContextPtr rmesa = R200_CONTEXT(ctx);
750 GLfloat constant = units * rmesa->state.depth.scale;
755 /* fprintf(stderr, "%s f:%f u:%f\n", __FUNCTION__, factor, constant); */
757 R200_STATECHANGE( rmesa, zbs );
758 rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_FACTOR] = *(GLuint *)&factor;
759 rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_CONSTANT] = *(GLuint *)&constant;
762 static void r200PolygonStipple( GLcontext *ctx, const GLubyte *mask )
764 r200ContextPtr rmesa = R200_CONTEXT(ctx);
766 drm_radeon_stipple_t stipple;
768 /* Must flip pattern upside down.
770 for ( i = 0 ; i < 32 ; i++ ) {
771 rmesa->state.stipple.mask[31 - i] = ((GLuint *) mask)[i];
774 /* TODO: push this into cmd mechanism
776 R200_FIREVERTICES( rmesa );
777 LOCK_HARDWARE( rmesa );
779 /* FIXME: Use window x,y offsets into stipple RAM.
781 stipple.mask = rmesa->state.stipple.mask;
782 drmCommandWrite( rmesa->dri.fd, DRM_RADEON_STIPPLE,
783 &stipple, sizeof(stipple) );
784 UNLOCK_HARDWARE( rmesa );
787 static void r200PolygonMode( GLcontext *ctx, GLenum face, GLenum mode )
789 r200ContextPtr rmesa = R200_CONTEXT(ctx);
790 GLboolean flag = (ctx->_TriangleCaps & DD_TRI_UNFILLED) != 0;
792 /* Can't generally do unfilled via tcl, but some good special
795 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_UNFILLED, flag);
796 if (rmesa->TclFallback) {
797 r200ChooseRenderState( ctx );
798 r200ChooseVertexState( ctx );
803 /* =============================================================
804 * Rendering attributes
806 * We really don't want to recalculate all this every time we bind a
807 * texture. These things shouldn't change all that often, so it makes
808 * sense to break them out of the core texture state update routines.
811 /* Examine lighting and texture state to determine if separate specular
814 static void r200UpdateSpecular( GLcontext *ctx )
816 r200ContextPtr rmesa = R200_CONTEXT(ctx);
817 uint32_t p = rmesa->hw.ctx.cmd[CTX_PP_CNTL];
819 R200_STATECHANGE( rmesa, tcl );
820 R200_STATECHANGE( rmesa, vtx );
822 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] &= ~(3<<R200_VTX_COLOR_0_SHIFT);
823 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] &= ~(3<<R200_VTX_COLOR_1_SHIFT);
824 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] &= ~R200_OUTPUT_COLOR_0;
825 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] &= ~R200_OUTPUT_COLOR_1;
826 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_LIGHTING_ENABLE;
828 p &= ~R200_SPECULAR_ENABLE;
830 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_DIFFUSE_SPECULAR_COMBINE;
833 if (ctx->Light.Enabled &&
834 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) {
835 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
836 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT) |
837 (R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT));
838 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_0;
839 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_1;
840 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHTING_ENABLE;
841 p |= R200_SPECULAR_ENABLE;
842 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &=
843 ~R200_DIFFUSE_SPECULAR_COMBINE;
845 else if (ctx->Light.Enabled) {
846 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
847 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT));
848 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_0;
849 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHTING_ENABLE;
850 } else if (ctx->Fog.ColorSumEnabled ) {
851 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
852 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT) |
853 (R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT));
854 p |= R200_SPECULAR_ENABLE;
856 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
857 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT));
860 if (ctx->Fog.Enabled) {
861 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
862 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT));
863 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_1;
866 if ( rmesa->hw.ctx.cmd[CTX_PP_CNTL] != p ) {
867 R200_STATECHANGE( rmesa, ctx );
868 rmesa->hw.ctx.cmd[CTX_PP_CNTL] = p;
871 /* Update vertex/render formats
873 if (rmesa->TclFallback) {
874 r200ChooseRenderState( ctx );
875 r200ChooseVertexState( ctx );
880 /* =============================================================
885 /* Update on colormaterial, material emmissive/ambient,
886 * lightmodel.globalambient
888 static void update_global_ambient( GLcontext *ctx )
890 r200ContextPtr rmesa = R200_CONTEXT(ctx);
891 float *fcmd = (float *)R200_DB_STATE( glt );
893 /* Need to do more if both emmissive & ambient are PREMULT:
894 * I believe this is not nessary when using source_material. This condition thus
895 * will never happen currently, and the function has no dependencies on materials now
897 if ((rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1] &
898 ((3 << R200_FRONT_EMISSIVE_SOURCE_SHIFT) |
899 (3 << R200_FRONT_AMBIENT_SOURCE_SHIFT))) == 0)
901 COPY_3V( &fcmd[GLT_RED],
902 ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION]);
903 ACC_SCALE_3V( &fcmd[GLT_RED],
904 ctx->Light.Model.Ambient,
905 ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT]);
909 COPY_3V( &fcmd[GLT_RED], ctx->Light.Model.Ambient );
912 R200_DB_STATECHANGE(rmesa, &rmesa->hw.glt);
915 /* Update on change to
919 static void update_light_colors( GLcontext *ctx, GLuint p )
921 struct gl_light *l = &ctx->Light.Light[p];
923 /* fprintf(stderr, "%s\n", __FUNCTION__); */
926 r200ContextPtr rmesa = R200_CONTEXT(ctx);
927 float *fcmd = (float *)R200_DB_STATE( lit[p] );
929 COPY_4V( &fcmd[LIT_AMBIENT_RED], l->Ambient );
930 COPY_4V( &fcmd[LIT_DIFFUSE_RED], l->Diffuse );
931 COPY_4V( &fcmd[LIT_SPECULAR_RED], l->Specular );
933 R200_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
937 static void r200ColorMaterial( GLcontext *ctx, GLenum face, GLenum mode )
939 r200ContextPtr rmesa = R200_CONTEXT(ctx);
940 GLuint light_model_ctl1 = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1];
941 light_model_ctl1 &= ~((0xf << R200_FRONT_EMISSIVE_SOURCE_SHIFT) |
942 (0xf << R200_FRONT_AMBIENT_SOURCE_SHIFT) |
943 (0xf << R200_FRONT_DIFFUSE_SOURCE_SHIFT) |
944 (0xf << R200_FRONT_SPECULAR_SOURCE_SHIFT) |
945 (0xf << R200_BACK_EMISSIVE_SOURCE_SHIFT) |
946 (0xf << R200_BACK_AMBIENT_SOURCE_SHIFT) |
947 (0xf << R200_BACK_DIFFUSE_SOURCE_SHIFT) |
948 (0xf << R200_BACK_SPECULAR_SOURCE_SHIFT));
950 if (ctx->Light.ColorMaterialEnabled) {
951 GLuint mask = ctx->Light.ColorMaterialBitmask;
953 if (mask & MAT_BIT_FRONT_EMISSION) {
954 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
955 R200_FRONT_EMISSIVE_SOURCE_SHIFT);
958 light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 <<
959 R200_FRONT_EMISSIVE_SOURCE_SHIFT);
961 if (mask & MAT_BIT_FRONT_AMBIENT) {
962 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
963 R200_FRONT_AMBIENT_SOURCE_SHIFT);
966 light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 <<
967 R200_FRONT_AMBIENT_SOURCE_SHIFT);
969 if (mask & MAT_BIT_FRONT_DIFFUSE) {
970 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
971 R200_FRONT_DIFFUSE_SOURCE_SHIFT);
974 light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 <<
975 R200_FRONT_DIFFUSE_SOURCE_SHIFT);
977 if (mask & MAT_BIT_FRONT_SPECULAR) {
978 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
979 R200_FRONT_SPECULAR_SOURCE_SHIFT);
982 light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 <<
983 R200_FRONT_SPECULAR_SOURCE_SHIFT);
986 if (mask & MAT_BIT_BACK_EMISSION) {
987 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
988 R200_BACK_EMISSIVE_SOURCE_SHIFT);
991 else light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 <<
992 R200_BACK_EMISSIVE_SOURCE_SHIFT);
994 if (mask & MAT_BIT_BACK_AMBIENT) {
995 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
996 R200_BACK_AMBIENT_SOURCE_SHIFT);
998 else light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 <<
999 R200_BACK_AMBIENT_SOURCE_SHIFT);
1001 if (mask & MAT_BIT_BACK_DIFFUSE) {
1002 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
1003 R200_BACK_DIFFUSE_SOURCE_SHIFT);
1005 else light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 <<
1006 R200_BACK_DIFFUSE_SOURCE_SHIFT);
1008 if (mask & MAT_BIT_BACK_SPECULAR) {
1009 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
1010 R200_BACK_SPECULAR_SOURCE_SHIFT);
1013 light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 <<
1014 R200_BACK_SPECULAR_SOURCE_SHIFT);
1018 /* Default to SOURCE_MATERIAL:
1021 (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_EMISSIVE_SOURCE_SHIFT) |
1022 (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_AMBIENT_SOURCE_SHIFT) |
1023 (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_DIFFUSE_SOURCE_SHIFT) |
1024 (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_SPECULAR_SOURCE_SHIFT) |
1025 (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_EMISSIVE_SOURCE_SHIFT) |
1026 (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_AMBIENT_SOURCE_SHIFT) |
1027 (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_DIFFUSE_SOURCE_SHIFT) |
1028 (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_SPECULAR_SOURCE_SHIFT);
1031 if (light_model_ctl1 != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1]) {
1032 R200_STATECHANGE( rmesa, tcl );
1033 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1] = light_model_ctl1;
1039 void r200UpdateMaterial( GLcontext *ctx )
1041 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1042 GLfloat (*mat)[4] = ctx->Light.Material.Attrib;
1043 GLfloat *fcmd = (GLfloat *)R200_DB_STATE( mtl[0] );
1044 GLfloat *fcmd2 = (GLfloat *)R200_DB_STATE( mtl[1] );
1047 /* Might be possible and faster to update everything unconditionally? */
1048 if (ctx->Light.ColorMaterialEnabled)
1049 mask &= ~ctx->Light.ColorMaterialBitmask;
1051 if (R200_DEBUG & DEBUG_STATE)
1052 fprintf(stderr, "%s\n", __FUNCTION__);
1054 if (mask & MAT_BIT_FRONT_EMISSION) {
1055 fcmd[MTL_EMMISSIVE_RED] = mat[MAT_ATTRIB_FRONT_EMISSION][0];
1056 fcmd[MTL_EMMISSIVE_GREEN] = mat[MAT_ATTRIB_FRONT_EMISSION][1];
1057 fcmd[MTL_EMMISSIVE_BLUE] = mat[MAT_ATTRIB_FRONT_EMISSION][2];
1058 fcmd[MTL_EMMISSIVE_ALPHA] = mat[MAT_ATTRIB_FRONT_EMISSION][3];
1060 if (mask & MAT_BIT_FRONT_AMBIENT) {
1061 fcmd[MTL_AMBIENT_RED] = mat[MAT_ATTRIB_FRONT_AMBIENT][0];
1062 fcmd[MTL_AMBIENT_GREEN] = mat[MAT_ATTRIB_FRONT_AMBIENT][1];
1063 fcmd[MTL_AMBIENT_BLUE] = mat[MAT_ATTRIB_FRONT_AMBIENT][2];
1064 fcmd[MTL_AMBIENT_ALPHA] = mat[MAT_ATTRIB_FRONT_AMBIENT][3];
1066 if (mask & MAT_BIT_FRONT_DIFFUSE) {
1067 fcmd[MTL_DIFFUSE_RED] = mat[MAT_ATTRIB_FRONT_DIFFUSE][0];
1068 fcmd[MTL_DIFFUSE_GREEN] = mat[MAT_ATTRIB_FRONT_DIFFUSE][1];
1069 fcmd[MTL_DIFFUSE_BLUE] = mat[MAT_ATTRIB_FRONT_DIFFUSE][2];
1070 fcmd[MTL_DIFFUSE_ALPHA] = mat[MAT_ATTRIB_FRONT_DIFFUSE][3];
1072 if (mask & MAT_BIT_FRONT_SPECULAR) {
1073 fcmd[MTL_SPECULAR_RED] = mat[MAT_ATTRIB_FRONT_SPECULAR][0];
1074 fcmd[MTL_SPECULAR_GREEN] = mat[MAT_ATTRIB_FRONT_SPECULAR][1];
1075 fcmd[MTL_SPECULAR_BLUE] = mat[MAT_ATTRIB_FRONT_SPECULAR][2];
1076 fcmd[MTL_SPECULAR_ALPHA] = mat[MAT_ATTRIB_FRONT_SPECULAR][3];
1078 if (mask & MAT_BIT_FRONT_SHININESS) {
1079 fcmd[MTL_SHININESS] = mat[MAT_ATTRIB_FRONT_SHININESS][0];
1082 if (mask & MAT_BIT_BACK_EMISSION) {
1083 fcmd2[MTL_EMMISSIVE_RED] = mat[MAT_ATTRIB_BACK_EMISSION][0];
1084 fcmd2[MTL_EMMISSIVE_GREEN] = mat[MAT_ATTRIB_BACK_EMISSION][1];
1085 fcmd2[MTL_EMMISSIVE_BLUE] = mat[MAT_ATTRIB_BACK_EMISSION][2];
1086 fcmd2[MTL_EMMISSIVE_ALPHA] = mat[MAT_ATTRIB_BACK_EMISSION][3];
1088 if (mask & MAT_BIT_BACK_AMBIENT) {
1089 fcmd2[MTL_AMBIENT_RED] = mat[MAT_ATTRIB_BACK_AMBIENT][0];
1090 fcmd2[MTL_AMBIENT_GREEN] = mat[MAT_ATTRIB_BACK_AMBIENT][1];
1091 fcmd2[MTL_AMBIENT_BLUE] = mat[MAT_ATTRIB_BACK_AMBIENT][2];
1092 fcmd2[MTL_AMBIENT_ALPHA] = mat[MAT_ATTRIB_BACK_AMBIENT][3];
1094 if (mask & MAT_BIT_BACK_DIFFUSE) {
1095 fcmd2[MTL_DIFFUSE_RED] = mat[MAT_ATTRIB_BACK_DIFFUSE][0];
1096 fcmd2[MTL_DIFFUSE_GREEN] = mat[MAT_ATTRIB_BACK_DIFFUSE][1];
1097 fcmd2[MTL_DIFFUSE_BLUE] = mat[MAT_ATTRIB_BACK_DIFFUSE][2];
1098 fcmd2[MTL_DIFFUSE_ALPHA] = mat[MAT_ATTRIB_BACK_DIFFUSE][3];
1100 if (mask & MAT_BIT_BACK_SPECULAR) {
1101 fcmd2[MTL_SPECULAR_RED] = mat[MAT_ATTRIB_BACK_SPECULAR][0];
1102 fcmd2[MTL_SPECULAR_GREEN] = mat[MAT_ATTRIB_BACK_SPECULAR][1];
1103 fcmd2[MTL_SPECULAR_BLUE] = mat[MAT_ATTRIB_BACK_SPECULAR][2];
1104 fcmd2[MTL_SPECULAR_ALPHA] = mat[MAT_ATTRIB_BACK_SPECULAR][3];
1106 if (mask & MAT_BIT_BACK_SHININESS) {
1107 fcmd2[MTL_SHININESS] = mat[MAT_ATTRIB_BACK_SHININESS][0];
1110 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mtl[0] );
1111 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mtl[1] );
1113 /* currently material changes cannot trigger a global ambient change, I believe this is correct
1114 update_global_ambient( ctx ); */
1119 * _MESA_NEW_NEED_EYE_COORDS
1121 * Uses derived state from mesa:
1126 * _ModelViewInvScale
1130 * which are calculated in light.c and are correct for the current
1131 * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
1132 * and _MESA_NEW_NEED_EYE_COORDS.
1134 static void update_light( GLcontext *ctx )
1136 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1138 /* Have to check these, or have an automatic shortcircuit mechanism
1139 * to remove noop statechanges. (Or just do a better job on the
1143 GLuint tmp = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0];
1145 if (ctx->_NeedEyeCoords)
1146 tmp &= ~R200_LIGHT_IN_MODELSPACE;
1148 tmp |= R200_LIGHT_IN_MODELSPACE;
1150 if (tmp != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0])
1152 R200_STATECHANGE( rmesa, tcl );
1153 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] = tmp;
1158 GLfloat *fcmd = (GLfloat *)R200_DB_STATE( eye );
1159 fcmd[EYE_X] = ctx->_EyeZDir[0];
1160 fcmd[EYE_Y] = ctx->_EyeZDir[1];
1161 fcmd[EYE_Z] = - ctx->_EyeZDir[2];
1162 fcmd[EYE_RESCALE_FACTOR] = ctx->_ModelViewInvScale;
1163 R200_DB_STATECHANGE( rmesa, &rmesa->hw.eye );
1168 if (ctx->Light.Enabled) {
1170 for (p = 0 ; p < MAX_LIGHTS; p++) {
1171 if (ctx->Light.Light[p].Enabled) {
1172 struct gl_light *l = &ctx->Light.Light[p];
1173 GLfloat *fcmd = (GLfloat *)R200_DB_STATE( lit[p] );
1175 if (l->EyePosition[3] == 0.0) {
1176 COPY_3FV( &fcmd[LIT_POSITION_X], l->_VP_inf_norm );
1177 COPY_3FV( &fcmd[LIT_DIRECTION_X], l->_h_inf_norm );
1178 fcmd[LIT_POSITION_W] = 0;
1179 fcmd[LIT_DIRECTION_W] = 0;
1181 COPY_4V( &fcmd[LIT_POSITION_X], l->_Position );
1182 fcmd[LIT_DIRECTION_X] = -l->_NormDirection[0];
1183 fcmd[LIT_DIRECTION_Y] = -l->_NormDirection[1];
1184 fcmd[LIT_DIRECTION_Z] = -l->_NormDirection[2];
1185 fcmd[LIT_DIRECTION_W] = 0;
1188 R200_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
1194 static void r200Lightfv( GLcontext *ctx, GLenum light,
1195 GLenum pname, const GLfloat *params )
1197 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1198 GLint p = light - GL_LIGHT0;
1199 struct gl_light *l = &ctx->Light.Light[p];
1200 GLfloat *fcmd = (GLfloat *)rmesa->hw.lit[p].cmd;
1207 update_light_colors( ctx, p );
1210 case GL_SPOT_DIRECTION:
1211 /* picked up in update_light */
1215 /* positions picked up in update_light, but can do flag here */
1216 GLuint flag = (p&1)? R200_LIGHT_1_IS_LOCAL : R200_LIGHT_0_IS_LOCAL;
1217 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1219 R200_STATECHANGE(rmesa, tcl);
1220 if (l->EyePosition[3] != 0.0F)
1221 rmesa->hw.tcl.cmd[idx] |= flag;
1223 rmesa->hw.tcl.cmd[idx] &= ~flag;
1227 case GL_SPOT_EXPONENT:
1228 R200_STATECHANGE(rmesa, lit[p]);
1229 fcmd[LIT_SPOT_EXPONENT] = params[0];
1232 case GL_SPOT_CUTOFF: {
1233 GLuint flag = (p&1) ? R200_LIGHT_1_IS_SPOT : R200_LIGHT_0_IS_SPOT;
1234 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1236 R200_STATECHANGE(rmesa, lit[p]);
1237 fcmd[LIT_SPOT_CUTOFF] = l->_CosCutoff;
1239 R200_STATECHANGE(rmesa, tcl);
1240 if (l->SpotCutoff != 180.0F)
1241 rmesa->hw.tcl.cmd[idx] |= flag;
1243 rmesa->hw.tcl.cmd[idx] &= ~flag;
1248 case GL_CONSTANT_ATTENUATION:
1249 R200_STATECHANGE(rmesa, lit[p]);
1250 fcmd[LIT_ATTEN_CONST] = params[0];
1251 if ( params[0] == 0.0 )
1252 fcmd[LIT_ATTEN_CONST_INV] = FLT_MAX;
1254 fcmd[LIT_ATTEN_CONST_INV] = 1.0 / params[0];
1256 case GL_LINEAR_ATTENUATION:
1257 R200_STATECHANGE(rmesa, lit[p]);
1258 fcmd[LIT_ATTEN_LINEAR] = params[0];
1260 case GL_QUADRATIC_ATTENUATION:
1261 R200_STATECHANGE(rmesa, lit[p]);
1262 fcmd[LIT_ATTEN_QUADRATIC] = params[0];
1268 /* Set RANGE_ATTEN only when needed */
1271 case GL_CONSTANT_ATTENUATION:
1272 case GL_LINEAR_ATTENUATION:
1273 case GL_QUADRATIC_ATTENUATION: {
1274 GLuint *icmd = (GLuint *)R200_DB_STATE( tcl );
1275 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1276 GLuint atten_flag = ( p&1 ) ? R200_LIGHT_1_ENABLE_RANGE_ATTEN
1277 : R200_LIGHT_0_ENABLE_RANGE_ATTEN;
1278 GLuint atten_const_flag = ( p&1 ) ? R200_LIGHT_1_CONSTANT_RANGE_ATTEN
1279 : R200_LIGHT_0_CONSTANT_RANGE_ATTEN;
1281 if ( l->EyePosition[3] == 0.0F ||
1282 ( ( fcmd[LIT_ATTEN_CONST] == 0.0 || fcmd[LIT_ATTEN_CONST] == 1.0 ) &&
1283 fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) ) {
1284 /* Disable attenuation */
1285 icmd[idx] &= ~atten_flag;
1287 if ( fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) {
1288 /* Enable only constant portion of attenuation calculation */
1289 icmd[idx] |= ( atten_flag | atten_const_flag );
1291 /* Enable full attenuation calculation */
1292 icmd[idx] &= ~atten_const_flag;
1293 icmd[idx] |= atten_flag;
1297 R200_DB_STATECHANGE( rmesa, &rmesa->hw.tcl );
1308 static void r200LightModelfv( GLcontext *ctx, GLenum pname,
1309 const GLfloat *param )
1311 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1314 case GL_LIGHT_MODEL_AMBIENT:
1315 update_global_ambient( ctx );
1318 case GL_LIGHT_MODEL_LOCAL_VIEWER:
1319 R200_STATECHANGE( rmesa, tcl );
1320 if (ctx->Light.Model.LocalViewer)
1321 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LOCAL_VIEWER;
1323 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_LOCAL_VIEWER;
1326 case GL_LIGHT_MODEL_TWO_SIDE:
1327 R200_STATECHANGE( rmesa, tcl );
1328 if (ctx->Light.Model.TwoSide)
1329 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHT_TWOSIDE;
1331 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~(R200_LIGHT_TWOSIDE);
1332 if (rmesa->TclFallback) {
1333 r200ChooseRenderState( ctx );
1334 r200ChooseVertexState( ctx );
1338 case GL_LIGHT_MODEL_COLOR_CONTROL:
1339 r200UpdateSpecular(ctx);
1347 static void r200ShadeModel( GLcontext *ctx, GLenum mode )
1349 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1350 GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL];
1352 s &= ~(R200_DIFFUSE_SHADE_MASK |
1353 R200_ALPHA_SHADE_MASK |
1354 R200_SPECULAR_SHADE_MASK |
1355 R200_FOG_SHADE_MASK);
1359 s |= (R200_DIFFUSE_SHADE_FLAT |
1360 R200_ALPHA_SHADE_FLAT |
1361 R200_SPECULAR_SHADE_FLAT |
1362 R200_FOG_SHADE_FLAT);
1365 s |= (R200_DIFFUSE_SHADE_GOURAUD |
1366 R200_ALPHA_SHADE_GOURAUD |
1367 R200_SPECULAR_SHADE_GOURAUD |
1368 R200_FOG_SHADE_GOURAUD);
1374 if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) {
1375 R200_STATECHANGE( rmesa, set );
1376 rmesa->hw.set.cmd[SET_SE_CNTL] = s;
1381 /* =============================================================
1385 static void r200ClipPlane( GLcontext *ctx, GLenum plane, const GLfloat *eq )
1387 GLint p = (GLint) plane - (GLint) GL_CLIP_PLANE0;
1388 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1389 GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
1391 R200_STATECHANGE( rmesa, ucp[p] );
1392 rmesa->hw.ucp[p].cmd[UCP_X] = ip[0];
1393 rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1];
1394 rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2];
1395 rmesa->hw.ucp[p].cmd[UCP_W] = ip[3];
1398 static void r200UpdateClipPlanes( GLcontext *ctx )
1400 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1403 for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
1404 if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
1405 GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
1407 R200_STATECHANGE( rmesa, ucp[p] );
1408 rmesa->hw.ucp[p].cmd[UCP_X] = ip[0];
1409 rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1];
1410 rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2];
1411 rmesa->hw.ucp[p].cmd[UCP_W] = ip[3];
1417 /* =============================================================
1421 static void r200StencilFunc( GLcontext *ctx, GLenum func,
1422 GLint ref, GLuint mask )
1424 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1425 GLuint refmask = ((ctx->Stencil.Ref[0] << R200_STENCIL_REF_SHIFT) |
1426 (ctx->Stencil.ValueMask[0] << R200_STENCIL_MASK_SHIFT));
1428 R200_STATECHANGE( rmesa, ctx );
1429 R200_STATECHANGE( rmesa, msk );
1431 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_STENCIL_TEST_MASK;
1432 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~(R200_STENCIL_REF_MASK|
1433 R200_STENCIL_VALUE_MASK);
1435 switch ( ctx->Stencil.Function[0] ) {
1437 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_NEVER;
1440 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_LESS;
1443 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_EQUAL;
1446 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_LEQUAL;
1449 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_GREATER;
1452 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_NEQUAL;
1455 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_GEQUAL;
1458 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_ALWAYS;
1462 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |= refmask;
1465 static void r200StencilMask( GLcontext *ctx, GLuint mask )
1467 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1469 R200_STATECHANGE( rmesa, msk );
1470 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~R200_STENCIL_WRITE_MASK;
1471 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |=
1472 (ctx->Stencil.WriteMask[0] << R200_STENCIL_WRITEMASK_SHIFT);
1475 static void r200StencilOp( GLcontext *ctx, GLenum fail,
1476 GLenum zfail, GLenum zpass )
1478 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1480 R200_STATECHANGE( rmesa, ctx );
1481 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~(R200_STENCIL_FAIL_MASK |
1482 R200_STENCIL_ZFAIL_MASK |
1483 R200_STENCIL_ZPASS_MASK);
1485 switch ( ctx->Stencil.FailFunc[0] ) {
1487 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_KEEP;
1490 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_ZERO;
1493 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_REPLACE;
1496 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INC;
1499 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_DEC;
1501 case GL_INCR_WRAP_EXT:
1502 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INC_WRAP;
1504 case GL_DECR_WRAP_EXT:
1505 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_DEC_WRAP;
1508 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INVERT;
1512 switch ( ctx->Stencil.ZFailFunc[0] ) {
1514 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_KEEP;
1517 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_ZERO;
1520 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_REPLACE;
1523 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INC;
1526 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_DEC;
1528 case GL_INCR_WRAP_EXT:
1529 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INC_WRAP;
1531 case GL_DECR_WRAP_EXT:
1532 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_DEC_WRAP;
1535 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INVERT;
1539 switch ( ctx->Stencil.ZPassFunc[0] ) {
1541 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_KEEP;
1544 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_ZERO;
1547 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_REPLACE;
1550 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INC;
1553 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_DEC;
1555 case GL_INCR_WRAP_EXT:
1556 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INC_WRAP;
1558 case GL_DECR_WRAP_EXT:
1559 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_DEC_WRAP;
1562 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INVERT;
1567 static void r200ClearStencil( GLcontext *ctx, GLint s )
1569 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1571 rmesa->state.stencil.clear =
1572 ((GLuint) ctx->Stencil.Clear |
1573 (0xff << R200_STENCIL_MASK_SHIFT) |
1574 (ctx->Stencil.WriteMask[0] << R200_STENCIL_WRITEMASK_SHIFT));
1578 /* =============================================================
1579 * Window position and viewport transformation
1583 * To correctly position primitives:
1585 #define SUBPIXEL_X 0.125
1586 #define SUBPIXEL_Y 0.125
1588 void r200UpdateWindow( GLcontext *ctx )
1590 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1591 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
1592 GLfloat xoffset = (GLfloat)dPriv->x;
1593 GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h;
1594 const GLfloat *v = ctx->Viewport._WindowMap.m;
1596 GLfloat sx = v[MAT_SX];
1597 GLfloat tx = v[MAT_TX] + xoffset + SUBPIXEL_X;
1598 GLfloat sy = - v[MAT_SY];
1599 GLfloat ty = (- v[MAT_TY]) + yoffset + SUBPIXEL_Y;
1600 GLfloat sz = v[MAT_SZ] * rmesa->state.depth.scale;
1601 GLfloat tz = v[MAT_TZ] * rmesa->state.depth.scale;
1603 R200_FIREVERTICES( rmesa );
1604 R200_STATECHANGE( rmesa, vpt );
1606 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XSCALE] = *(GLuint *)&sx;
1607 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = *(GLuint *)&tx;
1608 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YSCALE] = *(GLuint *)&sy;
1609 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = *(GLuint *)&ty;
1610 rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZSCALE] = *(GLuint *)&sz;
1611 rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZOFFSET] = *(GLuint *)&tz;
1616 static void r200Viewport( GLcontext *ctx, GLint x, GLint y,
1617 GLsizei width, GLsizei height )
1619 /* Don't pipeline viewport changes, conflict with window offset
1620 * setting below. Could apply deltas to rescue pipelined viewport
1621 * values, or keep the originals hanging around.
1623 R200_FIREVERTICES( R200_CONTEXT(ctx) );
1624 r200UpdateWindow( ctx );
1627 static void r200DepthRange( GLcontext *ctx, GLclampd nearval,
1630 r200UpdateWindow( ctx );
1633 void r200UpdateViewportOffset( GLcontext *ctx )
1635 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1636 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
1637 GLfloat xoffset = (GLfloat)dPriv->x;
1638 GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h;
1639 const GLfloat *v = ctx->Viewport._WindowMap.m;
1641 GLfloat tx = v[MAT_TX] + xoffset;
1642 GLfloat ty = (- v[MAT_TY]) + yoffset;
1644 if ( rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] != *(GLuint *)&tx ||
1645 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] != *(GLuint *)&ty )
1647 /* Note: this should also modify whatever data the context reset
1650 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = *(GLuint *)&tx;
1651 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = *(GLuint *)&ty;
1653 /* update polygon stipple x/y screen offset */
1656 GLuint m = rmesa->hw.msc.cmd[MSC_RE_MISC];
1658 m &= ~(R200_STIPPLE_X_OFFSET_MASK |
1659 R200_STIPPLE_Y_OFFSET_MASK);
1661 /* add magic offsets, then invert */
1662 stx = 31 - ((rmesa->dri.drawable->x - 1) & R200_STIPPLE_COORD_MASK);
1663 sty = 31 - ((rmesa->dri.drawable->y + rmesa->dri.drawable->h - 1)
1664 & R200_STIPPLE_COORD_MASK);
1666 m |= ((stx << R200_STIPPLE_X_OFFSET_SHIFT) |
1667 (sty << R200_STIPPLE_Y_OFFSET_SHIFT));
1669 if ( rmesa->hw.msc.cmd[MSC_RE_MISC] != m ) {
1670 R200_STATECHANGE( rmesa, msc );
1671 rmesa->hw.msc.cmd[MSC_RE_MISC] = m;
1676 r200UpdateScissor( ctx );
1681 /* =============================================================
1685 static void r200ClearColor( GLcontext *ctx, const GLfloat c[4] )
1687 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1689 CLAMPED_FLOAT_TO_UBYTE(color[0], c[0]);
1690 CLAMPED_FLOAT_TO_UBYTE(color[1], c[1]);
1691 CLAMPED_FLOAT_TO_UBYTE(color[2], c[2]);
1692 CLAMPED_FLOAT_TO_UBYTE(color[3], c[3]);
1693 rmesa->state.color.clear = r200PackColor( rmesa->r200Screen->cpp,
1695 color[2], color[3] );
1699 static void r200RenderMode( GLcontext *ctx, GLenum mode )
1701 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1702 FALLBACK( rmesa, R200_FALLBACK_RENDER_MODE, (mode != GL_RENDER) );
1706 static GLuint r200_rop_tab[] = {
1709 R200_ROP_AND_REVERSE,
1711 R200_ROP_AND_INVERTED,
1718 R200_ROP_OR_REVERSE,
1719 R200_ROP_COPY_INVERTED,
1720 R200_ROP_OR_INVERTED,
1725 static void r200LogicOpCode( GLcontext *ctx, GLenum opcode )
1727 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1728 GLuint rop = (GLuint)opcode - GL_CLEAR;
1732 R200_STATECHANGE( rmesa, msk );
1733 rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = r200_rop_tab[rop];
1737 void r200SetCliprects( r200ContextPtr rmesa, GLenum mode )
1739 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
1743 rmesa->numClipRects = dPriv->numClipRects;
1744 rmesa->pClipRects = dPriv->pClipRects;
1747 /* Can't ignore 2d windows if we are page flipping.
1749 if ( dPriv->numBackClipRects == 0 || rmesa->doPageFlip ) {
1750 rmesa->numClipRects = dPriv->numClipRects;
1751 rmesa->pClipRects = dPriv->pClipRects;
1754 rmesa->numClipRects = dPriv->numBackClipRects;
1755 rmesa->pClipRects = dPriv->pBackClipRects;
1759 fprintf(stderr, "bad mode in r200SetCliprects\n");
1763 if (rmesa->state.scissor.enabled)
1764 r200RecalcScissorRects( rmesa );
1768 static void r200DrawBuffer( GLcontext *ctx, GLenum mode )
1770 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1772 if (R200_DEBUG & DEBUG_DRI)
1773 fprintf(stderr, "%s %s\n", __FUNCTION__,
1774 _mesa_lookup_enum_by_nr( mode ));
1776 R200_FIREVERTICES(rmesa); /* don't pipeline cliprect changes */
1779 * _DrawDestMask is easier to cope with than <mode>.
1781 switch ( ctx->Color._DrawDestMask[0] ) {
1782 case DD_FRONT_LEFT_BIT:
1783 FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_FALSE );
1784 r200SetCliprects( rmesa, GL_FRONT_LEFT );
1786 case DD_BACK_LEFT_BIT:
1787 FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_FALSE );
1788 r200SetCliprects( rmesa, GL_BACK_LEFT );
1791 /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */
1792 FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_TRUE );
1796 /* We want to update the s/w rast state too so that r200SetBuffer()
1799 _swrast_DrawBuffer(ctx, mode);
1801 R200_STATECHANGE( rmesa, ctx );
1802 rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = ((rmesa->state.color.drawOffset +
1803 rmesa->r200Screen->fbLocation)
1804 & R200_COLOROFFSET_MASK);
1805 rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = rmesa->state.color.drawPitch;
1809 static void r200ReadBuffer( GLcontext *ctx, GLenum mode )
1811 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
1814 /* =============================================================
1815 * State enable/disable
1818 static void r200Enable( GLcontext *ctx, GLenum cap, GLboolean state )
1820 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1823 if ( R200_DEBUG & DEBUG_STATE )
1824 fprintf( stderr, "%s( %s = %s )\n", __FUNCTION__,
1825 _mesa_lookup_enum_by_nr( cap ),
1826 state ? "GL_TRUE" : "GL_FALSE" );
1829 /* Fast track this one...
1837 R200_STATECHANGE( rmesa, ctx );
1839 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ALPHA_TEST_ENABLE;
1841 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ALPHA_TEST_ENABLE;
1846 case GL_COLOR_LOGIC_OP:
1847 r200_set_blend_state( ctx );
1850 case GL_CLIP_PLANE0:
1851 case GL_CLIP_PLANE1:
1852 case GL_CLIP_PLANE2:
1853 case GL_CLIP_PLANE3:
1854 case GL_CLIP_PLANE4:
1855 case GL_CLIP_PLANE5:
1856 p = cap-GL_CLIP_PLANE0;
1857 R200_STATECHANGE( rmesa, tcl );
1859 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (R200_UCP_ENABLE_0<<p);
1860 r200ClipPlane( ctx, cap, NULL );
1863 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0<<p);
1867 case GL_COLOR_MATERIAL:
1868 r200ColorMaterial( ctx, 0, 0 );
1869 r200UpdateMaterial( ctx );
1873 r200CullFace( ctx, 0 );
1877 R200_STATECHANGE(rmesa, ctx );
1879 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_Z_ENABLE;
1881 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_Z_ENABLE;
1886 R200_STATECHANGE(rmesa, ctx );
1888 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_DITHER_ENABLE;
1889 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~rmesa->state.color.roundEnable;
1891 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_DITHER_ENABLE;
1892 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= rmesa->state.color.roundEnable;
1897 R200_STATECHANGE(rmesa, ctx );
1899 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_FOG_ENABLE;
1900 r200Fogfv( ctx, GL_FOG_MODE, 0 );
1902 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_FOG_ENABLE;
1903 R200_STATECHANGE(rmesa, tcl);
1904 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_TCL_FOG_MASK;
1906 r200UpdateSpecular( ctx ); /* for PK_SPEC */
1907 if (rmesa->TclFallback)
1908 r200ChooseVertexState( ctx );
1909 _mesa_allow_light_in_model( ctx, !state );
1920 R200_STATECHANGE(rmesa, tcl);
1921 p = cap - GL_LIGHT0;
1923 flag = (R200_LIGHT_1_ENABLE |
1924 R200_LIGHT_1_ENABLE_AMBIENT |
1925 R200_LIGHT_1_ENABLE_SPECULAR);
1927 flag = (R200_LIGHT_0_ENABLE |
1928 R200_LIGHT_0_ENABLE_AMBIENT |
1929 R200_LIGHT_0_ENABLE_SPECULAR);
1932 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] |= flag;
1934 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] &= ~flag;
1938 update_light_colors( ctx, p );
1942 r200UpdateSpecular(ctx);
1945 case GL_LINE_SMOOTH:
1946 R200_STATECHANGE( rmesa, ctx );
1948 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ANTI_ALIAS_LINE;
1950 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_LINE;
1954 case GL_LINE_STIPPLE:
1955 R200_STATECHANGE( rmesa, set );
1957 rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_PATTERN_ENABLE;
1959 rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_PATTERN_ENABLE;
1964 R200_STATECHANGE( rmesa, tcl );
1966 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_NORMALIZE_NORMALS;
1968 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_NORMALIZE_NORMALS;
1972 /* Pointsize registers on r200 don't seem to do anything. Maybe
1973 * have to pass pointsizes as vertex parameters? In any case,
1974 * setting pointmin == pointsizemax == 1.0, and doing nothing
1975 * for aa is enough to satisfy conform.
1977 case GL_POINT_SMOOTH:
1980 /* These don't really do anything, as we don't use the 3vtx
1984 case GL_POLYGON_OFFSET_POINT:
1985 R200_STATECHANGE( rmesa, set );
1987 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_POINT;
1989 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_POINT;
1993 case GL_POLYGON_OFFSET_LINE:
1994 R200_STATECHANGE( rmesa, set );
1996 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_LINE;
1998 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_LINE;
2003 case GL_POLYGON_OFFSET_FILL:
2004 R200_STATECHANGE( rmesa, set );
2006 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_TRI;
2008 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_TRI;
2012 case GL_POLYGON_SMOOTH:
2013 R200_STATECHANGE( rmesa, ctx );
2015 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ANTI_ALIAS_POLY;
2017 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_POLY;
2021 case GL_POLYGON_STIPPLE:
2022 R200_STATECHANGE(rmesa, set );
2024 rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_STIPPLE_ENABLE;
2026 rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_STIPPLE_ENABLE;
2030 case GL_RESCALE_NORMAL_EXT: {
2031 GLboolean tmp = ctx->_NeedEyeCoords ? state : !state;
2032 R200_STATECHANGE( rmesa, tcl );
2034 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_RESCALE_NORMALS;
2036 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS;
2041 case GL_SCISSOR_TEST:
2042 R200_FIREVERTICES( rmesa );
2043 rmesa->state.scissor.enabled = state;
2044 r200UpdateScissor( ctx );
2047 case GL_STENCIL_TEST:
2048 if ( rmesa->state.stencil.hwBuffer ) {
2049 R200_STATECHANGE( rmesa, ctx );
2051 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_STENCIL_ENABLE;
2053 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_STENCIL_ENABLE;
2056 FALLBACK( rmesa, R200_FALLBACK_STENCIL, state );
2060 case GL_TEXTURE_GEN_Q:
2061 case GL_TEXTURE_GEN_R:
2062 case GL_TEXTURE_GEN_S:
2063 case GL_TEXTURE_GEN_T:
2064 /* Picked up in r200UpdateTextureState.
2066 rmesa->recheck_texgen[ctx->Texture.CurrentUnit] = GL_TRUE;
2069 case GL_COLOR_SUM_EXT:
2070 r200UpdateSpecular ( ctx );
2073 case GL_VERTEX_PROGRAM_ARB:
2074 TCL_FALLBACK(rmesa->glCtx, R200_TCL_FALLBACK_TCL_DISABLE, state);
2083 void r200LightingSpaceChange( GLcontext *ctx )
2085 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2088 if (R200_DEBUG & DEBUG_STATE)
2089 fprintf(stderr, "%s %d BEFORE %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
2090 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]);
2092 if (ctx->_NeedEyeCoords)
2093 tmp = ctx->Transform.RescaleNormals;
2095 tmp = !ctx->Transform.RescaleNormals;
2097 R200_STATECHANGE( rmesa, tcl );
2099 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_RESCALE_NORMALS;
2101 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS;
2104 if (R200_DEBUG & DEBUG_STATE)
2105 fprintf(stderr, "%s %d AFTER %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
2106 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]);
2109 /* =============================================================
2110 * Deferred state management - matrices, textures, other?
2116 static void upload_matrix( r200ContextPtr rmesa, GLfloat *src, int idx )
2118 float *dest = ((float *)R200_DB_STATE( mat[idx] ))+MAT_ELT_0;
2122 for (i = 0 ; i < 4 ; i++) {
2126 *dest++ = src[i+12];
2129 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2132 static void upload_matrix_t( r200ContextPtr rmesa, const GLfloat *src, int idx )
2134 float *dest = ((float *)R200_DB_STATE( mat[idx] ))+MAT_ELT_0;
2135 memcpy(dest, src, 16*sizeof(float));
2136 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2140 static void update_texturematrix( GLcontext *ctx )
2142 r200ContextPtr rmesa = R200_CONTEXT( ctx );
2143 GLuint tpc = rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0];
2144 GLuint compsel = rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL];
2147 if (R200_DEBUG & DEBUG_STATE)
2148 fprintf(stderr, "%s before COMPSEL: %x\n", __FUNCTION__,
2149 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]);
2151 rmesa->TexMatEnabled = 0;
2152 rmesa->TexMatCompSel = 0;
2154 for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++) {
2155 if (!ctx->Texture.Unit[unit]._ReallyEnabled)
2158 if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY) {
2159 rmesa->TexMatEnabled |= (R200_TEXGEN_TEXMAT_0_ENABLE|
2160 R200_TEXMAT_0_ENABLE) << unit;
2162 rmesa->TexMatCompSel |= R200_OUTPUT_TEX_0 << unit;
2164 if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) {
2165 /* Need to preconcatenate any active texgen
2166 * obj/eyeplane matrices:
2168 _math_matrix_mul_matrix( &rmesa->tmpmat,
2169 ctx->TextureMatrixStack[unit].Top,
2170 &rmesa->TexGenMatrix[unit] );
2171 upload_matrix( rmesa, rmesa->tmpmat.m, R200_MTX_TEX0+unit );
2174 upload_matrix( rmesa, ctx->TextureMatrixStack[unit].Top->m,
2175 R200_MTX_TEX0+unit );
2178 else if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) {
2179 upload_matrix( rmesa, rmesa->TexGenMatrix[unit].m,
2180 R200_MTX_TEX0+unit );
2184 tpc = (rmesa->TexMatEnabled | rmesa->TexGenEnabled);
2185 if (tpc != rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0]) {
2186 R200_STATECHANGE(rmesa, tcg);
2187 rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0] = tpc;
2190 compsel &= ~R200_OUTPUT_TEX_MASK;
2191 compsel |= rmesa->TexMatCompSel | rmesa->TexGenCompSel;
2192 if (compsel != rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]) {
2193 R200_STATECHANGE(rmesa, vtx);
2194 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] = compsel;
2200 void r200ValidateState( GLcontext *ctx )
2202 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2203 GLuint new_state = rmesa->NewGLState;
2205 if (new_state & _NEW_TEXTURE) {
2206 r200UpdateTextureState( ctx );
2207 new_state |= rmesa->NewGLState; /* may add TEXTURE_MATRIX */
2210 /* Need an event driven matrix update?
2212 if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION))
2213 upload_matrix( rmesa, ctx->_ModelProjectMatrix.m, R200_MTX_MVP );
2215 /* Need these for lighting (shouldn't upload otherwise)
2217 if (new_state & (_NEW_MODELVIEW)) {
2218 upload_matrix( rmesa, ctx->ModelviewMatrixStack.Top->m, R200_MTX_MV );
2219 upload_matrix_t( rmesa, ctx->ModelviewMatrixStack.Top->inv, R200_MTX_IMV );
2222 /* Does this need to be triggered on eg. modelview for
2223 * texgen-derived objplane/eyeplane matrices?
2225 if (new_state & (_NEW_TEXTURE|_NEW_TEXTURE_MATRIX)) {
2226 update_texturematrix( ctx );
2229 if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW|_MESA_NEW_NEED_EYE_COORDS)) {
2230 update_light( ctx );
2233 /* emit all active clip planes if projection matrix changes.
2235 if (new_state & (_NEW_PROJECTION)) {
2236 if (ctx->Transform.ClipPlanesEnabled)
2237 r200UpdateClipPlanes( ctx );
2241 rmesa->NewGLState = 0;
2245 static void r200InvalidateState( GLcontext *ctx, GLuint new_state )
2247 _swrast_InvalidateState( ctx, new_state );
2248 _swsetup_InvalidateState( ctx, new_state );
2249 _ac_InvalidateState( ctx, new_state );
2250 _tnl_InvalidateState( ctx, new_state );
2251 _ae_invalidate_state( ctx, new_state );
2252 R200_CONTEXT(ctx)->NewGLState |= new_state;
2253 r200VtxfmtInvalidate( ctx );
2256 /* A hack. The r200 can actually cope just fine with materials
2257 * between begin/ends, so fix this. But how ?
2259 static GLboolean check_material( GLcontext *ctx )
2261 TNLcontext *tnl = TNL_CONTEXT(ctx);
2264 for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT;
2265 i < _TNL_ATTRIB_MAT_BACK_INDEXES;
2267 if (tnl->vb.AttribPtr[i] &&
2268 tnl->vb.AttribPtr[i]->stride)
2274 static void r200WrapRunPipeline( GLcontext *ctx )
2276 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2277 GLboolean has_material;
2280 fprintf(stderr, "%s, newstate: %x\n", __FUNCTION__, rmesa->NewGLState);
2284 if (rmesa->NewGLState)
2285 r200ValidateState( ctx );
2287 has_material = (ctx->Light.Enabled && check_material( ctx ));
2290 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_TRUE );
2293 /* Run the pipeline.
2295 _tnl_run_pipeline( ctx );
2298 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_FALSE );
2303 /* Initialize the driver's state functions.
2305 void r200InitStateFuncs( struct dd_function_table *functions )
2307 functions->UpdateState = r200InvalidateState;
2308 functions->LightingSpaceChange = r200LightingSpaceChange;
2310 functions->DrawBuffer = r200DrawBuffer;
2311 functions->ReadBuffer = r200ReadBuffer;
2313 functions->AlphaFunc = r200AlphaFunc;
2314 functions->BlendColor = r200BlendColor;
2315 functions->BlendEquationSeparate = r200BlendEquationSeparate;
2316 functions->BlendFuncSeparate = r200BlendFuncSeparate;
2317 functions->ClearColor = r200ClearColor;
2318 functions->ClearDepth = NULL;
2319 functions->ClearIndex = NULL;
2320 functions->ClearStencil = r200ClearStencil;
2321 functions->ClipPlane = r200ClipPlane;
2322 functions->ColorMask = r200ColorMask;
2323 functions->CullFace = r200CullFace;
2324 functions->DepthFunc = r200DepthFunc;
2325 functions->DepthMask = r200DepthMask;
2326 functions->DepthRange = r200DepthRange;
2327 functions->Enable = r200Enable;
2328 functions->Fogfv = r200Fogfv;
2329 functions->FrontFace = r200FrontFace;
2330 functions->Hint = NULL;
2331 functions->IndexMask = NULL;
2332 functions->LightModelfv = r200LightModelfv;
2333 functions->Lightfv = r200Lightfv;
2334 functions->LineStipple = r200LineStipple;
2335 functions->LineWidth = r200LineWidth;
2336 functions->LogicOpcode = r200LogicOpCode;
2337 functions->PolygonMode = r200PolygonMode;
2338 functions->PolygonOffset = r200PolygonOffset;
2339 functions->PolygonStipple = r200PolygonStipple;
2340 functions->PointSize = r200PointSize;
2341 functions->RenderMode = r200RenderMode;
2342 functions->Scissor = r200Scissor;
2343 functions->ShadeModel = r200ShadeModel;
2344 functions->StencilFunc = r200StencilFunc;
2345 functions->StencilMask = r200StencilMask;
2346 functions->StencilOp = r200StencilOp;
2347 functions->Viewport = r200Viewport;
2349 /* Swrast hooks for imaging extensions:
2351 functions->CopyColorTable = _swrast_CopyColorTable;
2352 functions->CopyColorSubTable = _swrast_CopyColorSubTable;
2353 functions->CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
2354 functions->CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
2358 void r200InitTnlFuncs( GLcontext *ctx )
2360 TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange = r200UpdateMaterial;
2361 TNL_CONTEXT(ctx)->Driver.RunPipeline = r200WrapRunPipeline;