1 /**************************************************************************
3 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
5 The Weather Channel (TM) funded Tungsten Graphics to develop the
6 initial release of the Radeon 8500 driver under the XFree86 license.
7 This notice must be preserved.
9 Permission is hereby granted, free of charge, to any person obtaining
10 a copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sublicense, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial
19 portions of the Software.
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
25 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 **************************************************************************/
33 * Keith Whitwell <keith@tungstengraphics.com>
36 #include "main/glheader.h"
37 #include "main/imports.h"
38 #include "main/api_arrayelt.h"
39 #include "main/enums.h"
40 #include "main/colormac.h"
41 #include "main/light.h"
42 #include "main/framebuffer.h"
43 #include "main/fbobject.h"
44 #include "main/stencil.h"
46 #include "swrast/swrast.h"
49 #include "tnl/t_pipeline.h"
50 #include "swrast_setup/swrast_setup.h"
51 #include "drivers/common/meta.h"
53 #include "radeon_common.h"
54 #include "radeon_mipmap_tree.h"
55 #include "r200_context.h"
56 #include "r200_ioctl.h"
57 #include "r200_state.h"
60 #include "r200_swtcl.h"
61 #include "r200_vertprog.h"
64 /* =============================================================
68 static void r200AlphaFunc( struct gl_context
*ctx
, GLenum func
, GLfloat ref
)
70 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
71 int pp_misc
= rmesa
->hw
.ctx
.cmd
[CTX_PP_MISC
];
74 CLAMPED_FLOAT_TO_UBYTE(refByte
, ref
);
76 R200_STATECHANGE( rmesa
, ctx
);
78 pp_misc
&= ~(R200_ALPHA_TEST_OP_MASK
| R200_REF_ALPHA_MASK
);
79 pp_misc
|= (refByte
& R200_REF_ALPHA_MASK
);
83 pp_misc
|= R200_ALPHA_TEST_FAIL
;
86 pp_misc
|= R200_ALPHA_TEST_LESS
;
89 pp_misc
|= R200_ALPHA_TEST_EQUAL
;
92 pp_misc
|= R200_ALPHA_TEST_LEQUAL
;
95 pp_misc
|= R200_ALPHA_TEST_GREATER
;
98 pp_misc
|= R200_ALPHA_TEST_NEQUAL
;
101 pp_misc
|= R200_ALPHA_TEST_GEQUAL
;
104 pp_misc
|= R200_ALPHA_TEST_PASS
;
108 rmesa
->hw
.ctx
.cmd
[CTX_PP_MISC
] = pp_misc
;
111 static void r200BlendColor( struct gl_context
*ctx
, const GLfloat cf
[4] )
114 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
115 R200_STATECHANGE( rmesa
, ctx
);
116 CLAMPED_FLOAT_TO_UBYTE(color
[0], cf
[0]);
117 CLAMPED_FLOAT_TO_UBYTE(color
[1], cf
[1]);
118 CLAMPED_FLOAT_TO_UBYTE(color
[2], cf
[2]);
119 CLAMPED_FLOAT_TO_UBYTE(color
[3], cf
[3]);
120 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCOLOR
] = radeonPackColor( 4, color
[0], color
[1], color
[2], color
[3] );
124 * Calculate the hardware blend factor setting. This same function is used
125 * for source and destination of both alpha and RGB.
128 * The hardware register value for the specified blend factor. This value
129 * will need to be shifted into the correct position for either source or
130 * destination factor.
133 * Since the two cases where source and destination are handled differently
134 * are essentially error cases, they should never happen. Determine if these
135 * cases can be removed.
137 static int blend_factor( GLenum factor
, GLboolean is_src
)
143 func
= R200_BLEND_GL_ZERO
;
146 func
= R200_BLEND_GL_ONE
;
149 func
= R200_BLEND_GL_DST_COLOR
;
151 case GL_ONE_MINUS_DST_COLOR
:
152 func
= R200_BLEND_GL_ONE_MINUS_DST_COLOR
;
155 func
= R200_BLEND_GL_SRC_COLOR
;
157 case GL_ONE_MINUS_SRC_COLOR
:
158 func
= R200_BLEND_GL_ONE_MINUS_SRC_COLOR
;
161 func
= R200_BLEND_GL_SRC_ALPHA
;
163 case GL_ONE_MINUS_SRC_ALPHA
:
164 func
= R200_BLEND_GL_ONE_MINUS_SRC_ALPHA
;
167 func
= R200_BLEND_GL_DST_ALPHA
;
169 case GL_ONE_MINUS_DST_ALPHA
:
170 func
= R200_BLEND_GL_ONE_MINUS_DST_ALPHA
;
172 case GL_SRC_ALPHA_SATURATE
:
173 func
= (is_src
) ? R200_BLEND_GL_SRC_ALPHA_SATURATE
: R200_BLEND_GL_ZERO
;
175 case GL_CONSTANT_COLOR
:
176 func
= R200_BLEND_GL_CONST_COLOR
;
178 case GL_ONE_MINUS_CONSTANT_COLOR
:
179 func
= R200_BLEND_GL_ONE_MINUS_CONST_COLOR
;
181 case GL_CONSTANT_ALPHA
:
182 func
= R200_BLEND_GL_CONST_ALPHA
;
184 case GL_ONE_MINUS_CONSTANT_ALPHA
:
185 func
= R200_BLEND_GL_ONE_MINUS_CONST_ALPHA
;
188 func
= (is_src
) ? R200_BLEND_GL_ONE
: R200_BLEND_GL_ZERO
;
194 * Sets both the blend equation and the blend function.
195 * This is done in a single
196 * function because some blend equations (i.e., \c GL_MIN and \c GL_MAX)
197 * change the interpretation of the blend function.
198 * Also, make sure that blend function and blend equation are set to their default
199 * value if color blending is not enabled, since at least blend equations GL_MIN
200 * and GL_FUNC_REVERSE_SUBTRACT will cause wrong results otherwise for
203 static void r200_set_blend_state( struct gl_context
* ctx
)
205 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
206 GLuint cntl
= rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &
207 ~(R200_ROP_ENABLE
| R200_ALPHA_BLEND_ENABLE
| R200_SEPARATE_ALPHA_ENABLE
);
209 int func
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
210 (R200_BLEND_GL_ZERO
<< R200_DST_BLEND_SHIFT
);
211 int eqn
= R200_COMB_FCN_ADD_CLAMP
;
212 int funcA
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
213 (R200_BLEND_GL_ZERO
<< R200_DST_BLEND_SHIFT
);
214 int eqnA
= R200_COMB_FCN_ADD_CLAMP
;
216 R200_STATECHANGE( rmesa
, ctx
);
218 if (ctx
->Color
.ColorLogicOpEnabled
) {
219 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
| R200_ROP_ENABLE
;
220 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ABLENDCNTL
] = eqn
| func
;
221 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CBLENDCNTL
] = eqn
| func
;
223 } else if (ctx
->Color
.BlendEnabled
) {
224 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
| R200_ALPHA_BLEND_ENABLE
| R200_SEPARATE_ALPHA_ENABLE
;
227 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
;
228 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ABLENDCNTL
] = eqn
| func
;
229 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CBLENDCNTL
] = eqn
| func
;
233 func
= (blend_factor( ctx
->Color
.Blend
[0].SrcRGB
, GL_TRUE
) << R200_SRC_BLEND_SHIFT
) |
234 (blend_factor( ctx
->Color
.Blend
[0].DstRGB
, GL_FALSE
) << R200_DST_BLEND_SHIFT
);
236 switch(ctx
->Color
.Blend
[0].EquationRGB
) {
238 eqn
= R200_COMB_FCN_ADD_CLAMP
;
241 case GL_FUNC_SUBTRACT
:
242 eqn
= R200_COMB_FCN_SUB_CLAMP
;
245 case GL_FUNC_REVERSE_SUBTRACT
:
246 eqn
= R200_COMB_FCN_RSUB_CLAMP
;
250 eqn
= R200_COMB_FCN_MIN
;
251 func
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
252 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
256 eqn
= R200_COMB_FCN_MAX
;
257 func
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
258 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
262 fprintf( stderr
, "[%s:%u] Invalid RGB blend equation (0x%04x).\n",
263 __FUNCTION__
, __LINE__
, ctx
->Color
.Blend
[0].EquationRGB
);
267 funcA
= (blend_factor( ctx
->Color
.Blend
[0].SrcA
, GL_TRUE
) << R200_SRC_BLEND_SHIFT
) |
268 (blend_factor( ctx
->Color
.Blend
[0].DstA
, GL_FALSE
) << R200_DST_BLEND_SHIFT
);
270 switch(ctx
->Color
.Blend
[0].EquationA
) {
272 eqnA
= R200_COMB_FCN_ADD_CLAMP
;
275 case GL_FUNC_SUBTRACT
:
276 eqnA
= R200_COMB_FCN_SUB_CLAMP
;
279 case GL_FUNC_REVERSE_SUBTRACT
:
280 eqnA
= R200_COMB_FCN_RSUB_CLAMP
;
284 eqnA
= R200_COMB_FCN_MIN
;
285 funcA
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
286 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
290 eqnA
= R200_COMB_FCN_MAX
;
291 funcA
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
292 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
296 fprintf( stderr
, "[%s:%u] Invalid A blend equation (0x%04x).\n",
297 __FUNCTION__
, __LINE__
, ctx
->Color
.Blend
[0].EquationA
);
301 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ABLENDCNTL
] = eqnA
| funcA
;
302 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CBLENDCNTL
] = eqn
| func
;
306 static void r200BlendEquationSeparate( struct gl_context
*ctx
,
307 GLenum modeRGB
, GLenum modeA
)
309 r200_set_blend_state( ctx
);
312 static void r200BlendFuncSeparate( struct gl_context
*ctx
,
313 GLenum sfactorRGB
, GLenum dfactorRGB
,
314 GLenum sfactorA
, GLenum dfactorA
)
316 r200_set_blend_state( ctx
);
320 /* =============================================================
324 static void r200DepthFunc( struct gl_context
*ctx
, GLenum func
)
326 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
328 R200_STATECHANGE( rmesa
, ctx
);
329 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_Z_TEST_MASK
;
331 switch ( ctx
->Depth
.Func
) {
333 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_NEVER
;
336 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_LESS
;
339 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_EQUAL
;
342 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_LEQUAL
;
345 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_GREATER
;
348 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_NEQUAL
;
351 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_GEQUAL
;
354 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_ALWAYS
;
359 static void r200DepthMask( struct gl_context
*ctx
, GLboolean flag
)
361 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
362 R200_STATECHANGE( rmesa
, ctx
);
364 if ( ctx
->Depth
.Mask
) {
365 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_WRITE_ENABLE
;
367 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_Z_WRITE_ENABLE
;
372 /* =============================================================
377 static void r200Fogfv( struct gl_context
*ctx
, GLenum pname
, const GLfloat
*param
)
379 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
380 union { int i
; float f
; } c
, d
;
384 c
.i
= rmesa
->hw
.fog
.cmd
[FOG_C
];
385 d
.i
= rmesa
->hw
.fog
.cmd
[FOG_D
];
389 if (!ctx
->Fog
.Enabled
)
391 R200_STATECHANGE(rmesa
, tcl
);
392 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_TCL_FOG_MASK
;
393 switch (ctx
->Fog
.Mode
) {
395 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_LINEAR
;
396 if (ctx
->Fog
.Start
== ctx
->Fog
.End
) {
401 c
.f
= ctx
->Fog
.End
/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
402 d
.f
= -1.0/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
406 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_EXP
;
408 d
.f
= -ctx
->Fog
.Density
;
411 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_EXP2
;
413 d
.f
= -(ctx
->Fog
.Density
* ctx
->Fog
.Density
);
420 switch (ctx
->Fog
.Mode
) {
423 d
.f
= -ctx
->Fog
.Density
;
427 d
.f
= -(ctx
->Fog
.Density
* ctx
->Fog
.Density
);
435 if (ctx
->Fog
.Mode
== GL_LINEAR
) {
436 if (ctx
->Fog
.Start
== ctx
->Fog
.End
) {
440 c
.f
= ctx
->Fog
.End
/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
441 d
.f
= -1.0/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
446 R200_STATECHANGE( rmesa
, ctx
);
447 _mesa_unclamped_float_rgba_to_ubyte(col
, ctx
->Fog
.Color
);
448 i
= radeonPackColor( 4, col
[0], col
[1], col
[2], 0 );
449 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] &= ~R200_FOG_COLOR_MASK
;
450 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] |= i
;
452 case GL_FOG_COORD_SRC
: {
453 GLuint out_0
= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
];
454 GLuint fog
= rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
];
456 fog
&= ~R200_FOG_USE_MASK
;
457 if ( ctx
->Fog
.FogCoordinateSource
== GL_FOG_COORD
|| ctx
->VertexProgram
.Enabled
) {
458 fog
|= R200_FOG_USE_VTX_FOG
;
459 out_0
|= R200_VTX_DISCRETE_FOG
;
462 fog
|= R200_FOG_USE_SPEC_ALPHA
;
463 out_0
&= ~R200_VTX_DISCRETE_FOG
;
466 if ( fog
!= rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] ) {
467 R200_STATECHANGE( rmesa
, ctx
);
468 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] = fog
;
471 if (out_0
!= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
]) {
472 R200_STATECHANGE( rmesa
, vtx
);
473 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] = out_0
;
482 if (c
.i
!= rmesa
->hw
.fog
.cmd
[FOG_C
] || d
.i
!= rmesa
->hw
.fog
.cmd
[FOG_D
]) {
483 R200_STATECHANGE( rmesa
, fog
);
484 rmesa
->hw
.fog
.cmd
[FOG_C
] = c
.i
;
485 rmesa
->hw
.fog
.cmd
[FOG_D
] = d
.i
;
489 /* =============================================================
493 static void r200CullFace( struct gl_context
*ctx
, GLenum unused
)
495 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
496 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
497 GLuint t
= rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
];
499 s
|= R200_FFACE_SOLID
| R200_BFACE_SOLID
;
500 t
&= ~(R200_CULL_FRONT
| R200_CULL_BACK
);
502 if ( ctx
->Polygon
.CullFlag
) {
503 switch ( ctx
->Polygon
.CullFaceMode
) {
505 s
&= ~R200_FFACE_SOLID
;
506 t
|= R200_CULL_FRONT
;
509 s
&= ~R200_BFACE_SOLID
;
512 case GL_FRONT_AND_BACK
:
513 s
&= ~(R200_FFACE_SOLID
| R200_BFACE_SOLID
);
514 t
|= (R200_CULL_FRONT
| R200_CULL_BACK
);
519 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
520 R200_STATECHANGE(rmesa
, set
);
521 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
524 if ( rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] != t
) {
525 R200_STATECHANGE(rmesa
, tcl
);
526 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] = t
;
530 static void r200FrontFace( struct gl_context
*ctx
, GLenum mode
)
532 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
533 int cull_face
= (mode
== GL_CW
) ? R200_FFACE_CULL_CW
: R200_FFACE_CULL_CCW
;
535 R200_STATECHANGE( rmesa
, set
);
536 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_FFACE_CULL_DIR_MASK
;
538 R200_STATECHANGE( rmesa
, tcl
);
539 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_CULL_FRONT_IS_CCW
;
541 /* Winding is inverted when rendering to FBO */
542 if (ctx
->DrawBuffer
&& _mesa_is_user_fbo(ctx
->DrawBuffer
))
543 cull_face
= (mode
== GL_CCW
) ? R200_FFACE_CULL_CW
: R200_FFACE_CULL_CCW
;
544 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= cull_face
;
546 if ( mode
== GL_CCW
)
547 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_CULL_FRONT_IS_CCW
;
550 /* =============================================================
553 static void r200PointSize( struct gl_context
*ctx
, GLfloat size
)
555 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
556 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.ptp
.cmd
;
558 radeon_print(RADEON_STATE
, RADEON_TRACE
,
559 "%s(%p) size: %f, fixed point result: %d.%d (%d/16)\n",
561 ((GLuint
)(ctx
->Point
.Size
* 16.0))/16,
562 (((GLuint
)(ctx
->Point
.Size
* 16.0))&15)*100/16,
563 ((GLuint
)(ctx
->Point
.Size
* 16.0))&15);
565 R200_STATECHANGE( rmesa
, cst
);
566 R200_STATECHANGE( rmesa
, ptp
);
567 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] &= ~0xffff;
568 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] |= ((GLuint
)(ctx
->Point
.Size
* 16.0));
569 /* this is the size param of the point size calculation (point size reg value
570 is not used when calculation is active). */
571 fcmd
[PTP_VPORT_SCALE_PTSIZE
] = ctx
->Point
.Size
;
574 static void r200PointParameter( struct gl_context
*ctx
, GLenum pname
, const GLfloat
*params
)
576 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
577 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.ptp
.cmd
;
580 case GL_POINT_SIZE_MIN
:
581 /* Can clamp both in tcl and setup - just set both (as does fglrx) */
582 R200_STATECHANGE( rmesa
, lin
);
583 R200_STATECHANGE( rmesa
, ptp
);
584 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] &= 0xffff;
585 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] |= (GLuint
)(ctx
->Point
.MinSize
* 16.0) << 16;
586 fcmd
[PTP_CLAMP_MIN
] = ctx
->Point
.MinSize
;
588 case GL_POINT_SIZE_MAX
:
589 R200_STATECHANGE( rmesa
, cst
);
590 R200_STATECHANGE( rmesa
, ptp
);
591 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] &= 0xffff;
592 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] |= (GLuint
)(ctx
->Point
.MaxSize
* 16.0) << 16;
593 fcmd
[PTP_CLAMP_MAX
] = ctx
->Point
.MaxSize
;
595 case GL_POINT_DISTANCE_ATTENUATION
:
596 R200_STATECHANGE( rmesa
, vtx
);
597 R200_STATECHANGE( rmesa
, spr
);
598 R200_STATECHANGE( rmesa
, ptp
);
599 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.ptp
.cmd
;
600 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] &=
601 ~(R200_PS_MULT_MASK
| R200_PS_LIN_ATT_ZERO
| R200_PS_SE_SEL_STATE
);
602 /* can't rely on ctx->Point._Attenuated here and test for NEW_POINT in
603 r200ValidateState looks like overkill */
604 if (ctx
->Point
.Params
[0] != 1.0 ||
605 ctx
->Point
.Params
[1] != 0.0 ||
606 ctx
->Point
.Params
[2] != 0.0 ||
607 (ctx
->VertexProgram
.Enabled
&& ctx
->VertexProgram
.PointSizeEnabled
)) {
608 /* all we care for vp would be the ps_se_sel_state setting */
609 fcmd
[PTP_ATT_CONST_QUAD
] = ctx
->Point
.Params
[2];
610 fcmd
[PTP_ATT_CONST_LIN
] = ctx
->Point
.Params
[1];
611 fcmd
[PTP_ATT_CONST_CON
] = ctx
->Point
.Params
[0];
612 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |= R200_PS_MULT_ATTENCONST
;
613 if (ctx
->Point
.Params
[1] == 0.0)
614 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |= R200_PS_LIN_ATT_ZERO
;
615 /* FIXME: setting this here doesn't look quite ok - we only want to do
616 that if we're actually drawing points probably */
617 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_PT_SIZE
;
618 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |= R200_VTX_POINT_SIZE
;
621 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |=
622 R200_PS_SE_SEL_STATE
| R200_PS_MULT_CONST
;
623 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_PT_SIZE
;
624 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~R200_VTX_POINT_SIZE
;
627 case GL_POINT_FADE_THRESHOLD_SIZE
:
628 /* don't support multisampling, so doesn't matter. */
630 /* can't do these but don't need them.
631 case GL_POINT_SPRITE_R_MODE_NV:
632 case GL_POINT_SPRITE_COORD_ORIGIN: */
634 fprintf(stderr
, "bad pname parameter in r200PointParameter\n");
639 /* =============================================================
642 static void r200LineWidth( struct gl_context
*ctx
, GLfloat widthf
)
644 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
646 R200_STATECHANGE( rmesa
, lin
);
647 R200_STATECHANGE( rmesa
, set
);
649 /* Line width is stored in U6.4 format.
650 * Same min/max limits for AA, non-AA lines.
652 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] &= ~0xffff;
653 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] |= (GLuint
)
654 (CLAMP(widthf
, ctx
->Const
.MinLineWidth
, ctx
->Const
.MaxLineWidth
) * 16.0);
656 if ( widthf
> 1.0 ) {
657 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_WIDELINE_ENABLE
;
659 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_WIDELINE_ENABLE
;
663 static void r200LineStipple( struct gl_context
*ctx
, GLint factor
, GLushort pattern
)
665 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
667 R200_STATECHANGE( rmesa
, lin
);
668 rmesa
->hw
.lin
.cmd
[LIN_RE_LINE_PATTERN
] =
669 ((((GLuint
)factor
& 0xff) << 16) | ((GLuint
)pattern
));
673 /* =============================================================
676 static void r200ColorMask( struct gl_context
*ctx
,
677 GLboolean r
, GLboolean g
,
678 GLboolean b
, GLboolean a
)
680 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
682 struct radeon_renderbuffer
*rrb
;
683 GLuint flag
= rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] & ~R200_PLANE_MASK_ENABLE
;
685 rrb
= radeon_get_colorbuffer(&rmesa
->radeon
);
688 mask
= radeonPackColor( rrb
->cpp
,
689 ctx
->Color
.ColorMask
[0][RCOMP
],
690 ctx
->Color
.ColorMask
[0][GCOMP
],
691 ctx
->Color
.ColorMask
[0][BCOMP
],
692 ctx
->Color
.ColorMask
[0][ACOMP
] );
695 if (!(r
&& g
&& b
&& a
))
696 flag
|= R200_PLANE_MASK_ENABLE
;
698 if ( rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] != flag
) {
699 R200_STATECHANGE( rmesa
, ctx
);
700 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = flag
;
703 if ( rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
] != mask
) {
704 R200_STATECHANGE( rmesa
, msk
);
705 rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
] = mask
;
710 /* =============================================================
714 static void r200PolygonOffset( struct gl_context
*ctx
,
715 GLfloat factor
, GLfloat units
)
717 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
718 const GLfloat depthScale
= 1.0F
/ ctx
->DrawBuffer
->_DepthMaxF
;
719 float_ui32_type constant
= { units
* depthScale
};
720 float_ui32_type factoru
= { factor
};
725 /* fprintf(stderr, "%s f:%f u:%f\n", __FUNCTION__, factor, constant); */
727 R200_STATECHANGE( rmesa
, zbs
);
728 rmesa
->hw
.zbs
.cmd
[ZBS_SE_ZBIAS_FACTOR
] = factoru
.ui32
;
729 rmesa
->hw
.zbs
.cmd
[ZBS_SE_ZBIAS_CONSTANT
] = constant
.ui32
;
732 static void r200PolygonMode( struct gl_context
*ctx
, GLenum face
, GLenum mode
)
734 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
735 GLboolean unfilled
= (ctx
->Polygon
.FrontMode
!= GL_FILL
||
736 ctx
->Polygon
.BackMode
!= GL_FILL
);
738 /* Can't generally do unfilled via tcl, but some good special
741 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_UNFILLED
, unfilled
);
742 if (rmesa
->radeon
.TclFallback
) {
743 r200ChooseRenderState( ctx
);
744 r200ChooseVertexState( ctx
);
749 /* =============================================================
750 * Rendering attributes
752 * We really don't want to recalculate all this every time we bind a
753 * texture. These things shouldn't change all that often, so it makes
754 * sense to break them out of the core texture state update routines.
757 /* Examine lighting and texture state to determine if separate specular
760 static void r200UpdateSpecular( struct gl_context
*ctx
)
762 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
763 uint32_t p
= rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
];
765 R200_STATECHANGE( rmesa
, tcl
);
766 R200_STATECHANGE( rmesa
, vtx
);
768 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~(3<<R200_VTX_COLOR_0_SHIFT
);
769 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~(3<<R200_VTX_COLOR_1_SHIFT
);
770 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_COLOR_0
;
771 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_COLOR_1
;
772 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LIGHTING_ENABLE
;
774 p
&= ~R200_SPECULAR_ENABLE
;
776 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_DIFFUSE_SPECULAR_COMBINE
;
779 if (ctx
->Light
.Enabled
&&
780 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
) {
781 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
782 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
) |
783 (R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
784 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_0
;
785 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_1
;
786 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHTING_ENABLE
;
787 p
|= R200_SPECULAR_ENABLE
;
788 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &=
789 ~R200_DIFFUSE_SPECULAR_COMBINE
;
791 else if (ctx
->Light
.Enabled
) {
792 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
793 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
));
794 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_0
;
795 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHTING_ENABLE
;
796 } else if (ctx
->Fog
.ColorSumEnabled
) {
797 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
798 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
) |
799 (R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
800 p
|= R200_SPECULAR_ENABLE
;
802 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
803 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
));
806 if (ctx
->Fog
.Enabled
) {
807 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
808 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
809 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_1
;
812 if ( rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] != p
) {
813 R200_STATECHANGE( rmesa
, ctx
);
814 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] = p
;
817 /* Update vertex/render formats
819 if (rmesa
->radeon
.TclFallback
) {
820 r200ChooseRenderState( ctx
);
821 r200ChooseVertexState( ctx
);
826 /* =============================================================
831 /* Update on colormaterial, material emmissive/ambient,
832 * lightmodel.globalambient
834 static void update_global_ambient( struct gl_context
*ctx
)
836 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
837 float *fcmd
= (float *)R200_DB_STATE( glt
);
839 /* Need to do more if both emmissive & ambient are PREMULT:
840 * I believe this is not nessary when using source_material. This condition thus
841 * will never happen currently, and the function has no dependencies on materials now
843 if ((rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
] &
844 ((3 << R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
845 (3 << R200_FRONT_AMBIENT_SOURCE_SHIFT
))) == 0)
847 COPY_3V( &fcmd
[GLT_RED
],
848 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_EMISSION
]);
849 ACC_SCALE_3V( &fcmd
[GLT_RED
],
850 ctx
->Light
.Model
.Ambient
,
851 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_AMBIENT
]);
855 COPY_3V( &fcmd
[GLT_RED
], ctx
->Light
.Model
.Ambient
);
858 R200_DB_STATECHANGE(rmesa
, &rmesa
->hw
.glt
);
861 /* Update on change to
865 static void update_light_colors( struct gl_context
*ctx
, GLuint p
)
867 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
869 /* fprintf(stderr, "%s\n", __FUNCTION__); */
872 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
873 float *fcmd
= (float *)R200_DB_STATE( lit
[p
] );
875 COPY_4V( &fcmd
[LIT_AMBIENT_RED
], l
->Ambient
);
876 COPY_4V( &fcmd
[LIT_DIFFUSE_RED
], l
->Diffuse
);
877 COPY_4V( &fcmd
[LIT_SPECULAR_RED
], l
->Specular
);
879 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
883 static void r200ColorMaterial( struct gl_context
*ctx
, GLenum face
, GLenum mode
)
885 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
886 GLuint light_model_ctl1
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
];
887 light_model_ctl1
&= ~((0xf << R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
888 (0xf << R200_FRONT_AMBIENT_SOURCE_SHIFT
) |
889 (0xf << R200_FRONT_DIFFUSE_SOURCE_SHIFT
) |
890 (0xf << R200_FRONT_SPECULAR_SOURCE_SHIFT
) |
891 (0xf << R200_BACK_EMISSIVE_SOURCE_SHIFT
) |
892 (0xf << R200_BACK_AMBIENT_SOURCE_SHIFT
) |
893 (0xf << R200_BACK_DIFFUSE_SOURCE_SHIFT
) |
894 (0xf << R200_BACK_SPECULAR_SOURCE_SHIFT
));
896 if (ctx
->Light
.ColorMaterialEnabled
) {
897 GLuint mask
= ctx
->Light
._ColorMaterialBitmask
;
899 if (mask
& MAT_BIT_FRONT_EMISSION
) {
900 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
901 R200_FRONT_EMISSIVE_SOURCE_SHIFT
);
904 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
905 R200_FRONT_EMISSIVE_SOURCE_SHIFT
);
907 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
908 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
909 R200_FRONT_AMBIENT_SOURCE_SHIFT
);
912 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
913 R200_FRONT_AMBIENT_SOURCE_SHIFT
);
915 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
916 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
917 R200_FRONT_DIFFUSE_SOURCE_SHIFT
);
920 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
921 R200_FRONT_DIFFUSE_SOURCE_SHIFT
);
923 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
924 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
925 R200_FRONT_SPECULAR_SOURCE_SHIFT
);
928 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
929 R200_FRONT_SPECULAR_SOURCE_SHIFT
);
932 if (mask
& MAT_BIT_BACK_EMISSION
) {
933 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
934 R200_BACK_EMISSIVE_SOURCE_SHIFT
);
937 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
938 R200_BACK_EMISSIVE_SOURCE_SHIFT
);
940 if (mask
& MAT_BIT_BACK_AMBIENT
) {
941 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
942 R200_BACK_AMBIENT_SOURCE_SHIFT
);
944 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
945 R200_BACK_AMBIENT_SOURCE_SHIFT
);
947 if (mask
& MAT_BIT_BACK_DIFFUSE
) {
948 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
949 R200_BACK_DIFFUSE_SOURCE_SHIFT
);
951 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
952 R200_BACK_DIFFUSE_SOURCE_SHIFT
);
954 if (mask
& MAT_BIT_BACK_SPECULAR
) {
955 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
956 R200_BACK_SPECULAR_SOURCE_SHIFT
);
959 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
960 R200_BACK_SPECULAR_SOURCE_SHIFT
);
964 /* Default to SOURCE_MATERIAL:
967 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
968 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_AMBIENT_SOURCE_SHIFT
) |
969 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_DIFFUSE_SOURCE_SHIFT
) |
970 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_SPECULAR_SOURCE_SHIFT
) |
971 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_EMISSIVE_SOURCE_SHIFT
) |
972 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_AMBIENT_SOURCE_SHIFT
) |
973 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_DIFFUSE_SOURCE_SHIFT
) |
974 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_SPECULAR_SOURCE_SHIFT
);
977 if (light_model_ctl1
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
]) {
978 R200_STATECHANGE( rmesa
, tcl
);
979 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
] = light_model_ctl1
;
985 void r200UpdateMaterial( struct gl_context
*ctx
)
987 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
988 GLfloat (*mat
)[4] = ctx
->Light
.Material
.Attrib
;
989 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( mtl
[0] );
990 GLfloat
*fcmd2
= (GLfloat
*)R200_DB_STATE( mtl
[1] );
993 /* Might be possible and faster to update everything unconditionally? */
994 if (ctx
->Light
.ColorMaterialEnabled
)
995 mask
&= ~ctx
->Light
._ColorMaterialBitmask
;
997 if (R200_DEBUG
& RADEON_STATE
)
998 fprintf(stderr
, "%s\n", __FUNCTION__
);
1000 if (mask
& MAT_BIT_FRONT_EMISSION
) {
1001 fcmd
[MTL_EMMISSIVE_RED
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][0];
1002 fcmd
[MTL_EMMISSIVE_GREEN
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][1];
1003 fcmd
[MTL_EMMISSIVE_BLUE
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][2];
1004 fcmd
[MTL_EMMISSIVE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][3];
1006 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
1007 fcmd
[MTL_AMBIENT_RED
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][0];
1008 fcmd
[MTL_AMBIENT_GREEN
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][1];
1009 fcmd
[MTL_AMBIENT_BLUE
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][2];
1010 fcmd
[MTL_AMBIENT_ALPHA
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][3];
1012 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
1013 fcmd
[MTL_DIFFUSE_RED
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][0];
1014 fcmd
[MTL_DIFFUSE_GREEN
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][1];
1015 fcmd
[MTL_DIFFUSE_BLUE
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][2];
1016 fcmd
[MTL_DIFFUSE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][3];
1018 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
1019 fcmd
[MTL_SPECULAR_RED
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][0];
1020 fcmd
[MTL_SPECULAR_GREEN
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][1];
1021 fcmd
[MTL_SPECULAR_BLUE
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][2];
1022 fcmd
[MTL_SPECULAR_ALPHA
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][3];
1024 if (mask
& MAT_BIT_FRONT_SHININESS
) {
1025 fcmd
[MTL_SHININESS
] = mat
[MAT_ATTRIB_FRONT_SHININESS
][0];
1028 if (mask
& MAT_BIT_BACK_EMISSION
) {
1029 fcmd2
[MTL_EMMISSIVE_RED
] = mat
[MAT_ATTRIB_BACK_EMISSION
][0];
1030 fcmd2
[MTL_EMMISSIVE_GREEN
] = mat
[MAT_ATTRIB_BACK_EMISSION
][1];
1031 fcmd2
[MTL_EMMISSIVE_BLUE
] = mat
[MAT_ATTRIB_BACK_EMISSION
][2];
1032 fcmd2
[MTL_EMMISSIVE_ALPHA
] = mat
[MAT_ATTRIB_BACK_EMISSION
][3];
1034 if (mask
& MAT_BIT_BACK_AMBIENT
) {
1035 fcmd2
[MTL_AMBIENT_RED
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][0];
1036 fcmd2
[MTL_AMBIENT_GREEN
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][1];
1037 fcmd2
[MTL_AMBIENT_BLUE
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][2];
1038 fcmd2
[MTL_AMBIENT_ALPHA
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][3];
1040 if (mask
& MAT_BIT_BACK_DIFFUSE
) {
1041 fcmd2
[MTL_DIFFUSE_RED
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][0];
1042 fcmd2
[MTL_DIFFUSE_GREEN
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][1];
1043 fcmd2
[MTL_DIFFUSE_BLUE
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][2];
1044 fcmd2
[MTL_DIFFUSE_ALPHA
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][3];
1046 if (mask
& MAT_BIT_BACK_SPECULAR
) {
1047 fcmd2
[MTL_SPECULAR_RED
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][0];
1048 fcmd2
[MTL_SPECULAR_GREEN
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][1];
1049 fcmd2
[MTL_SPECULAR_BLUE
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][2];
1050 fcmd2
[MTL_SPECULAR_ALPHA
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][3];
1052 if (mask
& MAT_BIT_BACK_SHININESS
) {
1053 fcmd2
[MTL_SHININESS
] = mat
[MAT_ATTRIB_BACK_SHININESS
][0];
1056 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mtl
[0] );
1057 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mtl
[1] );
1059 /* currently material changes cannot trigger a global ambient change, I believe this is correct
1060 update_global_ambient( ctx ); */
1065 * _MESA_NEW_NEED_EYE_COORDS
1067 * Uses derived state from mesa:
1071 * _NormSpotDirection
1072 * _ModelViewInvScale
1076 * which are calculated in light.c and are correct for the current
1077 * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
1078 * and _MESA_NEW_NEED_EYE_COORDS.
1080 static void update_light( struct gl_context
*ctx
)
1082 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1084 /* Have to check these, or have an automatic shortcircuit mechanism
1085 * to remove noop statechanges. (Or just do a better job on the
1089 GLuint tmp
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
];
1091 if (ctx
->_NeedEyeCoords
)
1092 tmp
&= ~R200_LIGHT_IN_MODELSPACE
;
1094 tmp
|= R200_LIGHT_IN_MODELSPACE
;
1096 if (tmp
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
])
1098 R200_STATECHANGE( rmesa
, tcl
);
1099 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] = tmp
;
1104 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( eye
);
1105 fcmd
[EYE_X
] = ctx
->_EyeZDir
[0];
1106 fcmd
[EYE_Y
] = ctx
->_EyeZDir
[1];
1107 fcmd
[EYE_Z
] = - ctx
->_EyeZDir
[2];
1108 fcmd
[EYE_RESCALE_FACTOR
] = ctx
->_ModelViewInvScale
;
1109 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.eye
);
1114 if (ctx
->Light
.Enabled
) {
1116 for (p
= 0 ; p
< MAX_LIGHTS
; p
++) {
1117 if (ctx
->Light
.Light
[p
].Enabled
) {
1118 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1119 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( lit
[p
] );
1121 if (l
->EyePosition
[3] == 0.0) {
1122 COPY_3FV( &fcmd
[LIT_POSITION_X
], l
->_VP_inf_norm
);
1123 COPY_3FV( &fcmd
[LIT_DIRECTION_X
], l
->_h_inf_norm
);
1124 fcmd
[LIT_POSITION_W
] = 0;
1125 fcmd
[LIT_DIRECTION_W
] = 0;
1127 COPY_4V( &fcmd
[LIT_POSITION_X
], l
->_Position
);
1128 fcmd
[LIT_DIRECTION_X
] = -l
->_NormSpotDirection
[0];
1129 fcmd
[LIT_DIRECTION_Y
] = -l
->_NormSpotDirection
[1];
1130 fcmd
[LIT_DIRECTION_Z
] = -l
->_NormSpotDirection
[2];
1131 fcmd
[LIT_DIRECTION_W
] = 0;
1134 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
1140 static void r200Lightfv( struct gl_context
*ctx
, GLenum light
,
1141 GLenum pname
, const GLfloat
*params
)
1143 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1144 GLint p
= light
- GL_LIGHT0
;
1145 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1146 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.lit
[p
].cmd
;
1153 update_light_colors( ctx
, p
);
1156 case GL_SPOT_DIRECTION
:
1157 /* picked up in update_light */
1161 /* positions picked up in update_light, but can do flag here */
1162 GLuint flag
= (p
&1)? R200_LIGHT_1_IS_LOCAL
: R200_LIGHT_0_IS_LOCAL
;
1163 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1165 R200_STATECHANGE(rmesa
, tcl
);
1166 if (l
->EyePosition
[3] != 0.0F
)
1167 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1169 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1173 case GL_SPOT_EXPONENT
:
1174 R200_STATECHANGE(rmesa
, lit
[p
]);
1175 fcmd
[LIT_SPOT_EXPONENT
] = params
[0];
1178 case GL_SPOT_CUTOFF
: {
1179 GLuint flag
= (p
&1) ? R200_LIGHT_1_IS_SPOT
: R200_LIGHT_0_IS_SPOT
;
1180 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1182 R200_STATECHANGE(rmesa
, lit
[p
]);
1183 fcmd
[LIT_SPOT_CUTOFF
] = l
->_CosCutoff
;
1185 R200_STATECHANGE(rmesa
, tcl
);
1186 if (l
->SpotCutoff
!= 180.0F
)
1187 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1189 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1194 case GL_CONSTANT_ATTENUATION
:
1195 R200_STATECHANGE(rmesa
, lit
[p
]);
1196 fcmd
[LIT_ATTEN_CONST
] = params
[0];
1197 if ( params
[0] == 0.0 )
1198 fcmd
[LIT_ATTEN_CONST_INV
] = FLT_MAX
;
1200 fcmd
[LIT_ATTEN_CONST_INV
] = 1.0 / params
[0];
1202 case GL_LINEAR_ATTENUATION
:
1203 R200_STATECHANGE(rmesa
, lit
[p
]);
1204 fcmd
[LIT_ATTEN_LINEAR
] = params
[0];
1206 case GL_QUADRATIC_ATTENUATION
:
1207 R200_STATECHANGE(rmesa
, lit
[p
]);
1208 fcmd
[LIT_ATTEN_QUADRATIC
] = params
[0];
1214 /* Set RANGE_ATTEN only when needed */
1217 case GL_CONSTANT_ATTENUATION
:
1218 case GL_LINEAR_ATTENUATION
:
1219 case GL_QUADRATIC_ATTENUATION
: {
1220 GLuint
*icmd
= (GLuint
*)R200_DB_STATE( tcl
);
1221 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1222 GLuint atten_flag
= ( p
&1 ) ? R200_LIGHT_1_ENABLE_RANGE_ATTEN
1223 : R200_LIGHT_0_ENABLE_RANGE_ATTEN
;
1224 GLuint atten_const_flag
= ( p
&1 ) ? R200_LIGHT_1_CONSTANT_RANGE_ATTEN
1225 : R200_LIGHT_0_CONSTANT_RANGE_ATTEN
;
1227 if ( l
->EyePosition
[3] == 0.0F
||
1228 ( ( fcmd
[LIT_ATTEN_CONST
] == 0.0 || fcmd
[LIT_ATTEN_CONST
] == 1.0 ) &&
1229 fcmd
[LIT_ATTEN_QUADRATIC
] == 0.0 && fcmd
[LIT_ATTEN_LINEAR
] == 0.0 ) ) {
1230 /* Disable attenuation */
1231 icmd
[idx
] &= ~atten_flag
;
1233 if ( fcmd
[LIT_ATTEN_QUADRATIC
] == 0.0 && fcmd
[LIT_ATTEN_LINEAR
] == 0.0 ) {
1234 /* Enable only constant portion of attenuation calculation */
1235 icmd
[idx
] |= ( atten_flag
| atten_const_flag
);
1237 /* Enable full attenuation calculation */
1238 icmd
[idx
] &= ~atten_const_flag
;
1239 icmd
[idx
] |= atten_flag
;
1243 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.tcl
);
1251 static void r200UpdateLocalViewer ( struct gl_context
*ctx
)
1253 /* It looks like for the texgen modes GL_SPHERE_MAP, GL_NORMAL_MAP and
1254 GL_REFLECTION_MAP we need R200_LOCAL_VIEWER set (fglrx does exactly that
1255 for these and only these modes). This means specular highlights may turn out
1256 wrong in some cases when lighting is enabled but GL_LIGHT_MODEL_LOCAL_VIEWER
1257 is not set, though it seems to happen rarely and the effect seems quite
1258 subtle. May need TCL fallback to fix it completely, though I'm not sure
1259 how you'd identify the cases where the specular highlights indeed will
1260 be wrong. Don't know if fglrx does something special in that case.
1262 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1263 R200_STATECHANGE( rmesa
, tcl
);
1264 if (ctx
->Light
.Model
.LocalViewer
||
1265 ctx
->Texture
._GenFlags
& TEXGEN_NEED_NORMALS
)
1266 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LOCAL_VIEWER
;
1268 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LOCAL_VIEWER
;
1271 static void r200LightModelfv( struct gl_context
*ctx
, GLenum pname
,
1272 const GLfloat
*param
)
1274 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1277 case GL_LIGHT_MODEL_AMBIENT
:
1278 update_global_ambient( ctx
);
1281 case GL_LIGHT_MODEL_LOCAL_VIEWER
:
1282 r200UpdateLocalViewer( ctx
);
1285 case GL_LIGHT_MODEL_TWO_SIDE
:
1286 R200_STATECHANGE( rmesa
, tcl
);
1287 if (ctx
->Light
.Model
.TwoSide
)
1288 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHT_TWOSIDE
;
1290 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~(R200_LIGHT_TWOSIDE
);
1291 if (rmesa
->radeon
.TclFallback
) {
1292 r200ChooseRenderState( ctx
);
1293 r200ChooseVertexState( ctx
);
1297 case GL_LIGHT_MODEL_COLOR_CONTROL
:
1298 r200UpdateSpecular(ctx
);
1306 static void r200ShadeModel( struct gl_context
*ctx
, GLenum mode
)
1308 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1309 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
1311 s
&= ~(R200_DIFFUSE_SHADE_MASK
|
1312 R200_ALPHA_SHADE_MASK
|
1313 R200_SPECULAR_SHADE_MASK
|
1314 R200_FOG_SHADE_MASK
|
1315 R200_DISC_FOG_SHADE_MASK
);
1319 s
|= (R200_DIFFUSE_SHADE_FLAT
|
1320 R200_ALPHA_SHADE_FLAT
|
1321 R200_SPECULAR_SHADE_FLAT
|
1322 R200_FOG_SHADE_FLAT
|
1323 R200_DISC_FOG_SHADE_FLAT
);
1326 s
|= (R200_DIFFUSE_SHADE_GOURAUD
|
1327 R200_ALPHA_SHADE_GOURAUD
|
1328 R200_SPECULAR_SHADE_GOURAUD
|
1329 R200_FOG_SHADE_GOURAUD
|
1330 R200_DISC_FOG_SHADE_GOURAUD
);
1336 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
1337 R200_STATECHANGE( rmesa
, set
);
1338 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
1343 /* =============================================================
1347 static void r200ClipPlane( struct gl_context
*ctx
, GLenum plane
, const GLfloat
*eq
)
1349 GLint p
= (GLint
) plane
- (GLint
) GL_CLIP_PLANE0
;
1350 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1351 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1353 R200_STATECHANGE( rmesa
, ucp
[p
] );
1354 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1355 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1356 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1357 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1360 static void r200UpdateClipPlanes( struct gl_context
*ctx
)
1362 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1365 for (p
= 0; p
< ctx
->Const
.MaxClipPlanes
; p
++) {
1366 if (ctx
->Transform
.ClipPlanesEnabled
& (1 << p
)) {
1367 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1369 R200_STATECHANGE( rmesa
, ucp
[p
] );
1370 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1371 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1372 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1373 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1379 /* =============================================================
1384 r200StencilFuncSeparate( struct gl_context
*ctx
, GLenum face
, GLenum func
,
1385 GLint ref
, GLuint mask
)
1387 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1388 GLuint refmask
= ((_mesa_get_stencil_ref(ctx
, 0) << R200_STENCIL_REF_SHIFT
) |
1389 ((ctx
->Stencil
.ValueMask
[0] & 0xff) << R200_STENCIL_MASK_SHIFT
));
1391 R200_STATECHANGE( rmesa
, ctx
);
1392 R200_STATECHANGE( rmesa
, msk
);
1394 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_STENCIL_TEST_MASK
;
1395 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~(R200_STENCIL_REF_MASK
|
1396 R200_STENCIL_VALUE_MASK
);
1398 switch ( ctx
->Stencil
.Function
[0] ) {
1400 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEVER
;
1403 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LESS
;
1406 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_EQUAL
;
1409 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LEQUAL
;
1412 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GREATER
;
1415 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEQUAL
;
1418 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GEQUAL
;
1421 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_ALWAYS
;
1425 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |= refmask
;
1429 r200StencilMaskSeparate( struct gl_context
*ctx
, GLenum face
, GLuint mask
)
1431 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1433 R200_STATECHANGE( rmesa
, msk
);
1434 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~R200_STENCIL_WRITE_MASK
;
1435 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |=
1436 ((ctx
->Stencil
.WriteMask
[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT
);
1440 r200StencilOpSeparate( struct gl_context
*ctx
, GLenum face
, GLenum fail
,
1441 GLenum zfail
, GLenum zpass
)
1443 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1445 R200_STATECHANGE( rmesa
, ctx
);
1446 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~(R200_STENCIL_FAIL_MASK
|
1447 R200_STENCIL_ZFAIL_MASK
|
1448 R200_STENCIL_ZPASS_MASK
);
1450 switch ( ctx
->Stencil
.FailFunc
[0] ) {
1452 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_KEEP
;
1455 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_ZERO
;
1458 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_REPLACE
;
1461 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC
;
1464 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC
;
1466 case GL_INCR_WRAP_EXT
:
1467 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC_WRAP
;
1469 case GL_DECR_WRAP_EXT
:
1470 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC_WRAP
;
1473 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INVERT
;
1477 switch ( ctx
->Stencil
.ZFailFunc
[0] ) {
1479 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_KEEP
;
1482 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_ZERO
;
1485 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_REPLACE
;
1488 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC
;
1491 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC
;
1493 case GL_INCR_WRAP_EXT
:
1494 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC_WRAP
;
1496 case GL_DECR_WRAP_EXT
:
1497 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC_WRAP
;
1500 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INVERT
;
1504 switch ( ctx
->Stencil
.ZPassFunc
[0] ) {
1506 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_KEEP
;
1509 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_ZERO
;
1512 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_REPLACE
;
1515 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC
;
1518 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC
;
1520 case GL_INCR_WRAP_EXT
:
1521 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC_WRAP
;
1523 case GL_DECR_WRAP_EXT
:
1524 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC_WRAP
;
1527 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INVERT
;
1533 /* =============================================================
1534 * Window position and viewport transformation
1538 * Called when window size or position changes or viewport or depth range
1539 * state is changed. We update the hardware viewport state here.
1541 void r200UpdateWindow( struct gl_context
*ctx
)
1543 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1544 __DRIdrawable
*dPriv
= radeon_get_drawable(&rmesa
->radeon
);
1545 GLfloat xoffset
= 0;
1546 GLfloat yoffset
= dPriv
? (GLfloat
) dPriv
->h
: 0;
1547 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1548 const GLboolean render_to_fbo
= (ctx
->DrawBuffer
? _mesa_is_user_fbo(ctx
->DrawBuffer
) : 0);
1549 const GLfloat depthScale
= 1.0F
/ ctx
->DrawBuffer
->_DepthMaxF
;
1550 GLfloat y_scale
, y_bias
;
1552 if (render_to_fbo
) {
1560 float_ui32_type sx
= { v
[MAT_SX
] };
1561 float_ui32_type tx
= { v
[MAT_TX
] + xoffset
};
1562 float_ui32_type sy
= { v
[MAT_SY
] * y_scale
};
1563 float_ui32_type ty
= { (v
[MAT_TY
] * y_scale
) + y_bias
};
1564 float_ui32_type sz
= { v
[MAT_SZ
] * depthScale
};
1565 float_ui32_type tz
= { v
[MAT_TZ
] * depthScale
};
1567 R200_STATECHANGE( rmesa
, vpt
);
1569 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XSCALE
] = sx
.ui32
;
1570 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = tx
.ui32
;
1571 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YSCALE
] = sy
.ui32
;
1572 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = ty
.ui32
;
1573 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZSCALE
] = sz
.ui32
;
1574 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZOFFSET
] = tz
.ui32
;
1577 void r200_vtbl_update_scissor( struct gl_context
*ctx
)
1579 r200ContextPtr r200
= R200_CONTEXT(ctx
);
1580 unsigned x1
, y1
, x2
, y2
;
1581 struct radeon_renderbuffer
*rrb
;
1583 R200_SET_STATE(r200
, set
, SET_RE_CNTL
, R200_SCISSOR_ENABLE
| r200
->hw
.set
.cmd
[SET_RE_CNTL
]);
1585 if (r200
->radeon
.state
.scissor
.enabled
) {
1586 x1
= r200
->radeon
.state
.scissor
.rect
.x1
;
1587 y1
= r200
->radeon
.state
.scissor
.rect
.y1
;
1588 x2
= r200
->radeon
.state
.scissor
.rect
.x2
;
1589 y2
= r200
->radeon
.state
.scissor
.rect
.y2
;
1591 rrb
= radeon_get_colorbuffer(&r200
->radeon
);
1594 x2
= rrb
->base
.Base
.Width
- 1;
1595 y2
= rrb
->base
.Base
.Height
- 1;
1598 R200_SET_STATE(r200
, sci
, SCI_XY_1
, x1
| (y1
<< 16));
1599 R200_SET_STATE(r200
, sci
, SCI_XY_2
, x2
| (y2
<< 16));
1603 static void r200Viewport( struct gl_context
*ctx
, GLint x
, GLint y
,
1604 GLsizei width
, GLsizei height
)
1606 /* Don't pipeline viewport changes, conflict with window offset
1607 * setting below. Could apply deltas to rescue pipelined viewport
1608 * values, or keep the originals hanging around.
1610 r200UpdateWindow( ctx
);
1612 radeon_viewport(ctx
, x
, y
, width
, height
);
1615 static void r200DepthRange( struct gl_context
*ctx
, GLclampd nearval
,
1618 r200UpdateWindow( ctx
);
1621 void r200UpdateViewportOffset( struct gl_context
*ctx
)
1623 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1624 __DRIdrawable
*dPriv
= radeon_get_drawable(&rmesa
->radeon
);
1625 GLfloat xoffset
= (GLfloat
)0;
1626 GLfloat yoffset
= (GLfloat
)dPriv
->h
;
1627 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1632 tx
.f
= v
[MAT_TX
] + xoffset
;
1633 ty
.f
= (- v
[MAT_TY
]) + yoffset
;
1635 if ( rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] != tx
.ui32
||
1636 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] != ty
.ui32
)
1638 /* Note: this should also modify whatever data the context reset
1641 R200_STATECHANGE( rmesa
, vpt
);
1642 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = tx
.ui32
;
1643 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = ty
.ui32
;
1645 /* update polygon stipple x/y screen offset */
1648 GLuint m
= rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
];
1650 m
&= ~(R200_STIPPLE_X_OFFSET_MASK
|
1651 R200_STIPPLE_Y_OFFSET_MASK
);
1653 /* add magic offsets, then invert */
1654 stx
= 31 - ((-1) & R200_STIPPLE_COORD_MASK
);
1655 sty
= 31 - ((dPriv
->h
- 1)
1656 & R200_STIPPLE_COORD_MASK
);
1658 m
|= ((stx
<< R200_STIPPLE_X_OFFSET_SHIFT
) |
1659 (sty
<< R200_STIPPLE_Y_OFFSET_SHIFT
));
1661 if ( rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] != m
) {
1662 R200_STATECHANGE( rmesa
, msc
);
1663 rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] = m
;
1668 radeonUpdateScissor( ctx
);
1673 /* =============================================================
1677 static void r200RenderMode( struct gl_context
*ctx
, GLenum mode
)
1679 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1680 FALLBACK( rmesa
, R200_FALLBACK_RENDER_MODE
, (mode
!= GL_RENDER
) );
1684 static GLuint r200_rop_tab
[] = {
1687 R200_ROP_AND_REVERSE
,
1689 R200_ROP_AND_INVERTED
,
1696 R200_ROP_OR_REVERSE
,
1697 R200_ROP_COPY_INVERTED
,
1698 R200_ROP_OR_INVERTED
,
1703 static void r200LogicOpCode( struct gl_context
*ctx
, GLenum opcode
)
1705 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1706 GLuint rop
= (GLuint
)opcode
- GL_CLEAR
;
1710 R200_STATECHANGE( rmesa
, msk
);
1711 rmesa
->hw
.msk
.cmd
[MSK_RB3D_ROPCNTL
] = r200_rop_tab
[rop
];
1714 /* =============================================================
1715 * State enable/disable
1718 static void r200Enable( struct gl_context
*ctx
, GLenum cap
, GLboolean state
)
1720 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1723 if ( R200_DEBUG
& RADEON_STATE
)
1724 fprintf( stderr
, "%s( %s = %s )\n", __FUNCTION__
,
1725 _mesa_lookup_enum_by_nr( cap
),
1726 state
? "GL_TRUE" : "GL_FALSE" );
1729 /* Fast track this one...
1737 R200_STATECHANGE( rmesa
, ctx
);
1739 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ALPHA_TEST_ENABLE
;
1741 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ALPHA_TEST_ENABLE
;
1746 case GL_COLOR_LOGIC_OP
:
1747 r200_set_blend_state( ctx
);
1750 case GL_CLIP_PLANE0
:
1751 case GL_CLIP_PLANE1
:
1752 case GL_CLIP_PLANE2
:
1753 case GL_CLIP_PLANE3
:
1754 case GL_CLIP_PLANE4
:
1755 case GL_CLIP_PLANE5
:
1756 p
= cap
-GL_CLIP_PLANE0
;
1757 R200_STATECHANGE( rmesa
, tcl
);
1759 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= (R200_UCP_ENABLE_0
<<p
);
1760 r200ClipPlane( ctx
, cap
, NULL
);
1763 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~(R200_UCP_ENABLE_0
<<p
);
1767 case GL_COLOR_MATERIAL
:
1768 r200ColorMaterial( ctx
, 0, 0 );
1769 r200UpdateMaterial( ctx
);
1773 r200CullFace( ctx
, 0 );
1777 R200_STATECHANGE(rmesa
, ctx
);
1779 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_Z_ENABLE
;
1781 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_Z_ENABLE
;
1786 R200_STATECHANGE(rmesa
, ctx
);
1788 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_DITHER_ENABLE
;
1789 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~rmesa
->radeon
.state
.color
.roundEnable
;
1791 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_DITHER_ENABLE
;
1792 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= rmesa
->radeon
.state
.color
.roundEnable
;
1797 R200_STATECHANGE(rmesa
, ctx
);
1799 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_FOG_ENABLE
;
1800 r200Fogfv( ctx
, GL_FOG_MODE
, NULL
);
1802 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_FOG_ENABLE
;
1803 R200_STATECHANGE(rmesa
, tcl
);
1804 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_TCL_FOG_MASK
;
1806 r200UpdateSpecular( ctx
); /* for PK_SPEC */
1807 if (rmesa
->radeon
.TclFallback
)
1808 r200ChooseVertexState( ctx
);
1809 _mesa_allow_light_in_model( ctx
, !state
);
1820 R200_STATECHANGE(rmesa
, tcl
);
1821 p
= cap
- GL_LIGHT0
;
1823 flag
= (R200_LIGHT_1_ENABLE
|
1824 R200_LIGHT_1_ENABLE_AMBIENT
|
1825 R200_LIGHT_1_ENABLE_SPECULAR
);
1827 flag
= (R200_LIGHT_0_ENABLE
|
1828 R200_LIGHT_0_ENABLE_AMBIENT
|
1829 R200_LIGHT_0_ENABLE_SPECULAR
);
1832 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] |= flag
;
1834 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] &= ~flag
;
1838 update_light_colors( ctx
, p
);
1842 r200UpdateSpecular(ctx
);
1843 /* for reflection map fixup - might set recheck_texgen for all units too */
1844 rmesa
->radeon
.NewGLState
|= _NEW_TEXTURE
;
1847 case GL_LINE_SMOOTH
:
1848 R200_STATECHANGE( rmesa
, ctx
);
1850 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_LINE
;
1852 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_LINE
;
1856 case GL_LINE_STIPPLE
:
1857 R200_STATECHANGE( rmesa
, set
);
1859 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_PATTERN_ENABLE
;
1861 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_PATTERN_ENABLE
;
1866 R200_STATECHANGE( rmesa
, tcl
);
1868 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_NORMALIZE_NORMALS
;
1870 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_NORMALIZE_NORMALS
;
1874 /* Pointsize registers on r200 only work for point sprites, and point smooth
1875 * doesn't work for point sprites (and isn't needed for 1.0 sized aa points).
1876 * In any case, setting pointmin == pointsizemax == 1.0 for aa points
1877 * is enough to satisfy conform.
1879 case GL_POINT_SMOOTH
:
1882 /* These don't really do anything, as we don't use the 3vtx
1886 case GL_POLYGON_OFFSET_POINT
:
1887 R200_STATECHANGE( rmesa
, set
);
1889 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_POINT
;
1891 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_POINT
;
1895 case GL_POLYGON_OFFSET_LINE
:
1896 R200_STATECHANGE( rmesa
, set
);
1898 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_LINE
;
1900 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_LINE
;
1905 case GL_POINT_SPRITE_ARB
:
1906 R200_STATECHANGE( rmesa
, spr
);
1909 for (i
= 0; i
< 6; i
++) {
1910 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |=
1911 ctx
->Point
.CoordReplace
[i
] << (R200_PS_GEN_TEX_0_SHIFT
+ i
);
1914 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] &= ~R200_PS_GEN_TEX_MASK
;
1918 case GL_POLYGON_OFFSET_FILL
:
1919 R200_STATECHANGE( rmesa
, set
);
1921 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_TRI
;
1923 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_TRI
;
1927 case GL_POLYGON_SMOOTH
:
1928 R200_STATECHANGE( rmesa
, ctx
);
1930 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_POLY
;
1932 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_POLY
;
1936 case GL_POLYGON_STIPPLE
:
1937 R200_STATECHANGE(rmesa
, set
);
1939 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_STIPPLE_ENABLE
;
1941 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_STIPPLE_ENABLE
;
1945 case GL_RESCALE_NORMAL_EXT
: {
1946 GLboolean tmp
= ctx
->_NeedEyeCoords
? state
: !state
;
1947 R200_STATECHANGE( rmesa
, tcl
);
1949 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
1951 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
1956 case GL_SCISSOR_TEST
:
1957 radeon_firevertices(&rmesa
->radeon
);
1958 rmesa
->radeon
.state
.scissor
.enabled
= state
;
1959 radeonUpdateScissor( ctx
);
1962 case GL_STENCIL_TEST
:
1964 GLboolean hw_stencil
= GL_FALSE
;
1965 if (ctx
->DrawBuffer
) {
1966 struct radeon_renderbuffer
*rrbStencil
1967 = radeon_get_renderbuffer(ctx
->DrawBuffer
, BUFFER_STENCIL
);
1968 hw_stencil
= (rrbStencil
&& rrbStencil
->bo
);
1972 R200_STATECHANGE( rmesa
, ctx
);
1974 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_STENCIL_ENABLE
;
1976 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_STENCIL_ENABLE
;
1979 FALLBACK( rmesa
, R200_FALLBACK_STENCIL
, state
);
1984 case GL_TEXTURE_GEN_Q
:
1985 case GL_TEXTURE_GEN_R
:
1986 case GL_TEXTURE_GEN_S
:
1987 case GL_TEXTURE_GEN_T
:
1988 /* Picked up in r200UpdateTextureState.
1990 rmesa
->recheck_texgen
[ctx
->Texture
.CurrentUnit
] = GL_TRUE
;
1993 case GL_COLOR_SUM_EXT
:
1994 r200UpdateSpecular ( ctx
);
1997 case GL_VERTEX_PROGRAM_ARB
:
2000 rmesa
->curr_vp_hw
= NULL
;
2001 R200_STATECHANGE( rmesa
, vap
);
2002 rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
] &= ~R200_VAP_PROG_VTX_SHADER_ENABLE
;
2003 /* mark all tcl atoms (tcl vector state got overwritten) dirty
2004 not sure about tcl scalar state - we need at least grd
2005 with vert progs too.
2006 ucp looks like it doesn't get overwritten (may even work
2007 with vp for pos-invariant progs if we're lucky) */
2008 R200_STATECHANGE( rmesa
, mtl
[0] );
2009 R200_STATECHANGE( rmesa
, mtl
[1] );
2010 R200_STATECHANGE( rmesa
, fog
);
2011 R200_STATECHANGE( rmesa
, glt
);
2012 R200_STATECHANGE( rmesa
, eye
);
2013 for (i
= R200_MTX_MV
; i
<= R200_MTX_TEX5
; i
++) {
2014 R200_STATECHANGE( rmesa
, mat
[i
] );
2016 for (i
= 0 ; i
< 8; i
++) {
2017 R200_STATECHANGE( rmesa
, lit
[i
] );
2019 R200_STATECHANGE( rmesa
, tcl
);
2020 for (i
= 0; i
<= ctx
->Const
.MaxClipPlanes
; i
++) {
2021 if (ctx
->Transform
.ClipPlanesEnabled
& (1 << i
)) {
2022 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= (R200_UCP_ENABLE_0
<< i
);
2025 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0 << i);
2028 /* ugly. Need to call everything which might change compsel. */
2029 r200UpdateSpecular( ctx
);
2031 /* shouldn't be necessary, as it's picked up anyway in r200ValidateState (_NEW_PROGRAM),
2032 but without it doom3 locks up at always the same places. Why? */
2033 /* FIXME: This can (and should) be replaced by a call to the TCL_STATE_FLUSH reg before
2034 accessing VAP_SE_VAP_CNTL. Requires drm changes (done). Remove after some time... */
2035 r200UpdateTextureState( ctx
);
2036 /* if we call r200UpdateTextureState we need the code below because we are calling it with
2037 non-current derived enabled values which may revert the state atoms for frag progs even when
2038 they already got disabled... ugh
2039 Should really figure out why we need to call r200UpdateTextureState in the first place */
2041 for (unit
= 0; unit
< R200_MAX_TEXTURE_UNITS
; unit
++) {
2042 R200_STATECHANGE( rmesa
, pix
[unit
] );
2043 R200_STATECHANGE( rmesa
, tex
[unit
] );
2044 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] &=
2045 ~(R200_TXFORMAT_ST_ROUTE_MASK
| R200_TXFORMAT_LOOKUP_DISABLE
);
2046 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] |= unit
<< R200_TXFORMAT_ST_ROUTE_SHIFT
;
2047 /* need to guard this with drmSupportsFragmentShader? Should never get here if
2048 we don't announce ATI_fs, right? */
2049 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXMULTI_CTL
] = 0;
2051 R200_STATECHANGE( rmesa
, cst
);
2052 R200_STATECHANGE( rmesa
, tf
);
2053 rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] = 0;
2057 /* picked up later */
2059 /* call functions which change hw state based on ARB_vp enabled or not. */
2060 r200PointParameter( ctx
, GL_POINT_DISTANCE_ATTENUATION
, NULL
);
2061 r200Fogfv( ctx
, GL_FOG_COORD_SRC
, NULL
);
2064 case GL_VERTEX_PROGRAM_POINT_SIZE_ARB
:
2065 r200PointParameter( ctx
, GL_POINT_DISTANCE_ATTENUATION
, NULL
);
2068 case GL_FRAGMENT_SHADER_ATI
:
2070 /* restore normal tex env colors and make sure tex env combine will get updated
2071 mark env atoms dirty (as their data was overwritten by afs even
2072 if they didn't change) and restore tex coord routing */
2074 for (unit
= 0; unit
< R200_MAX_TEXTURE_UNITS
; unit
++) {
2075 R200_STATECHANGE( rmesa
, pix
[unit
] );
2076 R200_STATECHANGE( rmesa
, tex
[unit
] );
2077 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] &=
2078 ~(R200_TXFORMAT_ST_ROUTE_MASK
| R200_TXFORMAT_LOOKUP_DISABLE
);
2079 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] |= unit
<< R200_TXFORMAT_ST_ROUTE_SHIFT
;
2080 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXMULTI_CTL
] = 0;
2082 R200_STATECHANGE( rmesa
, cst
);
2083 R200_STATECHANGE( rmesa
, tf
);
2084 rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] = 0;
2087 /* need to mark this dirty as pix/tf atoms have overwritten the data
2088 even if the data in the atoms didn't change */
2089 R200_STATECHANGE( rmesa
, atf
);
2090 R200_STATECHANGE( rmesa
, afs
[1] );
2091 /* everything else picked up in r200UpdateTextureState hopefully */
2100 void r200LightingSpaceChange( struct gl_context
*ctx
)
2102 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2105 if (R200_DEBUG
& RADEON_STATE
)
2106 fprintf(stderr
, "%s %d BEFORE %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
2107 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
2109 if (ctx
->_NeedEyeCoords
)
2110 tmp
= ctx
->Transform
.RescaleNormals
;
2112 tmp
= !ctx
->Transform
.RescaleNormals
;
2114 R200_STATECHANGE( rmesa
, tcl
);
2116 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
2118 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
2121 if (R200_DEBUG
& RADEON_STATE
)
2122 fprintf(stderr
, "%s %d AFTER %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
2123 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
2126 /* =============================================================
2127 * Deferred state management - matrices, textures, other?
2133 static void upload_matrix( r200ContextPtr rmesa
, GLfloat
*src
, int idx
)
2135 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
2139 for (i
= 0 ; i
< 4 ; i
++) {
2143 *dest
++ = src
[i
+12];
2146 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
2149 static void upload_matrix_t( r200ContextPtr rmesa
, const GLfloat
*src
, int idx
)
2151 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
2152 memcpy(dest
, src
, 16*sizeof(float));
2153 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
2157 static void update_texturematrix( struct gl_context
*ctx
)
2159 r200ContextPtr rmesa
= R200_CONTEXT( ctx
);
2160 GLuint tpc
= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
];
2161 GLuint compsel
= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
];
2164 if (R200_DEBUG
& RADEON_STATE
)
2165 fprintf(stderr
, "%s before COMPSEL: %x\n", __FUNCTION__
,
2166 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]);
2168 rmesa
->TexMatEnabled
= 0;
2169 rmesa
->TexMatCompSel
= 0;
2171 for (unit
= 0 ; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
2172 if (!ctx
->Texture
.Unit
[unit
]._ReallyEnabled
)
2175 if (ctx
->TextureMatrixStack
[unit
].Top
->type
!= MATRIX_IDENTITY
) {
2176 rmesa
->TexMatEnabled
|= (R200_TEXGEN_TEXMAT_0_ENABLE
|
2177 R200_TEXMAT_0_ENABLE
) << unit
;
2179 rmesa
->TexMatCompSel
|= R200_OUTPUT_TEX_0
<< unit
;
2181 if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2182 /* Need to preconcatenate any active texgen
2183 * obj/eyeplane matrices:
2185 _math_matrix_mul_matrix( &rmesa
->tmpmat
,
2186 ctx
->TextureMatrixStack
[unit
].Top
,
2187 &rmesa
->TexGenMatrix
[unit
] );
2188 upload_matrix( rmesa
, rmesa
->tmpmat
.m
, R200_MTX_TEX0
+unit
);
2191 upload_matrix( rmesa
, ctx
->TextureMatrixStack
[unit
].Top
->m
,
2192 R200_MTX_TEX0
+unit
);
2195 else if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2196 upload_matrix( rmesa
, rmesa
->TexGenMatrix
[unit
].m
,
2197 R200_MTX_TEX0
+unit
);
2201 tpc
= (rmesa
->TexMatEnabled
| rmesa
->TexGenEnabled
);
2202 if (tpc
!= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
]) {
2203 R200_STATECHANGE(rmesa
, tcg
);
2204 rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
] = tpc
;
2207 compsel
&= ~R200_OUTPUT_TEX_MASK
;
2208 compsel
|= rmesa
->TexMatCompSel
| rmesa
->TexGenCompSel
;
2209 if (compsel
!= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]) {
2210 R200_STATECHANGE(rmesa
, vtx
);
2211 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] = compsel
;
2215 static GLboolean
r200ValidateBuffers(struct gl_context
*ctx
)
2217 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2218 struct radeon_renderbuffer
*rrb
;
2219 struct radeon_dma_bo
*dma_bo
;
2222 if (RADEON_DEBUG
& RADEON_IOCTL
)
2223 fprintf(stderr
, "%s\n", __FUNCTION__
);
2224 radeon_cs_space_reset_bos(rmesa
->radeon
.cmdbuf
.cs
);
2226 rrb
= radeon_get_colorbuffer(&rmesa
->radeon
);
2228 if (rrb
&& rrb
->bo
) {
2229 radeon_cs_space_add_persistent_bo(rmesa
->radeon
.cmdbuf
.cs
, rrb
->bo
,
2230 0, RADEON_GEM_DOMAIN_VRAM
);
2234 rrb
= radeon_get_depthbuffer(&rmesa
->radeon
);
2236 if (rrb
&& rrb
->bo
) {
2237 radeon_cs_space_add_persistent_bo(rmesa
->radeon
.cmdbuf
.cs
, rrb
->bo
,
2238 0, RADEON_GEM_DOMAIN_VRAM
);
2241 for (i
= 0; i
< ctx
->Const
.FragmentProgram
.MaxTextureImageUnits
; ++i
) {
2244 if (!ctx
->Texture
.Unit
[i
]._ReallyEnabled
)
2247 t
= radeon_tex_obj(ctx
->Texture
.Unit
[i
]._Current
);
2248 if (t
->image_override
&& t
->bo
)
2249 radeon_cs_space_add_persistent_bo(rmesa
->radeon
.cmdbuf
.cs
, t
->bo
,
2250 RADEON_GEM_DOMAIN_GTT
| RADEON_GEM_DOMAIN_VRAM
, 0);
2252 radeon_cs_space_add_persistent_bo(rmesa
->radeon
.cmdbuf
.cs
, t
->mt
->bo
,
2253 RADEON_GEM_DOMAIN_GTT
| RADEON_GEM_DOMAIN_VRAM
, 0);
2256 dma_bo
= first_elem(&rmesa
->radeon
.dma
.reserved
);
2258 ret
= radeon_cs_space_check_with_bo(rmesa
->radeon
.cmdbuf
.cs
, dma_bo
->bo
, RADEON_GEM_DOMAIN_GTT
, 0);
2265 GLboolean
r200ValidateState( struct gl_context
*ctx
)
2267 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2268 GLuint new_state
= rmesa
->radeon
.NewGLState
;
2270 if (new_state
& _NEW_BUFFERS
) {
2271 _mesa_update_framebuffer(ctx
);
2272 /* this updates the DrawBuffer's Width/Height if it's a FBO */
2273 _mesa_update_draw_buffer_bounds(ctx
);
2275 R200_STATECHANGE(rmesa
, ctx
);
2278 if (new_state
& (_NEW_TEXTURE
| _NEW_PROGRAM
| _NEW_PROGRAM_CONSTANTS
)) {
2279 r200UpdateTextureState( ctx
);
2280 new_state
|= rmesa
->radeon
.NewGLState
; /* may add TEXTURE_MATRIX */
2281 r200UpdateLocalViewer( ctx
);
2284 /* we need to do a space check here */
2285 if (!r200ValidateBuffers(ctx
))
2288 /* FIXME: don't really need most of these when vertex progs are enabled */
2290 /* Need an event driven matrix update?
2292 if (new_state
& (_NEW_MODELVIEW
|_NEW_PROJECTION
))
2293 upload_matrix( rmesa
, ctx
->_ModelProjectMatrix
.m
, R200_MTX_MVP
);
2295 /* Need these for lighting (shouldn't upload otherwise)
2297 if (new_state
& (_NEW_MODELVIEW
)) {
2298 upload_matrix( rmesa
, ctx
->ModelviewMatrixStack
.Top
->m
, R200_MTX_MV
);
2299 upload_matrix_t( rmesa
, ctx
->ModelviewMatrixStack
.Top
->inv
, R200_MTX_IMV
);
2302 /* Does this need to be triggered on eg. modelview for
2303 * texgen-derived objplane/eyeplane matrices?
2305 if (new_state
& (_NEW_TEXTURE
|_NEW_TEXTURE_MATRIX
)) {
2306 update_texturematrix( ctx
);
2309 if (new_state
& (_NEW_LIGHT
|_NEW_MODELVIEW
|_MESA_NEW_NEED_EYE_COORDS
)) {
2310 update_light( ctx
);
2313 /* emit all active clip planes if projection matrix changes.
2315 if (new_state
& (_NEW_PROJECTION
)) {
2316 if (ctx
->Transform
.ClipPlanesEnabled
)
2317 r200UpdateClipPlanes( ctx
);
2320 if (new_state
& (_NEW_PROGRAM
|
2321 _NEW_PROGRAM_CONSTANTS
|
2322 /* need to test for pretty much anything due to possible parameter bindings */
2323 _NEW_MODELVIEW
|_NEW_PROJECTION
|_NEW_TRANSFORM
|
2324 _NEW_LIGHT
|_NEW_TEXTURE
|_NEW_TEXTURE_MATRIX
|
2325 _NEW_FOG
|_NEW_POINT
|_NEW_TRACK_MATRIX
)) {
2326 if (ctx
->VertexProgram
._Enabled
) {
2327 r200SetupVertexProg( ctx
);
2329 else TCL_FALLBACK(ctx
, R200_TCL_FALLBACK_VERTEX_PROGRAM
, 0);
2332 rmesa
->radeon
.NewGLState
= 0;
2337 static void r200InvalidateState( struct gl_context
*ctx
, GLuint new_state
)
2339 _swrast_InvalidateState( ctx
, new_state
);
2340 _swsetup_InvalidateState( ctx
, new_state
);
2341 _vbo_InvalidateState( ctx
, new_state
);
2342 _tnl_InvalidateState( ctx
, new_state
);
2343 _ae_invalidate_state( ctx
, new_state
);
2344 R200_CONTEXT(ctx
)->radeon
.NewGLState
|= new_state
;
2347 /* A hack. The r200 can actually cope just fine with materials
2348 * between begin/ends, so fix this.
2349 * Should map to inputs just like the generic vertex arrays for vertex progs.
2350 * In theory there could still be too many and we'd still need a fallback.
2352 static GLboolean
check_material( struct gl_context
*ctx
)
2354 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
2357 for (i
= _TNL_ATTRIB_MAT_FRONT_AMBIENT
;
2358 i
< _TNL_ATTRIB_MAT_BACK_INDEXES
;
2360 if (tnl
->vb
.AttribPtr
[i
] &&
2361 tnl
->vb
.AttribPtr
[i
]->stride
)
2367 static void r200WrapRunPipeline( struct gl_context
*ctx
)
2369 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2370 GLboolean has_material
;
2373 fprintf(stderr
, "%s, newstate: %x\n", __FUNCTION__
, rmesa
->radeon
.NewGLState
);
2377 if (rmesa
->radeon
.NewGLState
)
2378 if (!r200ValidateState( ctx
))
2379 FALLBACK(rmesa
, RADEON_FALLBACK_TEXTURE
, GL_TRUE
);
2381 has_material
= !ctx
->VertexProgram
._Enabled
&& ctx
->Light
.Enabled
&& check_material( ctx
);
2384 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_TRUE
);
2387 /* Run the pipeline.
2389 _tnl_run_pipeline( ctx
);
2392 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_FALSE
);
2397 static void r200PolygonStipple( struct gl_context
*ctx
, const GLubyte
*mask
)
2399 r200ContextPtr r200
= R200_CONTEXT(ctx
);
2402 radeon_firevertices(&r200
->radeon
);
2404 radeon_print(RADEON_STATE
, RADEON_TRACE
,
2405 "%s(%p) first 32 bits are %x.\n",
2410 R200_STATECHANGE(r200
, stp
);
2412 /* Must flip pattern upside down.
2414 for ( i
= 31 ; i
>= 0; i
--) {
2415 r200
->hw
.stp
.cmd
[3 + i
] = ((GLuint
*) mask
)[i
];
2418 /* Initialize the driver's state functions.
2420 void r200InitStateFuncs( radeonContextPtr radeon
, struct dd_function_table
*functions
)
2422 functions
->UpdateState
= r200InvalidateState
;
2423 functions
->LightingSpaceChange
= r200LightingSpaceChange
;
2425 functions
->DrawBuffer
= radeonDrawBuffer
;
2426 functions
->ReadBuffer
= radeonReadBuffer
;
2428 functions
->CopyPixels
= _mesa_meta_CopyPixels
;
2429 functions
->DrawPixels
= _mesa_meta_DrawPixels
;
2430 functions
->ReadPixels
= radeonReadPixels
;
2432 functions
->AlphaFunc
= r200AlphaFunc
;
2433 functions
->BlendColor
= r200BlendColor
;
2434 functions
->BlendEquationSeparate
= r200BlendEquationSeparate
;
2435 functions
->BlendFuncSeparate
= r200BlendFuncSeparate
;
2436 functions
->ClipPlane
= r200ClipPlane
;
2437 functions
->ColorMask
= r200ColorMask
;
2438 functions
->CullFace
= r200CullFace
;
2439 functions
->DepthFunc
= r200DepthFunc
;
2440 functions
->DepthMask
= r200DepthMask
;
2441 functions
->DepthRange
= r200DepthRange
;
2442 functions
->Enable
= r200Enable
;
2443 functions
->Fogfv
= r200Fogfv
;
2444 functions
->FrontFace
= r200FrontFace
;
2445 functions
->Hint
= NULL
;
2446 functions
->LightModelfv
= r200LightModelfv
;
2447 functions
->Lightfv
= r200Lightfv
;
2448 functions
->LineStipple
= r200LineStipple
;
2449 functions
->LineWidth
= r200LineWidth
;
2450 functions
->LogicOpcode
= r200LogicOpCode
;
2451 functions
->PolygonMode
= r200PolygonMode
;
2452 functions
->PolygonOffset
= r200PolygonOffset
;
2453 functions
->PolygonStipple
= r200PolygonStipple
;
2454 functions
->PointParameterfv
= r200PointParameter
;
2455 functions
->PointSize
= r200PointSize
;
2456 functions
->RenderMode
= r200RenderMode
;
2457 functions
->Scissor
= radeonScissor
;
2458 functions
->ShadeModel
= r200ShadeModel
;
2459 functions
->StencilFuncSeparate
= r200StencilFuncSeparate
;
2460 functions
->StencilMaskSeparate
= r200StencilMaskSeparate
;
2461 functions
->StencilOpSeparate
= r200StencilOpSeparate
;
2462 functions
->Viewport
= r200Viewport
;
2466 void r200InitTnlFuncs( struct gl_context
*ctx
)
2468 TNL_CONTEXT(ctx
)->Driver
.NotifyMaterialChange
= r200UpdateMaterial
;
2469 TNL_CONTEXT(ctx
)->Driver
.RunPipeline
= r200WrapRunPipeline
;