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"
44 #include "swrast/swrast.h"
47 #include "tnl/t_pipeline.h"
48 #include "swrast_setup/swrast_setup.h"
49 #include "drivers/common/meta.h"
51 #include "radeon_common.h"
52 #include "radeon_mipmap_tree.h"
53 #include "r200_context.h"
54 #include "r200_ioctl.h"
55 #include "r200_state.h"
58 #include "r200_swtcl.h"
59 #include "r200_vertprog.h"
62 /* =============================================================
66 static void r200AlphaFunc( GLcontext
*ctx
, GLenum func
, GLfloat ref
)
68 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
69 int pp_misc
= rmesa
->hw
.ctx
.cmd
[CTX_PP_MISC
];
72 CLAMPED_FLOAT_TO_UBYTE(refByte
, ref
);
74 R200_STATECHANGE( rmesa
, ctx
);
76 pp_misc
&= ~(R200_ALPHA_TEST_OP_MASK
| R200_REF_ALPHA_MASK
);
77 pp_misc
|= (refByte
& R200_REF_ALPHA_MASK
);
81 pp_misc
|= R200_ALPHA_TEST_FAIL
;
84 pp_misc
|= R200_ALPHA_TEST_LESS
;
87 pp_misc
|= R200_ALPHA_TEST_EQUAL
;
90 pp_misc
|= R200_ALPHA_TEST_LEQUAL
;
93 pp_misc
|= R200_ALPHA_TEST_GREATER
;
96 pp_misc
|= R200_ALPHA_TEST_NEQUAL
;
99 pp_misc
|= R200_ALPHA_TEST_GEQUAL
;
102 pp_misc
|= R200_ALPHA_TEST_PASS
;
106 rmesa
->hw
.ctx
.cmd
[CTX_PP_MISC
] = pp_misc
;
109 static void r200BlendColor( GLcontext
*ctx
, const GLfloat cf
[4] )
112 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
113 R200_STATECHANGE( rmesa
, ctx
);
114 CLAMPED_FLOAT_TO_UBYTE(color
[0], cf
[0]);
115 CLAMPED_FLOAT_TO_UBYTE(color
[1], cf
[1]);
116 CLAMPED_FLOAT_TO_UBYTE(color
[2], cf
[2]);
117 CLAMPED_FLOAT_TO_UBYTE(color
[3], cf
[3]);
118 if (rmesa
->radeon
.radeonScreen
->drmSupportsBlendColor
)
119 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCOLOR
] = radeonPackColor( 4, color
[0], color
[1], color
[2], color
[3] );
123 * Calculate the hardware blend factor setting. This same function is used
124 * for source and destination of both alpha and RGB.
127 * The hardware register value for the specified blend factor. This value
128 * will need to be shifted into the correct position for either source or
129 * destination factor.
132 * Since the two cases where source and destination are handled differently
133 * are essentially error cases, they should never happen. Determine if these
134 * cases can be removed.
136 static int blend_factor( GLenum factor
, GLboolean is_src
)
142 func
= R200_BLEND_GL_ZERO
;
145 func
= R200_BLEND_GL_ONE
;
148 func
= R200_BLEND_GL_DST_COLOR
;
150 case GL_ONE_MINUS_DST_COLOR
:
151 func
= R200_BLEND_GL_ONE_MINUS_DST_COLOR
;
154 func
= R200_BLEND_GL_SRC_COLOR
;
156 case GL_ONE_MINUS_SRC_COLOR
:
157 func
= R200_BLEND_GL_ONE_MINUS_SRC_COLOR
;
160 func
= R200_BLEND_GL_SRC_ALPHA
;
162 case GL_ONE_MINUS_SRC_ALPHA
:
163 func
= R200_BLEND_GL_ONE_MINUS_SRC_ALPHA
;
166 func
= R200_BLEND_GL_DST_ALPHA
;
168 case GL_ONE_MINUS_DST_ALPHA
:
169 func
= R200_BLEND_GL_ONE_MINUS_DST_ALPHA
;
171 case GL_SRC_ALPHA_SATURATE
:
172 func
= (is_src
) ? R200_BLEND_GL_SRC_ALPHA_SATURATE
: R200_BLEND_GL_ZERO
;
174 case GL_CONSTANT_COLOR
:
175 func
= R200_BLEND_GL_CONST_COLOR
;
177 case GL_ONE_MINUS_CONSTANT_COLOR
:
178 func
= R200_BLEND_GL_ONE_MINUS_CONST_COLOR
;
180 case GL_CONSTANT_ALPHA
:
181 func
= R200_BLEND_GL_CONST_ALPHA
;
183 case GL_ONE_MINUS_CONSTANT_ALPHA
:
184 func
= R200_BLEND_GL_ONE_MINUS_CONST_ALPHA
;
187 func
= (is_src
) ? R200_BLEND_GL_ONE
: R200_BLEND_GL_ZERO
;
193 * Sets both the blend equation and the blend function.
194 * This is done in a single
195 * function because some blend equations (i.e., \c GL_MIN and \c GL_MAX)
196 * change the interpretation of the blend function.
197 * Also, make sure that blend function and blend equation are set to their default
198 * value if color blending is not enabled, since at least blend equations GL_MIN
199 * and GL_FUNC_REVERSE_SUBTRACT will cause wrong results otherwise for
202 static void r200_set_blend_state( GLcontext
* ctx
)
204 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
205 GLuint cntl
= rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &
206 ~(R200_ROP_ENABLE
| R200_ALPHA_BLEND_ENABLE
| R200_SEPARATE_ALPHA_ENABLE
);
208 int func
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
209 (R200_BLEND_GL_ZERO
<< R200_DST_BLEND_SHIFT
);
210 int eqn
= R200_COMB_FCN_ADD_CLAMP
;
211 int funcA
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
212 (R200_BLEND_GL_ZERO
<< R200_DST_BLEND_SHIFT
);
213 int eqnA
= R200_COMB_FCN_ADD_CLAMP
;
215 R200_STATECHANGE( rmesa
, ctx
);
217 if (rmesa
->radeon
.radeonScreen
->drmSupportsBlendColor
) {
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
;
234 if (ctx
->Color
.ColorLogicOpEnabled
) {
235 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
| R200_ROP_ENABLE
;
236 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] = eqn
| func
;
238 } else if (ctx
->Color
.BlendEnabled
) {
239 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
| R200_ALPHA_BLEND_ENABLE
;
242 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
;
243 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] = eqn
| func
;
248 func
= (blend_factor( ctx
->Color
.BlendSrcRGB
, GL_TRUE
) << R200_SRC_BLEND_SHIFT
) |
249 (blend_factor( ctx
->Color
.BlendDstRGB
, GL_FALSE
) << R200_DST_BLEND_SHIFT
);
251 switch(ctx
->Color
.BlendEquationRGB
) {
253 eqn
= R200_COMB_FCN_ADD_CLAMP
;
256 case GL_FUNC_SUBTRACT
:
257 eqn
= R200_COMB_FCN_SUB_CLAMP
;
260 case GL_FUNC_REVERSE_SUBTRACT
:
261 eqn
= R200_COMB_FCN_RSUB_CLAMP
;
265 eqn
= R200_COMB_FCN_MIN
;
266 func
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
267 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
271 eqn
= R200_COMB_FCN_MAX
;
272 func
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
273 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
277 fprintf( stderr
, "[%s:%u] Invalid RGB blend equation (0x%04x).\n",
278 __FUNCTION__
, __LINE__
, ctx
->Color
.BlendEquationRGB
);
282 if (!rmesa
->radeon
.radeonScreen
->drmSupportsBlendColor
) {
283 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] = eqn
| func
;
287 funcA
= (blend_factor( ctx
->Color
.BlendSrcA
, GL_TRUE
) << R200_SRC_BLEND_SHIFT
) |
288 (blend_factor( ctx
->Color
.BlendDstA
, GL_FALSE
) << R200_DST_BLEND_SHIFT
);
290 switch(ctx
->Color
.BlendEquationA
) {
292 eqnA
= R200_COMB_FCN_ADD_CLAMP
;
295 case GL_FUNC_SUBTRACT
:
296 eqnA
= R200_COMB_FCN_SUB_CLAMP
;
299 case GL_FUNC_REVERSE_SUBTRACT
:
300 eqnA
= R200_COMB_FCN_RSUB_CLAMP
;
304 eqnA
= R200_COMB_FCN_MIN
;
305 funcA
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
306 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
310 eqnA
= R200_COMB_FCN_MAX
;
311 funcA
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
312 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
316 fprintf( stderr
, "[%s:%u] Invalid A blend equation (0x%04x).\n",
317 __FUNCTION__
, __LINE__
, ctx
->Color
.BlendEquationA
);
321 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ABLENDCNTL
] = eqnA
| funcA
;
322 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CBLENDCNTL
] = eqn
| func
;
326 static void r200BlendEquationSeparate( GLcontext
*ctx
,
327 GLenum modeRGB
, GLenum modeA
)
329 r200_set_blend_state( ctx
);
332 static void r200BlendFuncSeparate( GLcontext
*ctx
,
333 GLenum sfactorRGB
, GLenum dfactorRGB
,
334 GLenum sfactorA
, GLenum dfactorA
)
336 r200_set_blend_state( ctx
);
340 /* =============================================================
344 static void r200DepthFunc( GLcontext
*ctx
, GLenum func
)
346 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
348 R200_STATECHANGE( rmesa
, ctx
);
349 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_Z_TEST_MASK
;
351 switch ( ctx
->Depth
.Func
) {
353 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_NEVER
;
356 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_LESS
;
359 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_EQUAL
;
362 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_LEQUAL
;
365 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_GREATER
;
368 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_NEQUAL
;
371 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_GEQUAL
;
374 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_ALWAYS
;
379 static void r200ClearDepth( GLcontext
*ctx
, GLclampd d
)
381 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
382 GLuint format
= (rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &
383 R200_DEPTH_FORMAT_MASK
);
386 case R200_DEPTH_FORMAT_16BIT_INT_Z
:
387 rmesa
->radeon
.state
.depth
.clear
= d
* 0x0000ffff;
389 case R200_DEPTH_FORMAT_24BIT_INT_Z
:
390 rmesa
->radeon
.state
.depth
.clear
= d
* 0x00ffffff;
395 static void r200DepthMask( GLcontext
*ctx
, GLboolean flag
)
397 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
398 R200_STATECHANGE( rmesa
, ctx
);
400 if ( ctx
->Depth
.Mask
) {
401 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_WRITE_ENABLE
;
403 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_Z_WRITE_ENABLE
;
408 /* =============================================================
413 static void r200Fogfv( GLcontext
*ctx
, GLenum pname
, const GLfloat
*param
)
415 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
416 union { int i
; float f
; } c
, d
;
420 c
.i
= rmesa
->hw
.fog
.cmd
[FOG_C
];
421 d
.i
= rmesa
->hw
.fog
.cmd
[FOG_D
];
425 if (!ctx
->Fog
.Enabled
)
427 R200_STATECHANGE(rmesa
, tcl
);
428 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_TCL_FOG_MASK
;
429 switch (ctx
->Fog
.Mode
) {
431 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_LINEAR
;
432 if (ctx
->Fog
.Start
== ctx
->Fog
.End
) {
437 c
.f
= ctx
->Fog
.End
/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
438 d
.f
= -1.0/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
442 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_EXP
;
444 d
.f
= -ctx
->Fog
.Density
;
447 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_EXP2
;
449 d
.f
= -(ctx
->Fog
.Density
* ctx
->Fog
.Density
);
456 switch (ctx
->Fog
.Mode
) {
459 d
.f
= -ctx
->Fog
.Density
;
463 d
.f
= -(ctx
->Fog
.Density
* ctx
->Fog
.Density
);
471 if (ctx
->Fog
.Mode
== GL_LINEAR
) {
472 if (ctx
->Fog
.Start
== ctx
->Fog
.End
) {
476 c
.f
= ctx
->Fog
.End
/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
477 d
.f
= -1.0/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
482 R200_STATECHANGE( rmesa
, ctx
);
483 UNCLAMPED_FLOAT_TO_RGB_CHAN( col
, ctx
->Fog
.Color
);
484 i
= radeonPackColor( 4, col
[0], col
[1], col
[2], 0 );
485 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] &= ~R200_FOG_COLOR_MASK
;
486 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] |= i
;
488 case GL_FOG_COORD_SRC
: {
489 GLuint out_0
= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
];
490 GLuint fog
= rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
];
492 fog
&= ~R200_FOG_USE_MASK
;
493 if ( ctx
->Fog
.FogCoordinateSource
== GL_FOG_COORD
|| ctx
->VertexProgram
.Enabled
) {
494 fog
|= R200_FOG_USE_VTX_FOG
;
495 out_0
|= R200_VTX_DISCRETE_FOG
;
498 fog
|= R200_FOG_USE_SPEC_ALPHA
;
499 out_0
&= ~R200_VTX_DISCRETE_FOG
;
502 if ( fog
!= rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] ) {
503 R200_STATECHANGE( rmesa
, ctx
);
504 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] = fog
;
507 if (out_0
!= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
]) {
508 R200_STATECHANGE( rmesa
, vtx
);
509 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] = out_0
;
518 if (c
.i
!= rmesa
->hw
.fog
.cmd
[FOG_C
] || d
.i
!= rmesa
->hw
.fog
.cmd
[FOG_D
]) {
519 R200_STATECHANGE( rmesa
, fog
);
520 rmesa
->hw
.fog
.cmd
[FOG_C
] = c
.i
;
521 rmesa
->hw
.fog
.cmd
[FOG_D
] = d
.i
;
525 /* =============================================================
529 static void r200CullFace( GLcontext
*ctx
, GLenum unused
)
531 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
532 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
533 GLuint t
= rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
];
535 s
|= R200_FFACE_SOLID
| R200_BFACE_SOLID
;
536 t
&= ~(R200_CULL_FRONT
| R200_CULL_BACK
);
538 if ( ctx
->Polygon
.CullFlag
) {
539 switch ( ctx
->Polygon
.CullFaceMode
) {
541 s
&= ~R200_FFACE_SOLID
;
542 t
|= R200_CULL_FRONT
;
545 s
&= ~R200_BFACE_SOLID
;
548 case GL_FRONT_AND_BACK
:
549 s
&= ~(R200_FFACE_SOLID
| R200_BFACE_SOLID
);
550 t
|= (R200_CULL_FRONT
| R200_CULL_BACK
);
555 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
556 R200_STATECHANGE(rmesa
, set
);
557 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
560 if ( rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] != t
) {
561 R200_STATECHANGE(rmesa
, tcl
);
562 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] = t
;
566 static void r200FrontFace( GLcontext
*ctx
, GLenum mode
)
568 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
570 R200_STATECHANGE( rmesa
, set
);
571 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_FFACE_CULL_DIR_MASK
;
573 R200_STATECHANGE( rmesa
, tcl
);
574 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_CULL_FRONT_IS_CCW
;
576 /* Winding is inverted when rendering to FBO */
577 if (ctx
->DrawBuffer
&& ctx
->DrawBuffer
->Name
)
578 mode
= (mode
== GL_CW
) ? GL_CCW
: GL_CW
;
582 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_FFACE_CULL_CW
;
585 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_FFACE_CULL_CCW
;
586 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_CULL_FRONT_IS_CCW
;
591 /* =============================================================
594 static void r200PointSize( GLcontext
*ctx
, GLfloat size
)
596 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
597 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.ptp
.cmd
;
599 radeon_print(RADEON_STATE
, RADEON_TRACE
,
600 "%s(%p) size: %f, fixed point result: %d.%d (%d/16)\n",
602 ((GLuint
)(ctx
->Point
.Size
* 16.0))/16,
603 (((GLuint
)(ctx
->Point
.Size
* 16.0))&15)*100/16,
604 ((GLuint
)(ctx
->Point
.Size
* 16.0))&15);
606 R200_STATECHANGE( rmesa
, cst
);
607 R200_STATECHANGE( rmesa
, ptp
);
608 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] &= ~0xffff;
609 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] |= ((GLuint
)(ctx
->Point
.Size
* 16.0));
610 /* this is the size param of the point size calculation (point size reg value
611 is not used when calculation is active). */
612 fcmd
[PTP_VPORT_SCALE_PTSIZE
] = ctx
->Point
.Size
;
615 static void r200PointParameter( GLcontext
*ctx
, GLenum pname
, const GLfloat
*params
)
617 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
618 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.ptp
.cmd
;
621 case GL_POINT_SIZE_MIN
:
622 /* Can clamp both in tcl and setup - just set both (as does fglrx) */
623 R200_STATECHANGE( rmesa
, lin
);
624 R200_STATECHANGE( rmesa
, ptp
);
625 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] &= 0xffff;
626 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] |= (GLuint
)(ctx
->Point
.MinSize
* 16.0) << 16;
627 fcmd
[PTP_CLAMP_MIN
] = ctx
->Point
.MinSize
;
629 case GL_POINT_SIZE_MAX
:
630 R200_STATECHANGE( rmesa
, cst
);
631 R200_STATECHANGE( rmesa
, ptp
);
632 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] &= 0xffff;
633 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] |= (GLuint
)(ctx
->Point
.MaxSize
* 16.0) << 16;
634 fcmd
[PTP_CLAMP_MAX
] = ctx
->Point
.MaxSize
;
636 case GL_POINT_DISTANCE_ATTENUATION
:
637 R200_STATECHANGE( rmesa
, vtx
);
638 R200_STATECHANGE( rmesa
, spr
);
639 R200_STATECHANGE( rmesa
, ptp
);
640 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.ptp
.cmd
;
641 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] &=
642 ~(R200_PS_MULT_MASK
| R200_PS_LIN_ATT_ZERO
| R200_PS_SE_SEL_STATE
);
643 /* can't rely on ctx->Point._Attenuated here and test for NEW_POINT in
644 r200ValidateState looks like overkill */
645 if (ctx
->Point
.Params
[0] != 1.0 ||
646 ctx
->Point
.Params
[1] != 0.0 ||
647 ctx
->Point
.Params
[2] != 0.0 ||
648 (ctx
->VertexProgram
.Enabled
&& ctx
->VertexProgram
.PointSizeEnabled
)) {
649 /* all we care for vp would be the ps_se_sel_state setting */
650 fcmd
[PTP_ATT_CONST_QUAD
] = ctx
->Point
.Params
[2];
651 fcmd
[PTP_ATT_CONST_LIN
] = ctx
->Point
.Params
[1];
652 fcmd
[PTP_ATT_CONST_CON
] = ctx
->Point
.Params
[0];
653 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |= R200_PS_MULT_ATTENCONST
;
654 if (ctx
->Point
.Params
[1] == 0.0)
655 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |= R200_PS_LIN_ATT_ZERO
;
656 /* FIXME: setting this here doesn't look quite ok - we only want to do
657 that if we're actually drawing points probably */
658 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_PT_SIZE
;
659 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |= R200_VTX_POINT_SIZE
;
662 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |=
663 R200_PS_SE_SEL_STATE
| R200_PS_MULT_CONST
;
664 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_PT_SIZE
;
665 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~R200_VTX_POINT_SIZE
;
668 case GL_POINT_FADE_THRESHOLD_SIZE
:
669 /* don't support multisampling, so doesn't matter. */
671 /* can't do these but don't need them.
672 case GL_POINT_SPRITE_R_MODE_NV:
673 case GL_POINT_SPRITE_COORD_ORIGIN: */
675 fprintf(stderr
, "bad pname parameter in r200PointParameter\n");
680 /* =============================================================
683 static void r200LineWidth( GLcontext
*ctx
, GLfloat widthf
)
685 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
687 R200_STATECHANGE( rmesa
, lin
);
688 R200_STATECHANGE( rmesa
, set
);
690 /* Line width is stored in U6.4 format.
691 * Same min/max limits for AA, non-AA lines.
693 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] &= ~0xffff;
694 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] |= (GLuint
)
695 (CLAMP(widthf
, ctx
->Const
.MinLineWidth
, ctx
->Const
.MaxLineWidth
) * 16.0);
697 if ( widthf
> 1.0 ) {
698 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_WIDELINE_ENABLE
;
700 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_WIDELINE_ENABLE
;
704 static void r200LineStipple( GLcontext
*ctx
, GLint factor
, GLushort pattern
)
706 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
708 R200_STATECHANGE( rmesa
, lin
);
709 rmesa
->hw
.lin
.cmd
[LIN_RE_LINE_PATTERN
] =
710 ((((GLuint
)factor
& 0xff) << 16) | ((GLuint
)pattern
));
714 /* =============================================================
717 static void r200ColorMask( GLcontext
*ctx
,
718 GLboolean r
, GLboolean g
,
719 GLboolean b
, GLboolean a
)
721 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
723 struct radeon_renderbuffer
*rrb
;
724 GLuint flag
= rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] & ~R200_PLANE_MASK_ENABLE
;
726 rrb
= radeon_get_colorbuffer(&rmesa
->radeon
);
729 mask
= radeonPackColor( rrb
->cpp
,
730 ctx
->Color
.ColorMask
[0][RCOMP
],
731 ctx
->Color
.ColorMask
[0][GCOMP
],
732 ctx
->Color
.ColorMask
[0][BCOMP
],
733 ctx
->Color
.ColorMask
[0][ACOMP
] );
736 if (!(r
&& g
&& b
&& a
))
737 flag
|= R200_PLANE_MASK_ENABLE
;
739 if ( rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] != flag
) {
740 R200_STATECHANGE( rmesa
, ctx
);
741 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = flag
;
744 if ( rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
] != mask
) {
745 R200_STATECHANGE( rmesa
, msk
);
746 rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
] = mask
;
751 /* =============================================================
755 static void r200PolygonOffset( GLcontext
*ctx
,
756 GLfloat factor
, GLfloat units
)
758 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
759 const GLfloat depthScale
= 1.0F
/ ctx
->DrawBuffer
->_DepthMaxF
;
760 float_ui32_type constant
= { units
* depthScale
};
761 float_ui32_type factoru
= { factor
};
766 /* fprintf(stderr, "%s f:%f u:%f\n", __FUNCTION__, factor, constant); */
768 R200_STATECHANGE( rmesa
, zbs
);
769 rmesa
->hw
.zbs
.cmd
[ZBS_SE_ZBIAS_FACTOR
] = factoru
.ui32
;
770 rmesa
->hw
.zbs
.cmd
[ZBS_SE_ZBIAS_CONSTANT
] = constant
.ui32
;
773 static void r200PolygonMode( GLcontext
*ctx
, GLenum face
, GLenum mode
)
775 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
776 GLboolean flag
= (ctx
->_TriangleCaps
& DD_TRI_UNFILLED
) != 0;
778 /* Can't generally do unfilled via tcl, but some good special
781 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_UNFILLED
, flag
);
782 if (rmesa
->radeon
.TclFallback
) {
783 r200ChooseRenderState( ctx
);
784 r200ChooseVertexState( ctx
);
789 /* =============================================================
790 * Rendering attributes
792 * We really don't want to recalculate all this every time we bind a
793 * texture. These things shouldn't change all that often, so it makes
794 * sense to break them out of the core texture state update routines.
797 /* Examine lighting and texture state to determine if separate specular
800 static void r200UpdateSpecular( GLcontext
*ctx
)
802 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
803 uint32_t p
= rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
];
805 R200_STATECHANGE( rmesa
, tcl
);
806 R200_STATECHANGE( rmesa
, vtx
);
808 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~(3<<R200_VTX_COLOR_0_SHIFT
);
809 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~(3<<R200_VTX_COLOR_1_SHIFT
);
810 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_COLOR_0
;
811 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_COLOR_1
;
812 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LIGHTING_ENABLE
;
814 p
&= ~R200_SPECULAR_ENABLE
;
816 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_DIFFUSE_SPECULAR_COMBINE
;
819 if (ctx
->Light
.Enabled
&&
820 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
) {
821 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
822 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
) |
823 (R200_VTX_FP_RGBA
<< 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
;
827 p
|= R200_SPECULAR_ENABLE
;
828 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &=
829 ~R200_DIFFUSE_SPECULAR_COMBINE
;
831 else if (ctx
->Light
.Enabled
) {
832 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
833 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
));
834 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_0
;
835 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHTING_ENABLE
;
836 } else if (ctx
->Fog
.ColorSumEnabled
) {
837 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
838 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
) |
839 (R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
840 p
|= R200_SPECULAR_ENABLE
;
842 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
843 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
));
846 if (ctx
->Fog
.Enabled
) {
847 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
848 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
849 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_1
;
852 if ( rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] != p
) {
853 R200_STATECHANGE( rmesa
, ctx
);
854 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] = p
;
857 /* Update vertex/render formats
859 if (rmesa
->radeon
.TclFallback
) {
860 r200ChooseRenderState( ctx
);
861 r200ChooseVertexState( ctx
);
866 /* =============================================================
871 /* Update on colormaterial, material emmissive/ambient,
872 * lightmodel.globalambient
874 static void update_global_ambient( GLcontext
*ctx
)
876 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
877 float *fcmd
= (float *)R200_DB_STATE( glt
);
879 /* Need to do more if both emmissive & ambient are PREMULT:
880 * I believe this is not nessary when using source_material. This condition thus
881 * will never happen currently, and the function has no dependencies on materials now
883 if ((rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
] &
884 ((3 << R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
885 (3 << R200_FRONT_AMBIENT_SOURCE_SHIFT
))) == 0)
887 COPY_3V( &fcmd
[GLT_RED
],
888 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_EMISSION
]);
889 ACC_SCALE_3V( &fcmd
[GLT_RED
],
890 ctx
->Light
.Model
.Ambient
,
891 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_AMBIENT
]);
895 COPY_3V( &fcmd
[GLT_RED
], ctx
->Light
.Model
.Ambient
);
898 R200_DB_STATECHANGE(rmesa
, &rmesa
->hw
.glt
);
901 /* Update on change to
905 static void update_light_colors( GLcontext
*ctx
, GLuint p
)
907 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
909 /* fprintf(stderr, "%s\n", __FUNCTION__); */
912 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
913 float *fcmd
= (float *)R200_DB_STATE( lit
[p
] );
915 COPY_4V( &fcmd
[LIT_AMBIENT_RED
], l
->Ambient
);
916 COPY_4V( &fcmd
[LIT_DIFFUSE_RED
], l
->Diffuse
);
917 COPY_4V( &fcmd
[LIT_SPECULAR_RED
], l
->Specular
);
919 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
923 static void r200ColorMaterial( GLcontext
*ctx
, GLenum face
, GLenum mode
)
925 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
926 GLuint light_model_ctl1
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
];
927 light_model_ctl1
&= ~((0xf << R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
928 (0xf << R200_FRONT_AMBIENT_SOURCE_SHIFT
) |
929 (0xf << R200_FRONT_DIFFUSE_SOURCE_SHIFT
) |
930 (0xf << R200_FRONT_SPECULAR_SOURCE_SHIFT
) |
931 (0xf << R200_BACK_EMISSIVE_SOURCE_SHIFT
) |
932 (0xf << R200_BACK_AMBIENT_SOURCE_SHIFT
) |
933 (0xf << R200_BACK_DIFFUSE_SOURCE_SHIFT
) |
934 (0xf << R200_BACK_SPECULAR_SOURCE_SHIFT
));
936 if (ctx
->Light
.ColorMaterialEnabled
) {
937 GLuint mask
= ctx
->Light
.ColorMaterialBitmask
;
939 if (mask
& MAT_BIT_FRONT_EMISSION
) {
940 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
941 R200_FRONT_EMISSIVE_SOURCE_SHIFT
);
944 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
945 R200_FRONT_EMISSIVE_SOURCE_SHIFT
);
947 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
948 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
949 R200_FRONT_AMBIENT_SOURCE_SHIFT
);
952 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
953 R200_FRONT_AMBIENT_SOURCE_SHIFT
);
955 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
956 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
957 R200_FRONT_DIFFUSE_SOURCE_SHIFT
);
960 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
961 R200_FRONT_DIFFUSE_SOURCE_SHIFT
);
963 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
964 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
965 R200_FRONT_SPECULAR_SOURCE_SHIFT
);
968 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
969 R200_FRONT_SPECULAR_SOURCE_SHIFT
);
972 if (mask
& MAT_BIT_BACK_EMISSION
) {
973 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
974 R200_BACK_EMISSIVE_SOURCE_SHIFT
);
977 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
978 R200_BACK_EMISSIVE_SOURCE_SHIFT
);
980 if (mask
& MAT_BIT_BACK_AMBIENT
) {
981 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
982 R200_BACK_AMBIENT_SOURCE_SHIFT
);
984 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
985 R200_BACK_AMBIENT_SOURCE_SHIFT
);
987 if (mask
& MAT_BIT_BACK_DIFFUSE
) {
988 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
989 R200_BACK_DIFFUSE_SOURCE_SHIFT
);
991 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
992 R200_BACK_DIFFUSE_SOURCE_SHIFT
);
994 if (mask
& MAT_BIT_BACK_SPECULAR
) {
995 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
996 R200_BACK_SPECULAR_SOURCE_SHIFT
);
999 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
1000 R200_BACK_SPECULAR_SOURCE_SHIFT
);
1004 /* Default to SOURCE_MATERIAL:
1007 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
1008 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_AMBIENT_SOURCE_SHIFT
) |
1009 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_DIFFUSE_SOURCE_SHIFT
) |
1010 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_SPECULAR_SOURCE_SHIFT
) |
1011 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_EMISSIVE_SOURCE_SHIFT
) |
1012 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_AMBIENT_SOURCE_SHIFT
) |
1013 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_DIFFUSE_SOURCE_SHIFT
) |
1014 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_SPECULAR_SOURCE_SHIFT
);
1017 if (light_model_ctl1
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
]) {
1018 R200_STATECHANGE( rmesa
, tcl
);
1019 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
] = light_model_ctl1
;
1025 void r200UpdateMaterial( GLcontext
*ctx
)
1027 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1028 GLfloat (*mat
)[4] = ctx
->Light
.Material
.Attrib
;
1029 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( mtl
[0] );
1030 GLfloat
*fcmd2
= (GLfloat
*)R200_DB_STATE( mtl
[1] );
1033 /* Might be possible and faster to update everything unconditionally? */
1034 if (ctx
->Light
.ColorMaterialEnabled
)
1035 mask
&= ~ctx
->Light
.ColorMaterialBitmask
;
1037 if (R200_DEBUG
& RADEON_STATE
)
1038 fprintf(stderr
, "%s\n", __FUNCTION__
);
1040 if (mask
& MAT_BIT_FRONT_EMISSION
) {
1041 fcmd
[MTL_EMMISSIVE_RED
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][0];
1042 fcmd
[MTL_EMMISSIVE_GREEN
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][1];
1043 fcmd
[MTL_EMMISSIVE_BLUE
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][2];
1044 fcmd
[MTL_EMMISSIVE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][3];
1046 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
1047 fcmd
[MTL_AMBIENT_RED
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][0];
1048 fcmd
[MTL_AMBIENT_GREEN
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][1];
1049 fcmd
[MTL_AMBIENT_BLUE
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][2];
1050 fcmd
[MTL_AMBIENT_ALPHA
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][3];
1052 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
1053 fcmd
[MTL_DIFFUSE_RED
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][0];
1054 fcmd
[MTL_DIFFUSE_GREEN
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][1];
1055 fcmd
[MTL_DIFFUSE_BLUE
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][2];
1056 fcmd
[MTL_DIFFUSE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][3];
1058 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
1059 fcmd
[MTL_SPECULAR_RED
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][0];
1060 fcmd
[MTL_SPECULAR_GREEN
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][1];
1061 fcmd
[MTL_SPECULAR_BLUE
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][2];
1062 fcmd
[MTL_SPECULAR_ALPHA
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][3];
1064 if (mask
& MAT_BIT_FRONT_SHININESS
) {
1065 fcmd
[MTL_SHININESS
] = mat
[MAT_ATTRIB_FRONT_SHININESS
][0];
1068 if (mask
& MAT_BIT_BACK_EMISSION
) {
1069 fcmd2
[MTL_EMMISSIVE_RED
] = mat
[MAT_ATTRIB_BACK_EMISSION
][0];
1070 fcmd2
[MTL_EMMISSIVE_GREEN
] = mat
[MAT_ATTRIB_BACK_EMISSION
][1];
1071 fcmd2
[MTL_EMMISSIVE_BLUE
] = mat
[MAT_ATTRIB_BACK_EMISSION
][2];
1072 fcmd2
[MTL_EMMISSIVE_ALPHA
] = mat
[MAT_ATTRIB_BACK_EMISSION
][3];
1074 if (mask
& MAT_BIT_BACK_AMBIENT
) {
1075 fcmd2
[MTL_AMBIENT_RED
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][0];
1076 fcmd2
[MTL_AMBIENT_GREEN
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][1];
1077 fcmd2
[MTL_AMBIENT_BLUE
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][2];
1078 fcmd2
[MTL_AMBIENT_ALPHA
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][3];
1080 if (mask
& MAT_BIT_BACK_DIFFUSE
) {
1081 fcmd2
[MTL_DIFFUSE_RED
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][0];
1082 fcmd2
[MTL_DIFFUSE_GREEN
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][1];
1083 fcmd2
[MTL_DIFFUSE_BLUE
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][2];
1084 fcmd2
[MTL_DIFFUSE_ALPHA
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][3];
1086 if (mask
& MAT_BIT_BACK_SPECULAR
) {
1087 fcmd2
[MTL_SPECULAR_RED
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][0];
1088 fcmd2
[MTL_SPECULAR_GREEN
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][1];
1089 fcmd2
[MTL_SPECULAR_BLUE
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][2];
1090 fcmd2
[MTL_SPECULAR_ALPHA
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][3];
1092 if (mask
& MAT_BIT_BACK_SHININESS
) {
1093 fcmd2
[MTL_SHININESS
] = mat
[MAT_ATTRIB_BACK_SHININESS
][0];
1096 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mtl
[0] );
1097 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mtl
[1] );
1099 /* currently material changes cannot trigger a global ambient change, I believe this is correct
1100 update_global_ambient( ctx ); */
1105 * _MESA_NEW_NEED_EYE_COORDS
1107 * Uses derived state from mesa:
1111 * _NormSpotDirection
1112 * _ModelViewInvScale
1116 * which are calculated in light.c and are correct for the current
1117 * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
1118 * and _MESA_NEW_NEED_EYE_COORDS.
1120 static void update_light( GLcontext
*ctx
)
1122 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1124 /* Have to check these, or have an automatic shortcircuit mechanism
1125 * to remove noop statechanges. (Or just do a better job on the
1129 GLuint tmp
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
];
1131 if (ctx
->_NeedEyeCoords
)
1132 tmp
&= ~R200_LIGHT_IN_MODELSPACE
;
1134 tmp
|= R200_LIGHT_IN_MODELSPACE
;
1136 if (tmp
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
])
1138 R200_STATECHANGE( rmesa
, tcl
);
1139 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] = tmp
;
1144 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( eye
);
1145 fcmd
[EYE_X
] = ctx
->_EyeZDir
[0];
1146 fcmd
[EYE_Y
] = ctx
->_EyeZDir
[1];
1147 fcmd
[EYE_Z
] = - ctx
->_EyeZDir
[2];
1148 fcmd
[EYE_RESCALE_FACTOR
] = ctx
->_ModelViewInvScale
;
1149 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.eye
);
1154 if (ctx
->Light
.Enabled
) {
1156 for (p
= 0 ; p
< MAX_LIGHTS
; p
++) {
1157 if (ctx
->Light
.Light
[p
].Enabled
) {
1158 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1159 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( lit
[p
] );
1161 if (l
->EyePosition
[3] == 0.0) {
1162 COPY_3FV( &fcmd
[LIT_POSITION_X
], l
->_VP_inf_norm
);
1163 COPY_3FV( &fcmd
[LIT_DIRECTION_X
], l
->_h_inf_norm
);
1164 fcmd
[LIT_POSITION_W
] = 0;
1165 fcmd
[LIT_DIRECTION_W
] = 0;
1167 COPY_4V( &fcmd
[LIT_POSITION_X
], l
->_Position
);
1168 fcmd
[LIT_DIRECTION_X
] = -l
->_NormSpotDirection
[0];
1169 fcmd
[LIT_DIRECTION_Y
] = -l
->_NormSpotDirection
[1];
1170 fcmd
[LIT_DIRECTION_Z
] = -l
->_NormSpotDirection
[2];
1171 fcmd
[LIT_DIRECTION_W
] = 0;
1174 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
1180 static void r200Lightfv( GLcontext
*ctx
, GLenum light
,
1181 GLenum pname
, const GLfloat
*params
)
1183 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1184 GLint p
= light
- GL_LIGHT0
;
1185 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1186 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.lit
[p
].cmd
;
1193 update_light_colors( ctx
, p
);
1196 case GL_SPOT_DIRECTION
:
1197 /* picked up in update_light */
1201 /* positions picked up in update_light, but can do flag here */
1202 GLuint flag
= (p
&1)? R200_LIGHT_1_IS_LOCAL
: R200_LIGHT_0_IS_LOCAL
;
1203 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1205 R200_STATECHANGE(rmesa
, tcl
);
1206 if (l
->EyePosition
[3] != 0.0F
)
1207 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1209 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1213 case GL_SPOT_EXPONENT
:
1214 R200_STATECHANGE(rmesa
, lit
[p
]);
1215 fcmd
[LIT_SPOT_EXPONENT
] = params
[0];
1218 case GL_SPOT_CUTOFF
: {
1219 GLuint flag
= (p
&1) ? R200_LIGHT_1_IS_SPOT
: R200_LIGHT_0_IS_SPOT
;
1220 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1222 R200_STATECHANGE(rmesa
, lit
[p
]);
1223 fcmd
[LIT_SPOT_CUTOFF
] = l
->_CosCutoff
;
1225 R200_STATECHANGE(rmesa
, tcl
);
1226 if (l
->SpotCutoff
!= 180.0F
)
1227 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1229 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1234 case GL_CONSTANT_ATTENUATION
:
1235 R200_STATECHANGE(rmesa
, lit
[p
]);
1236 fcmd
[LIT_ATTEN_CONST
] = params
[0];
1237 if ( params
[0] == 0.0 )
1238 fcmd
[LIT_ATTEN_CONST_INV
] = FLT_MAX
;
1240 fcmd
[LIT_ATTEN_CONST_INV
] = 1.0 / params
[0];
1242 case GL_LINEAR_ATTENUATION
:
1243 R200_STATECHANGE(rmesa
, lit
[p
]);
1244 fcmd
[LIT_ATTEN_LINEAR
] = params
[0];
1246 case GL_QUADRATIC_ATTENUATION
:
1247 R200_STATECHANGE(rmesa
, lit
[p
]);
1248 fcmd
[LIT_ATTEN_QUADRATIC
] = params
[0];
1254 /* Set RANGE_ATTEN only when needed */
1257 case GL_CONSTANT_ATTENUATION
:
1258 case GL_LINEAR_ATTENUATION
:
1259 case GL_QUADRATIC_ATTENUATION
: {
1260 GLuint
*icmd
= (GLuint
*)R200_DB_STATE( tcl
);
1261 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1262 GLuint atten_flag
= ( p
&1 ) ? R200_LIGHT_1_ENABLE_RANGE_ATTEN
1263 : R200_LIGHT_0_ENABLE_RANGE_ATTEN
;
1264 GLuint atten_const_flag
= ( p
&1 ) ? R200_LIGHT_1_CONSTANT_RANGE_ATTEN
1265 : R200_LIGHT_0_CONSTANT_RANGE_ATTEN
;
1267 if ( l
->EyePosition
[3] == 0.0F
||
1268 ( ( fcmd
[LIT_ATTEN_CONST
] == 0.0 || fcmd
[LIT_ATTEN_CONST
] == 1.0 ) &&
1269 fcmd
[LIT_ATTEN_QUADRATIC
] == 0.0 && fcmd
[LIT_ATTEN_LINEAR
] == 0.0 ) ) {
1270 /* Disable attenuation */
1271 icmd
[idx
] &= ~atten_flag
;
1273 if ( fcmd
[LIT_ATTEN_QUADRATIC
] == 0.0 && fcmd
[LIT_ATTEN_LINEAR
] == 0.0 ) {
1274 /* Enable only constant portion of attenuation calculation */
1275 icmd
[idx
] |= ( atten_flag
| atten_const_flag
);
1277 /* Enable full attenuation calculation */
1278 icmd
[idx
] &= ~atten_const_flag
;
1279 icmd
[idx
] |= atten_flag
;
1283 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.tcl
);
1291 static void r200UpdateLocalViewer ( GLcontext
*ctx
)
1293 /* It looks like for the texgen modes GL_SPHERE_MAP, GL_NORMAL_MAP and
1294 GL_REFLECTION_MAP we need R200_LOCAL_VIEWER set (fglrx does exactly that
1295 for these and only these modes). This means specular highlights may turn out
1296 wrong in some cases when lighting is enabled but GL_LIGHT_MODEL_LOCAL_VIEWER
1297 is not set, though it seems to happen rarely and the effect seems quite
1298 subtle. May need TCL fallback to fix it completely, though I'm not sure
1299 how you'd identify the cases where the specular highlights indeed will
1300 be wrong. Don't know if fglrx does something special in that case.
1302 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1303 R200_STATECHANGE( rmesa
, tcl
);
1304 if (ctx
->Light
.Model
.LocalViewer
||
1305 ctx
->Texture
._GenFlags
& TEXGEN_NEED_NORMALS
)
1306 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LOCAL_VIEWER
;
1308 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LOCAL_VIEWER
;
1311 static void r200LightModelfv( GLcontext
*ctx
, GLenum pname
,
1312 const GLfloat
*param
)
1314 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1317 case GL_LIGHT_MODEL_AMBIENT
:
1318 update_global_ambient( ctx
);
1321 case GL_LIGHT_MODEL_LOCAL_VIEWER
:
1322 r200UpdateLocalViewer( ctx
);
1325 case GL_LIGHT_MODEL_TWO_SIDE
:
1326 R200_STATECHANGE( rmesa
, tcl
);
1327 if (ctx
->Light
.Model
.TwoSide
)
1328 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHT_TWOSIDE
;
1330 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~(R200_LIGHT_TWOSIDE
);
1331 if (rmesa
->radeon
.TclFallback
) {
1332 r200ChooseRenderState( ctx
);
1333 r200ChooseVertexState( ctx
);
1337 case GL_LIGHT_MODEL_COLOR_CONTROL
:
1338 r200UpdateSpecular(ctx
);
1346 static void r200ShadeModel( GLcontext
*ctx
, GLenum mode
)
1348 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1349 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
1351 s
&= ~(R200_DIFFUSE_SHADE_MASK
|
1352 R200_ALPHA_SHADE_MASK
|
1353 R200_SPECULAR_SHADE_MASK
|
1354 R200_FOG_SHADE_MASK
|
1355 R200_DISC_FOG_SHADE_MASK
);
1359 s
|= (R200_DIFFUSE_SHADE_FLAT
|
1360 R200_ALPHA_SHADE_FLAT
|
1361 R200_SPECULAR_SHADE_FLAT
|
1362 R200_FOG_SHADE_FLAT
|
1363 R200_DISC_FOG_SHADE_FLAT
);
1366 s
|= (R200_DIFFUSE_SHADE_GOURAUD
|
1367 R200_ALPHA_SHADE_GOURAUD
|
1368 R200_SPECULAR_SHADE_GOURAUD
|
1369 R200_FOG_SHADE_GOURAUD
|
1370 R200_DISC_FOG_SHADE_GOURAUD
);
1376 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
1377 R200_STATECHANGE( rmesa
, set
);
1378 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
1383 /* =============================================================
1387 static void r200ClipPlane( GLcontext
*ctx
, GLenum plane
, const GLfloat
*eq
)
1389 GLint p
= (GLint
) plane
- (GLint
) GL_CLIP_PLANE0
;
1390 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1391 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1393 R200_STATECHANGE( rmesa
, ucp
[p
] );
1394 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1395 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1396 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1397 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1400 static void r200UpdateClipPlanes( GLcontext
*ctx
)
1402 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1405 for (p
= 0; p
< ctx
->Const
.MaxClipPlanes
; p
++) {
1406 if (ctx
->Transform
.ClipPlanesEnabled
& (1 << p
)) {
1407 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1409 R200_STATECHANGE( rmesa
, ucp
[p
] );
1410 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1411 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1412 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1413 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1419 /* =============================================================
1424 r200StencilFuncSeparate( GLcontext
*ctx
, GLenum face
, GLenum func
,
1425 GLint ref
, GLuint mask
)
1427 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1428 GLuint refmask
= (((ctx
->Stencil
.Ref
[0] & 0xff) << R200_STENCIL_REF_SHIFT
) |
1429 ((ctx
->Stencil
.ValueMask
[0] & 0xff) << R200_STENCIL_MASK_SHIFT
));
1431 R200_STATECHANGE( rmesa
, ctx
);
1432 R200_STATECHANGE( rmesa
, msk
);
1434 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_STENCIL_TEST_MASK
;
1435 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~(R200_STENCIL_REF_MASK
|
1436 R200_STENCIL_VALUE_MASK
);
1438 switch ( ctx
->Stencil
.Function
[0] ) {
1440 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEVER
;
1443 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LESS
;
1446 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_EQUAL
;
1449 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LEQUAL
;
1452 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GREATER
;
1455 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEQUAL
;
1458 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GEQUAL
;
1461 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_ALWAYS
;
1465 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |= refmask
;
1469 r200StencilMaskSeparate( GLcontext
*ctx
, GLenum face
, GLuint mask
)
1471 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1473 R200_STATECHANGE( rmesa
, msk
);
1474 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~R200_STENCIL_WRITE_MASK
;
1475 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |=
1476 ((ctx
->Stencil
.WriteMask
[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT
);
1480 r200StencilOpSeparate( GLcontext
*ctx
, GLenum face
, GLenum fail
,
1481 GLenum zfail
, GLenum zpass
)
1483 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1485 R200_STATECHANGE( rmesa
, ctx
);
1486 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~(R200_STENCIL_FAIL_MASK
|
1487 R200_STENCIL_ZFAIL_MASK
|
1488 R200_STENCIL_ZPASS_MASK
);
1490 switch ( ctx
->Stencil
.FailFunc
[0] ) {
1492 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_KEEP
;
1495 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_ZERO
;
1498 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_REPLACE
;
1501 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC
;
1504 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC
;
1506 case GL_INCR_WRAP_EXT
:
1507 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC_WRAP
;
1509 case GL_DECR_WRAP_EXT
:
1510 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC_WRAP
;
1513 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INVERT
;
1517 switch ( ctx
->Stencil
.ZFailFunc
[0] ) {
1519 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_KEEP
;
1522 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_ZERO
;
1525 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_REPLACE
;
1528 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC
;
1531 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC
;
1533 case GL_INCR_WRAP_EXT
:
1534 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC_WRAP
;
1536 case GL_DECR_WRAP_EXT
:
1537 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC_WRAP
;
1540 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INVERT
;
1544 switch ( ctx
->Stencil
.ZPassFunc
[0] ) {
1546 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_KEEP
;
1549 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_ZERO
;
1552 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_REPLACE
;
1555 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC
;
1558 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC
;
1560 case GL_INCR_WRAP_EXT
:
1561 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC_WRAP
;
1563 case GL_DECR_WRAP_EXT
:
1564 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC_WRAP
;
1567 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INVERT
;
1572 static void r200ClearStencil( GLcontext
*ctx
, GLint s
)
1574 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1576 rmesa
->radeon
.state
.stencil
.clear
=
1577 ((GLuint
) (ctx
->Stencil
.Clear
& 0xff) |
1578 (0xff << R200_STENCIL_MASK_SHIFT
) |
1579 ((ctx
->Stencil
.WriteMask
[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT
));
1583 /* =============================================================
1584 * Window position and viewport transformation
1588 * Called when window size or position changes or viewport or depth range
1589 * state is changed. We update the hardware viewport state here.
1591 void r200UpdateWindow( GLcontext
*ctx
)
1593 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1594 __DRIdrawable
*dPriv
= radeon_get_drawable(&rmesa
->radeon
);
1595 GLfloat xoffset
= dPriv
? (GLfloat
) dPriv
->x
: 0;
1596 GLfloat yoffset
= dPriv
? (GLfloat
) dPriv
->y
+ dPriv
->h
: 0;
1597 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1598 const GLboolean render_to_fbo
= (ctx
->DrawBuffer
? (ctx
->DrawBuffer
->Name
!= 0) : 0);
1599 const GLfloat depthScale
= 1.0F
/ ctx
->DrawBuffer
->_DepthMaxF
;
1600 GLfloat y_scale
, y_bias
;
1602 if (render_to_fbo
) {
1610 float_ui32_type sx
= { v
[MAT_SX
] };
1611 float_ui32_type tx
= { v
[MAT_TX
] + xoffset
};
1612 float_ui32_type sy
= { v
[MAT_SY
] * y_scale
};
1613 float_ui32_type ty
= { (v
[MAT_TY
] * y_scale
) + y_bias
};
1614 float_ui32_type sz
= { v
[MAT_SZ
] * depthScale
};
1615 float_ui32_type tz
= { v
[MAT_TZ
] * depthScale
};
1617 R200_STATECHANGE( rmesa
, vpt
);
1619 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XSCALE
] = sx
.ui32
;
1620 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = tx
.ui32
;
1621 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YSCALE
] = sy
.ui32
;
1622 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = ty
.ui32
;
1623 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZSCALE
] = sz
.ui32
;
1624 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZOFFSET
] = tz
.ui32
;
1627 void r200_vtbl_update_scissor( GLcontext
*ctx
)
1629 r200ContextPtr r200
= R200_CONTEXT(ctx
);
1630 unsigned x1
, y1
, x2
, y2
;
1631 struct radeon_renderbuffer
*rrb
;
1633 R200_SET_STATE(r200
, set
, SET_RE_CNTL
, R200_SCISSOR_ENABLE
| r200
->hw
.set
.cmd
[SET_RE_CNTL
]);
1635 if (r200
->radeon
.state
.scissor
.enabled
) {
1636 x1
= r200
->radeon
.state
.scissor
.rect
.x1
;
1637 y1
= r200
->radeon
.state
.scissor
.rect
.y1
;
1638 x2
= r200
->radeon
.state
.scissor
.rect
.x2
;
1639 y2
= r200
->radeon
.state
.scissor
.rect
.y2
;
1641 rrb
= radeon_get_colorbuffer(&r200
->radeon
);
1644 x2
= rrb
->base
.Width
- 1;
1645 y2
= rrb
->base
.Height
- 1;
1648 R200_SET_STATE(r200
, sci
, SCI_XY_1
, x1
| (y1
<< 16));
1649 R200_SET_STATE(r200
, sci
, SCI_XY_2
, x2
| (y2
<< 16));
1653 static void r200Viewport( GLcontext
*ctx
, GLint x
, GLint y
,
1654 GLsizei width
, GLsizei height
)
1656 /* Don't pipeline viewport changes, conflict with window offset
1657 * setting below. Could apply deltas to rescue pipelined viewport
1658 * values, or keep the originals hanging around.
1660 r200UpdateWindow( ctx
);
1662 radeon_viewport(ctx
, x
, y
, width
, height
);
1665 static void r200DepthRange( GLcontext
*ctx
, GLclampd nearval
,
1668 r200UpdateWindow( ctx
);
1671 void r200UpdateViewportOffset( GLcontext
*ctx
)
1673 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1674 __DRIdrawable
*dPriv
= radeon_get_drawable(&rmesa
->radeon
);
1675 GLfloat xoffset
= (GLfloat
)dPriv
->x
;
1676 GLfloat yoffset
= (GLfloat
)dPriv
->y
+ dPriv
->h
;
1677 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1682 tx
.f
= v
[MAT_TX
] + xoffset
;
1683 ty
.f
= (- v
[MAT_TY
]) + yoffset
;
1685 if ( rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] != tx
.ui32
||
1686 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] != ty
.ui32
)
1688 /* Note: this should also modify whatever data the context reset
1691 R200_STATECHANGE( rmesa
, vpt
);
1692 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = tx
.ui32
;
1693 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = ty
.ui32
;
1695 /* update polygon stipple x/y screen offset */
1698 GLuint m
= rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
];
1700 m
&= ~(R200_STIPPLE_X_OFFSET_MASK
|
1701 R200_STIPPLE_Y_OFFSET_MASK
);
1703 /* add magic offsets, then invert */
1704 stx
= 31 - ((dPriv
->x
- 1) & R200_STIPPLE_COORD_MASK
);
1705 sty
= 31 - ((dPriv
->y
+ dPriv
->h
- 1)
1706 & R200_STIPPLE_COORD_MASK
);
1708 m
|= ((stx
<< R200_STIPPLE_X_OFFSET_SHIFT
) |
1709 (sty
<< R200_STIPPLE_Y_OFFSET_SHIFT
));
1711 if ( rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] != m
) {
1712 R200_STATECHANGE( rmesa
, msc
);
1713 rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] = m
;
1718 radeonUpdateScissor( ctx
);
1723 /* =============================================================
1727 static void r200ClearColor( GLcontext
*ctx
, const GLfloat c
[4] )
1729 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1731 struct radeon_renderbuffer
*rrb
;
1733 rrb
= radeon_get_colorbuffer(&rmesa
->radeon
);
1736 CLAMPED_FLOAT_TO_UBYTE(color
[0], c
[0]);
1737 CLAMPED_FLOAT_TO_UBYTE(color
[1], c
[1]);
1738 CLAMPED_FLOAT_TO_UBYTE(color
[2], c
[2]);
1739 CLAMPED_FLOAT_TO_UBYTE(color
[3], c
[3]);
1740 rmesa
->radeon
.state
.color
.clear
= radeonPackColor( rrb
->cpp
,
1742 color
[2], color
[3] );
1746 static void r200RenderMode( GLcontext
*ctx
, GLenum mode
)
1748 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1749 FALLBACK( rmesa
, R200_FALLBACK_RENDER_MODE
, (mode
!= GL_RENDER
) );
1753 static GLuint r200_rop_tab
[] = {
1756 R200_ROP_AND_REVERSE
,
1758 R200_ROP_AND_INVERTED
,
1765 R200_ROP_OR_REVERSE
,
1766 R200_ROP_COPY_INVERTED
,
1767 R200_ROP_OR_INVERTED
,
1772 static void r200LogicOpCode( GLcontext
*ctx
, GLenum opcode
)
1774 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1775 GLuint rop
= (GLuint
)opcode
- GL_CLEAR
;
1779 R200_STATECHANGE( rmesa
, msk
);
1780 rmesa
->hw
.msk
.cmd
[MSK_RB3D_ROPCNTL
] = r200_rop_tab
[rop
];
1783 /* =============================================================
1784 * State enable/disable
1787 static void r200Enable( GLcontext
*ctx
, GLenum cap
, GLboolean state
)
1789 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1792 if ( R200_DEBUG
& RADEON_STATE
)
1793 fprintf( stderr
, "%s( %s = %s )\n", __FUNCTION__
,
1794 _mesa_lookup_enum_by_nr( cap
),
1795 state
? "GL_TRUE" : "GL_FALSE" );
1798 /* Fast track this one...
1806 R200_STATECHANGE( rmesa
, ctx
);
1808 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ALPHA_TEST_ENABLE
;
1810 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ALPHA_TEST_ENABLE
;
1815 case GL_COLOR_LOGIC_OP
:
1816 r200_set_blend_state( ctx
);
1819 case GL_CLIP_PLANE0
:
1820 case GL_CLIP_PLANE1
:
1821 case GL_CLIP_PLANE2
:
1822 case GL_CLIP_PLANE3
:
1823 case GL_CLIP_PLANE4
:
1824 case GL_CLIP_PLANE5
:
1825 p
= cap
-GL_CLIP_PLANE0
;
1826 R200_STATECHANGE( rmesa
, tcl
);
1828 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= (R200_UCP_ENABLE_0
<<p
);
1829 r200ClipPlane( ctx
, cap
, NULL
);
1832 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~(R200_UCP_ENABLE_0
<<p
);
1836 case GL_COLOR_MATERIAL
:
1837 r200ColorMaterial( ctx
, 0, 0 );
1838 r200UpdateMaterial( ctx
);
1842 r200CullFace( ctx
, 0 );
1846 R200_STATECHANGE(rmesa
, ctx
);
1848 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_Z_ENABLE
;
1850 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_Z_ENABLE
;
1855 R200_STATECHANGE(rmesa
, ctx
);
1857 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_DITHER_ENABLE
;
1858 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~rmesa
->radeon
.state
.color
.roundEnable
;
1860 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_DITHER_ENABLE
;
1861 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= rmesa
->radeon
.state
.color
.roundEnable
;
1866 R200_STATECHANGE(rmesa
, ctx
);
1868 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_FOG_ENABLE
;
1869 r200Fogfv( ctx
, GL_FOG_MODE
, NULL
);
1871 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_FOG_ENABLE
;
1872 R200_STATECHANGE(rmesa
, tcl
);
1873 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_TCL_FOG_MASK
;
1875 r200UpdateSpecular( ctx
); /* for PK_SPEC */
1876 if (rmesa
->radeon
.TclFallback
)
1877 r200ChooseVertexState( ctx
);
1878 _mesa_allow_light_in_model( ctx
, !state
);
1889 R200_STATECHANGE(rmesa
, tcl
);
1890 p
= cap
- GL_LIGHT0
;
1892 flag
= (R200_LIGHT_1_ENABLE
|
1893 R200_LIGHT_1_ENABLE_AMBIENT
|
1894 R200_LIGHT_1_ENABLE_SPECULAR
);
1896 flag
= (R200_LIGHT_0_ENABLE
|
1897 R200_LIGHT_0_ENABLE_AMBIENT
|
1898 R200_LIGHT_0_ENABLE_SPECULAR
);
1901 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] |= flag
;
1903 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] &= ~flag
;
1907 update_light_colors( ctx
, p
);
1911 r200UpdateSpecular(ctx
);
1912 /* for reflection map fixup - might set recheck_texgen for all units too */
1913 rmesa
->radeon
.NewGLState
|= _NEW_TEXTURE
;
1916 case GL_LINE_SMOOTH
:
1917 R200_STATECHANGE( rmesa
, ctx
);
1919 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_LINE
;
1921 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_LINE
;
1925 case GL_LINE_STIPPLE
:
1926 R200_STATECHANGE( rmesa
, set
);
1928 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_PATTERN_ENABLE
;
1930 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_PATTERN_ENABLE
;
1935 R200_STATECHANGE( rmesa
, tcl
);
1937 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_NORMALIZE_NORMALS
;
1939 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_NORMALIZE_NORMALS
;
1943 /* Pointsize registers on r200 only work for point sprites, and point smooth
1944 * doesn't work for point sprites (and isn't needed for 1.0 sized aa points).
1945 * In any case, setting pointmin == pointsizemax == 1.0 for aa points
1946 * is enough to satisfy conform.
1948 case GL_POINT_SMOOTH
:
1951 /* These don't really do anything, as we don't use the 3vtx
1955 case GL_POLYGON_OFFSET_POINT
:
1956 R200_STATECHANGE( rmesa
, set
);
1958 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_POINT
;
1960 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_POINT
;
1964 case GL_POLYGON_OFFSET_LINE
:
1965 R200_STATECHANGE( rmesa
, set
);
1967 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_LINE
;
1969 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_LINE
;
1974 case GL_POINT_SPRITE_ARB
:
1975 R200_STATECHANGE( rmesa
, spr
);
1978 for (i
= 0; i
< 6; i
++) {
1979 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |=
1980 ctx
->Point
.CoordReplace
[i
] << (R200_PS_GEN_TEX_0_SHIFT
+ i
);
1983 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] &= ~R200_PS_GEN_TEX_MASK
;
1987 case GL_POLYGON_OFFSET_FILL
:
1988 R200_STATECHANGE( rmesa
, set
);
1990 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_TRI
;
1992 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_TRI
;
1996 case GL_POLYGON_SMOOTH
:
1997 R200_STATECHANGE( rmesa
, ctx
);
1999 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_POLY
;
2001 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_POLY
;
2005 case GL_POLYGON_STIPPLE
:
2006 R200_STATECHANGE(rmesa
, set
);
2008 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_STIPPLE_ENABLE
;
2010 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_STIPPLE_ENABLE
;
2014 case GL_RESCALE_NORMAL_EXT
: {
2015 GLboolean tmp
= ctx
->_NeedEyeCoords
? state
: !state
;
2016 R200_STATECHANGE( rmesa
, tcl
);
2018 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
2020 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
2025 case GL_SCISSOR_TEST
:
2026 radeon_firevertices(&rmesa
->radeon
);
2027 rmesa
->radeon
.state
.scissor
.enabled
= state
;
2028 radeonUpdateScissor( ctx
);
2031 case GL_STENCIL_TEST
:
2033 GLboolean hw_stencil
= GL_FALSE
;
2034 if (ctx
->DrawBuffer
) {
2035 struct radeon_renderbuffer
*rrbStencil
2036 = radeon_get_renderbuffer(ctx
->DrawBuffer
, BUFFER_STENCIL
);
2037 hw_stencil
= (rrbStencil
&& rrbStencil
->bo
);
2041 R200_STATECHANGE( rmesa
, ctx
);
2043 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_STENCIL_ENABLE
;
2045 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_STENCIL_ENABLE
;
2048 FALLBACK( rmesa
, R200_FALLBACK_STENCIL
, state
);
2053 case GL_TEXTURE_GEN_Q
:
2054 case GL_TEXTURE_GEN_R
:
2055 case GL_TEXTURE_GEN_S
:
2056 case GL_TEXTURE_GEN_T
:
2057 /* Picked up in r200UpdateTextureState.
2059 rmesa
->recheck_texgen
[ctx
->Texture
.CurrentUnit
] = GL_TRUE
;
2062 case GL_COLOR_SUM_EXT
:
2063 r200UpdateSpecular ( ctx
);
2066 case GL_VERTEX_PROGRAM_ARB
:
2069 rmesa
->curr_vp_hw
= NULL
;
2070 R200_STATECHANGE( rmesa
, vap
);
2071 rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
] &= ~R200_VAP_PROG_VTX_SHADER_ENABLE
;
2072 /* mark all tcl atoms (tcl vector state got overwritten) dirty
2073 not sure about tcl scalar state - we need at least grd
2074 with vert progs too.
2075 ucp looks like it doesn't get overwritten (may even work
2076 with vp for pos-invariant progs if we're lucky) */
2077 R200_STATECHANGE( rmesa
, mtl
[0] );
2078 R200_STATECHANGE( rmesa
, mtl
[1] );
2079 R200_STATECHANGE( rmesa
, fog
);
2080 R200_STATECHANGE( rmesa
, glt
);
2081 R200_STATECHANGE( rmesa
, eye
);
2082 for (i
= R200_MTX_MV
; i
<= R200_MTX_TEX5
; i
++) {
2083 R200_STATECHANGE( rmesa
, mat
[i
] );
2085 for (i
= 0 ; i
< 8; i
++) {
2086 R200_STATECHANGE( rmesa
, lit
[i
] );
2088 R200_STATECHANGE( rmesa
, tcl
);
2089 for (i
= 0; i
<= ctx
->Const
.MaxClipPlanes
; i
++) {
2090 if (ctx
->Transform
.ClipPlanesEnabled
& (1 << i
)) {
2091 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= (R200_UCP_ENABLE_0
<< i
);
2094 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0 << i);
2097 /* ugly. Need to call everything which might change compsel. */
2098 r200UpdateSpecular( ctx
);
2100 /* shouldn't be necessary, as it's picked up anyway in r200ValidateState (_NEW_PROGRAM),
2101 but without it doom3 locks up at always the same places. Why? */
2102 /* FIXME: This can (and should) be replaced by a call to the TCL_STATE_FLUSH reg before
2103 accessing VAP_SE_VAP_CNTL. Requires drm changes (done). Remove after some time... */
2104 r200UpdateTextureState( ctx
);
2105 /* if we call r200UpdateTextureState we need the code below because we are calling it with
2106 non-current derived enabled values which may revert the state atoms for frag progs even when
2107 they already got disabled... ugh
2108 Should really figure out why we need to call r200UpdateTextureState in the first place */
2110 for (unit
= 0; unit
< R200_MAX_TEXTURE_UNITS
; unit
++) {
2111 R200_STATECHANGE( rmesa
, pix
[unit
] );
2112 R200_STATECHANGE( rmesa
, tex
[unit
] );
2113 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] &=
2114 ~(R200_TXFORMAT_ST_ROUTE_MASK
| R200_TXFORMAT_LOOKUP_DISABLE
);
2115 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] |= unit
<< R200_TXFORMAT_ST_ROUTE_SHIFT
;
2116 /* need to guard this with drmSupportsFragmentShader? Should never get here if
2117 we don't announce ATI_fs, right? */
2118 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXMULTI_CTL
] = 0;
2120 R200_STATECHANGE( rmesa
, cst
);
2121 R200_STATECHANGE( rmesa
, tf
);
2122 rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] = 0;
2126 /* picked up later */
2128 /* call functions which change hw state based on ARB_vp enabled or not. */
2129 r200PointParameter( ctx
, GL_POINT_DISTANCE_ATTENUATION
, NULL
);
2130 r200Fogfv( ctx
, GL_FOG_COORD_SRC
, NULL
);
2133 case GL_VERTEX_PROGRAM_POINT_SIZE_ARB
:
2134 r200PointParameter( ctx
, GL_POINT_DISTANCE_ATTENUATION
, NULL
);
2137 case GL_FRAGMENT_SHADER_ATI
:
2139 /* restore normal tex env colors and make sure tex env combine will get updated
2140 mark env atoms dirty (as their data was overwritten by afs even
2141 if they didn't change) and restore tex coord routing */
2143 for (unit
= 0; unit
< R200_MAX_TEXTURE_UNITS
; unit
++) {
2144 R200_STATECHANGE( rmesa
, pix
[unit
] );
2145 R200_STATECHANGE( rmesa
, tex
[unit
] );
2146 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] &=
2147 ~(R200_TXFORMAT_ST_ROUTE_MASK
| R200_TXFORMAT_LOOKUP_DISABLE
);
2148 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] |= unit
<< R200_TXFORMAT_ST_ROUTE_SHIFT
;
2149 /* need to guard this with drmSupportsFragmentShader? Should never get here if
2150 we don't announce ATI_fs, right? */
2151 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXMULTI_CTL
] = 0;
2153 R200_STATECHANGE( rmesa
, cst
);
2154 R200_STATECHANGE( rmesa
, tf
);
2155 rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] = 0;
2158 /* need to mark this dirty as pix/tf atoms have overwritten the data
2159 even if the data in the atoms didn't change */
2160 R200_STATECHANGE( rmesa
, atf
);
2161 R200_STATECHANGE( rmesa
, afs
[1] );
2162 /* everything else picked up in r200UpdateTextureState hopefully */
2171 void r200LightingSpaceChange( GLcontext
*ctx
)
2173 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2176 if (R200_DEBUG
& RADEON_STATE
)
2177 fprintf(stderr
, "%s %d BEFORE %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
2178 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
2180 if (ctx
->_NeedEyeCoords
)
2181 tmp
= ctx
->Transform
.RescaleNormals
;
2183 tmp
= !ctx
->Transform
.RescaleNormals
;
2185 R200_STATECHANGE( rmesa
, tcl
);
2187 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
2189 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
2192 if (R200_DEBUG
& RADEON_STATE
)
2193 fprintf(stderr
, "%s %d AFTER %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
2194 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
2197 /* =============================================================
2198 * Deferred state management - matrices, textures, other?
2204 static void upload_matrix( r200ContextPtr rmesa
, GLfloat
*src
, int idx
)
2206 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
2210 for (i
= 0 ; i
< 4 ; i
++) {
2214 *dest
++ = src
[i
+12];
2217 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
2220 static void upload_matrix_t( r200ContextPtr rmesa
, const GLfloat
*src
, int idx
)
2222 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
2223 memcpy(dest
, src
, 16*sizeof(float));
2224 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
2228 static void update_texturematrix( GLcontext
*ctx
)
2230 r200ContextPtr rmesa
= R200_CONTEXT( ctx
);
2231 GLuint tpc
= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
];
2232 GLuint compsel
= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
];
2235 if (R200_DEBUG
& RADEON_STATE
)
2236 fprintf(stderr
, "%s before COMPSEL: %x\n", __FUNCTION__
,
2237 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]);
2239 rmesa
->TexMatEnabled
= 0;
2240 rmesa
->TexMatCompSel
= 0;
2242 for (unit
= 0 ; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
2243 if (!ctx
->Texture
.Unit
[unit
]._ReallyEnabled
)
2246 if (ctx
->TextureMatrixStack
[unit
].Top
->type
!= MATRIX_IDENTITY
) {
2247 rmesa
->TexMatEnabled
|= (R200_TEXGEN_TEXMAT_0_ENABLE
|
2248 R200_TEXMAT_0_ENABLE
) << unit
;
2250 rmesa
->TexMatCompSel
|= R200_OUTPUT_TEX_0
<< unit
;
2252 if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2253 /* Need to preconcatenate any active texgen
2254 * obj/eyeplane matrices:
2256 _math_matrix_mul_matrix( &rmesa
->tmpmat
,
2257 ctx
->TextureMatrixStack
[unit
].Top
,
2258 &rmesa
->TexGenMatrix
[unit
] );
2259 upload_matrix( rmesa
, rmesa
->tmpmat
.m
, R200_MTX_TEX0
+unit
);
2262 upload_matrix( rmesa
, ctx
->TextureMatrixStack
[unit
].Top
->m
,
2263 R200_MTX_TEX0
+unit
);
2266 else if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2267 upload_matrix( rmesa
, rmesa
->TexGenMatrix
[unit
].m
,
2268 R200_MTX_TEX0
+unit
);
2272 tpc
= (rmesa
->TexMatEnabled
| rmesa
->TexGenEnabled
);
2273 if (tpc
!= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
]) {
2274 R200_STATECHANGE(rmesa
, tcg
);
2275 rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
] = tpc
;
2278 compsel
&= ~R200_OUTPUT_TEX_MASK
;
2279 compsel
|= rmesa
->TexMatCompSel
| rmesa
->TexGenCompSel
;
2280 if (compsel
!= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]) {
2281 R200_STATECHANGE(rmesa
, vtx
);
2282 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] = compsel
;
2286 static GLboolean
r200ValidateBuffers(GLcontext
*ctx
)
2288 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2289 struct radeon_renderbuffer
*rrb
;
2290 struct radeon_dma_bo
*dma_bo
;
2293 if (RADEON_DEBUG
& RADEON_IOCTL
)
2294 fprintf(stderr
, "%s\n", __FUNCTION__
);
2295 radeon_cs_space_reset_bos(rmesa
->radeon
.cmdbuf
.cs
);
2297 rrb
= radeon_get_colorbuffer(&rmesa
->radeon
);
2299 if (rrb
&& rrb
->bo
) {
2300 radeon_cs_space_add_persistent_bo(rmesa
->radeon
.cmdbuf
.cs
, rrb
->bo
,
2301 0, RADEON_GEM_DOMAIN_VRAM
);
2305 rrb
= radeon_get_depthbuffer(&rmesa
->radeon
);
2307 if (rrb
&& rrb
->bo
) {
2308 radeon_cs_space_add_persistent_bo(rmesa
->radeon
.cmdbuf
.cs
, rrb
->bo
,
2309 0, RADEON_GEM_DOMAIN_VRAM
);
2312 for (i
= 0; i
< ctx
->Const
.MaxTextureImageUnits
; ++i
) {
2315 if (!ctx
->Texture
.Unit
[i
]._ReallyEnabled
)
2318 t
= radeon_tex_obj(ctx
->Texture
.Unit
[i
]._Current
);
2319 if (t
->image_override
&& t
->bo
)
2320 radeon_cs_space_add_persistent_bo(rmesa
->radeon
.cmdbuf
.cs
, t
->bo
,
2321 RADEON_GEM_DOMAIN_GTT
| RADEON_GEM_DOMAIN_VRAM
, 0);
2323 radeon_cs_space_add_persistent_bo(rmesa
->radeon
.cmdbuf
.cs
, t
->mt
->bo
,
2324 RADEON_GEM_DOMAIN_GTT
| RADEON_GEM_DOMAIN_VRAM
, 0);
2327 dma_bo
= first_elem(&rmesa
->radeon
.dma
.reserved
);
2329 ret
= radeon_cs_space_check_with_bo(rmesa
->radeon
.cmdbuf
.cs
, dma_bo
->bo
, RADEON_GEM_DOMAIN_GTT
, 0);
2336 GLboolean
r200ValidateState( GLcontext
*ctx
)
2338 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2339 GLuint new_state
= rmesa
->radeon
.NewGLState
;
2341 if (new_state
& _NEW_BUFFERS
) {
2342 _mesa_update_framebuffer(ctx
);
2343 /* this updates the DrawBuffer's Width/Height if it's a FBO */
2344 _mesa_update_draw_buffer_bounds(ctx
);
2346 R200_STATECHANGE(rmesa
, ctx
);
2349 if (new_state
& (_NEW_TEXTURE
| _NEW_PROGRAM
| _NEW_PROGRAM_CONSTANTS
)) {
2350 r200UpdateTextureState( ctx
);
2351 new_state
|= rmesa
->radeon
.NewGLState
; /* may add TEXTURE_MATRIX */
2352 r200UpdateLocalViewer( ctx
);
2355 /* we need to do a space check here */
2356 if (!r200ValidateBuffers(ctx
))
2359 /* FIXME: don't really need most of these when vertex progs are enabled */
2361 /* Need an event driven matrix update?
2363 if (new_state
& (_NEW_MODELVIEW
|_NEW_PROJECTION
))
2364 upload_matrix( rmesa
, ctx
->_ModelProjectMatrix
.m
, R200_MTX_MVP
);
2366 /* Need these for lighting (shouldn't upload otherwise)
2368 if (new_state
& (_NEW_MODELVIEW
)) {
2369 upload_matrix( rmesa
, ctx
->ModelviewMatrixStack
.Top
->m
, R200_MTX_MV
);
2370 upload_matrix_t( rmesa
, ctx
->ModelviewMatrixStack
.Top
->inv
, R200_MTX_IMV
);
2373 /* Does this need to be triggered on eg. modelview for
2374 * texgen-derived objplane/eyeplane matrices?
2376 if (new_state
& (_NEW_TEXTURE
|_NEW_TEXTURE_MATRIX
)) {
2377 update_texturematrix( ctx
);
2380 if (new_state
& (_NEW_LIGHT
|_NEW_MODELVIEW
|_MESA_NEW_NEED_EYE_COORDS
)) {
2381 update_light( ctx
);
2384 /* emit all active clip planes if projection matrix changes.
2386 if (new_state
& (_NEW_PROJECTION
)) {
2387 if (ctx
->Transform
.ClipPlanesEnabled
)
2388 r200UpdateClipPlanes( ctx
);
2391 if (new_state
& (_NEW_PROGRAM
|
2392 _NEW_PROGRAM_CONSTANTS
|
2393 /* need to test for pretty much anything due to possible parameter bindings */
2394 _NEW_MODELVIEW
|_NEW_PROJECTION
|_NEW_TRANSFORM
|
2395 _NEW_LIGHT
|_NEW_TEXTURE
|_NEW_TEXTURE_MATRIX
|
2396 _NEW_FOG
|_NEW_POINT
|_NEW_TRACK_MATRIX
)) {
2397 if (ctx
->VertexProgram
._Enabled
) {
2398 r200SetupVertexProg( ctx
);
2400 else TCL_FALLBACK(ctx
, R200_TCL_FALLBACK_VERTEX_PROGRAM
, 0);
2403 rmesa
->radeon
.NewGLState
= 0;
2408 static void r200InvalidateState( GLcontext
*ctx
, GLuint new_state
)
2410 _swrast_InvalidateState( ctx
, new_state
);
2411 _swsetup_InvalidateState( ctx
, new_state
);
2412 _vbo_InvalidateState( ctx
, new_state
);
2413 _tnl_InvalidateState( ctx
, new_state
);
2414 _ae_invalidate_state( ctx
, new_state
);
2415 R200_CONTEXT(ctx
)->radeon
.NewGLState
|= new_state
;
2418 /* A hack. The r200 can actually cope just fine with materials
2419 * between begin/ends, so fix this.
2420 * Should map to inputs just like the generic vertex arrays for vertex progs.
2421 * In theory there could still be too many and we'd still need a fallback.
2423 static GLboolean
check_material( GLcontext
*ctx
)
2425 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
2428 for (i
= _TNL_ATTRIB_MAT_FRONT_AMBIENT
;
2429 i
< _TNL_ATTRIB_MAT_BACK_INDEXES
;
2431 if (tnl
->vb
.AttribPtr
[i
] &&
2432 tnl
->vb
.AttribPtr
[i
]->stride
)
2438 static void r200WrapRunPipeline( GLcontext
*ctx
)
2440 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2441 GLboolean has_material
;
2444 fprintf(stderr
, "%s, newstate: %x\n", __FUNCTION__
, rmesa
->radeon
.NewGLState
);
2448 if (rmesa
->radeon
.NewGLState
)
2449 if (!r200ValidateState( ctx
))
2450 FALLBACK(rmesa
, RADEON_FALLBACK_TEXTURE
, GL_TRUE
);
2452 has_material
= !ctx
->VertexProgram
._Enabled
&& ctx
->Light
.Enabled
&& check_material( ctx
);
2455 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_TRUE
);
2458 /* Run the pipeline.
2460 _tnl_run_pipeline( ctx
);
2463 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_FALSE
);
2468 static void r200PolygonStipple( GLcontext
*ctx
, const GLubyte
*mask
)
2470 r200ContextPtr r200
= R200_CONTEXT(ctx
);
2473 radeon_firevertices(&r200
->radeon
);
2475 radeon_print(RADEON_STATE
, RADEON_TRACE
,
2476 "%s(%p) first 32 bits are %x.\n",
2481 R200_STATECHANGE(r200
, stp
);
2483 /* Must flip pattern upside down.
2485 for ( i
= 31 ; i
>= 0; i
--) {
2486 r200
->hw
.stp
.cmd
[3 + i
] = ((GLuint
*) mask
)[i
];
2489 /* Initialize the driver's state functions.
2491 void r200InitStateFuncs( radeonContextPtr radeon
, struct dd_function_table
*functions
)
2493 functions
->UpdateState
= r200InvalidateState
;
2494 functions
->LightingSpaceChange
= r200LightingSpaceChange
;
2496 functions
->DrawBuffer
= radeonDrawBuffer
;
2497 functions
->ReadBuffer
= radeonReadBuffer
;
2499 if (radeon
->radeonScreen
->kernel_mm
) {
2500 functions
->CopyPixels
= _mesa_meta_CopyPixels
;
2501 functions
->DrawPixels
= _mesa_meta_DrawPixels
;
2502 functions
->ReadPixels
= radeonReadPixels
;
2505 functions
->AlphaFunc
= r200AlphaFunc
;
2506 functions
->BlendColor
= r200BlendColor
;
2507 functions
->BlendEquationSeparate
= r200BlendEquationSeparate
;
2508 functions
->BlendFuncSeparate
= r200BlendFuncSeparate
;
2509 functions
->ClearColor
= r200ClearColor
;
2510 functions
->ClearDepth
= r200ClearDepth
;
2511 functions
->ClearStencil
= r200ClearStencil
;
2512 functions
->ClipPlane
= r200ClipPlane
;
2513 functions
->ColorMask
= r200ColorMask
;
2514 functions
->CullFace
= r200CullFace
;
2515 functions
->DepthFunc
= r200DepthFunc
;
2516 functions
->DepthMask
= r200DepthMask
;
2517 functions
->DepthRange
= r200DepthRange
;
2518 functions
->Enable
= r200Enable
;
2519 functions
->Fogfv
= r200Fogfv
;
2520 functions
->FrontFace
= r200FrontFace
;
2521 functions
->Hint
= NULL
;
2522 functions
->LightModelfv
= r200LightModelfv
;
2523 functions
->Lightfv
= r200Lightfv
;
2524 functions
->LineStipple
= r200LineStipple
;
2525 functions
->LineWidth
= r200LineWidth
;
2526 functions
->LogicOpcode
= r200LogicOpCode
;
2527 functions
->PolygonMode
= r200PolygonMode
;
2528 functions
->PolygonOffset
= r200PolygonOffset
;
2529 functions
->PolygonStipple
= r200PolygonStipple
;
2530 functions
->PointParameterfv
= r200PointParameter
;
2531 functions
->PointSize
= r200PointSize
;
2532 functions
->RenderMode
= r200RenderMode
;
2533 functions
->Scissor
= radeonScissor
;
2534 functions
->ShadeModel
= r200ShadeModel
;
2535 functions
->StencilFuncSeparate
= r200StencilFuncSeparate
;
2536 functions
->StencilMaskSeparate
= r200StencilMaskSeparate
;
2537 functions
->StencilOpSeparate
= r200StencilOpSeparate
;
2538 functions
->Viewport
= r200Viewport
;
2542 void r200InitTnlFuncs( GLcontext
*ctx
)
2544 TNL_CONTEXT(ctx
)->Driver
.NotifyMaterialChange
= r200UpdateMaterial
;
2545 TNL_CONTEXT(ctx
)->Driver
.RunPipeline
= r200WrapRunPipeline
;