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"
50 #include "radeon_common.h"
51 #include "radeon_mipmap_tree.h"
52 #include "r200_context.h"
53 #include "r200_ioctl.h"
54 #include "r200_state.h"
57 #include "r200_swtcl.h"
58 #include "r200_vertprog.h"
60 #include "drirenderbuffer.h"
63 /* =============================================================
67 static void r200AlphaFunc( GLcontext
*ctx
, GLenum func
, GLfloat ref
)
69 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
70 int pp_misc
= rmesa
->hw
.ctx
.cmd
[CTX_PP_MISC
];
73 CLAMPED_FLOAT_TO_UBYTE(refByte
, ref
);
75 R200_STATECHANGE( rmesa
, ctx
);
77 pp_misc
&= ~(R200_ALPHA_TEST_OP_MASK
| R200_REF_ALPHA_MASK
);
78 pp_misc
|= (refByte
& R200_REF_ALPHA_MASK
);
82 pp_misc
|= R200_ALPHA_TEST_FAIL
;
85 pp_misc
|= R200_ALPHA_TEST_LESS
;
88 pp_misc
|= R200_ALPHA_TEST_EQUAL
;
91 pp_misc
|= R200_ALPHA_TEST_LEQUAL
;
94 pp_misc
|= R200_ALPHA_TEST_GREATER
;
97 pp_misc
|= R200_ALPHA_TEST_NEQUAL
;
100 pp_misc
|= R200_ALPHA_TEST_GEQUAL
;
103 pp_misc
|= R200_ALPHA_TEST_PASS
;
107 rmesa
->hw
.ctx
.cmd
[CTX_PP_MISC
] = pp_misc
;
110 static void r200BlendColor( GLcontext
*ctx
, const GLfloat cf
[4] )
113 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
114 R200_STATECHANGE( rmesa
, ctx
);
115 CLAMPED_FLOAT_TO_UBYTE(color
[0], cf
[0]);
116 CLAMPED_FLOAT_TO_UBYTE(color
[1], cf
[1]);
117 CLAMPED_FLOAT_TO_UBYTE(color
[2], cf
[2]);
118 CLAMPED_FLOAT_TO_UBYTE(color
[3], cf
[3]);
119 if (rmesa
->radeon
.radeonScreen
->drmSupportsBlendColor
)
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( GLcontext
* 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 (rmesa
->radeon
.radeonScreen
->drmSupportsBlendColor
) {
219 if (ctx
->Color
.ColorLogicOpEnabled
) {
220 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
| R200_ROP_ENABLE
;
221 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ABLENDCNTL
] = eqn
| func
;
222 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CBLENDCNTL
] = eqn
| func
;
224 } else if (ctx
->Color
.BlendEnabled
) {
225 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
| R200_ALPHA_BLEND_ENABLE
| R200_SEPARATE_ALPHA_ENABLE
;
228 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
;
229 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ABLENDCNTL
] = eqn
| func
;
230 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CBLENDCNTL
] = eqn
| func
;
235 if (ctx
->Color
.ColorLogicOpEnabled
) {
236 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
| R200_ROP_ENABLE
;
237 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] = eqn
| func
;
239 } else if (ctx
->Color
.BlendEnabled
) {
240 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
| R200_ALPHA_BLEND_ENABLE
;
243 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
;
244 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] = eqn
| func
;
249 func
= (blend_factor( ctx
->Color
.BlendSrcRGB
, GL_TRUE
) << R200_SRC_BLEND_SHIFT
) |
250 (blend_factor( ctx
->Color
.BlendDstRGB
, GL_FALSE
) << R200_DST_BLEND_SHIFT
);
252 switch(ctx
->Color
.BlendEquationRGB
) {
254 eqn
= R200_COMB_FCN_ADD_CLAMP
;
257 case GL_FUNC_SUBTRACT
:
258 eqn
= R200_COMB_FCN_SUB_CLAMP
;
261 case GL_FUNC_REVERSE_SUBTRACT
:
262 eqn
= R200_COMB_FCN_RSUB_CLAMP
;
266 eqn
= R200_COMB_FCN_MIN
;
267 func
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
268 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
272 eqn
= R200_COMB_FCN_MAX
;
273 func
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
274 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
278 fprintf( stderr
, "[%s:%u] Invalid RGB blend equation (0x%04x).\n",
279 __FUNCTION__
, __LINE__
, ctx
->Color
.BlendEquationRGB
);
283 if (!rmesa
->radeon
.radeonScreen
->drmSupportsBlendColor
) {
284 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] = eqn
| func
;
288 funcA
= (blend_factor( ctx
->Color
.BlendSrcA
, GL_TRUE
) << R200_SRC_BLEND_SHIFT
) |
289 (blend_factor( ctx
->Color
.BlendDstA
, GL_FALSE
) << R200_DST_BLEND_SHIFT
);
291 switch(ctx
->Color
.BlendEquationA
) {
293 eqnA
= R200_COMB_FCN_ADD_CLAMP
;
296 case GL_FUNC_SUBTRACT
:
297 eqnA
= R200_COMB_FCN_SUB_CLAMP
;
300 case GL_FUNC_REVERSE_SUBTRACT
:
301 eqnA
= R200_COMB_FCN_RSUB_CLAMP
;
305 eqnA
= R200_COMB_FCN_MIN
;
306 funcA
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
307 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
311 eqnA
= R200_COMB_FCN_MAX
;
312 funcA
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
313 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
317 fprintf( stderr
, "[%s:%u] Invalid A blend equation (0x%04x).\n",
318 __FUNCTION__
, __LINE__
, ctx
->Color
.BlendEquationA
);
322 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ABLENDCNTL
] = eqnA
| funcA
;
323 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CBLENDCNTL
] = eqn
| func
;
327 static void r200BlendEquationSeparate( GLcontext
*ctx
,
328 GLenum modeRGB
, GLenum modeA
)
330 r200_set_blend_state( ctx
);
333 static void r200BlendFuncSeparate( GLcontext
*ctx
,
334 GLenum sfactorRGB
, GLenum dfactorRGB
,
335 GLenum sfactorA
, GLenum dfactorA
)
337 r200_set_blend_state( ctx
);
341 /* =============================================================
345 static void r200DepthFunc( GLcontext
*ctx
, GLenum func
)
347 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
349 R200_STATECHANGE( rmesa
, ctx
);
350 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_Z_TEST_MASK
;
352 switch ( ctx
->Depth
.Func
) {
354 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_NEVER
;
357 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_LESS
;
360 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_EQUAL
;
363 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_LEQUAL
;
366 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_GREATER
;
369 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_NEQUAL
;
372 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_GEQUAL
;
375 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_ALWAYS
;
380 static void r200ClearDepth( GLcontext
*ctx
, GLclampd d
)
382 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
383 GLuint format
= (rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &
384 R200_DEPTH_FORMAT_MASK
);
387 case R200_DEPTH_FORMAT_16BIT_INT_Z
:
388 rmesa
->radeon
.state
.depth
.clear
= d
* 0x0000ffff;
390 case R200_DEPTH_FORMAT_24BIT_INT_Z
:
391 rmesa
->radeon
.state
.depth
.clear
= d
* 0x00ffffff;
396 static void r200DepthMask( GLcontext
*ctx
, GLboolean flag
)
398 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
399 R200_STATECHANGE( rmesa
, ctx
);
401 if ( ctx
->Depth
.Mask
) {
402 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_WRITE_ENABLE
;
404 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_Z_WRITE_ENABLE
;
409 /* =============================================================
414 static void r200Fogfv( GLcontext
*ctx
, GLenum pname
, const GLfloat
*param
)
416 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
417 union { int i
; float f
; } c
, d
;
421 c
.i
= rmesa
->hw
.fog
.cmd
[FOG_C
];
422 d
.i
= rmesa
->hw
.fog
.cmd
[FOG_D
];
426 if (!ctx
->Fog
.Enabled
)
428 R200_STATECHANGE(rmesa
, tcl
);
429 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_TCL_FOG_MASK
;
430 switch (ctx
->Fog
.Mode
) {
432 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_LINEAR
;
433 if (ctx
->Fog
.Start
== ctx
->Fog
.End
) {
438 c
.f
= ctx
->Fog
.End
/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
439 d
.f
= -1.0/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
443 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_EXP
;
445 d
.f
= -ctx
->Fog
.Density
;
448 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_EXP2
;
450 d
.f
= -(ctx
->Fog
.Density
* ctx
->Fog
.Density
);
457 switch (ctx
->Fog
.Mode
) {
460 d
.f
= -ctx
->Fog
.Density
;
464 d
.f
= -(ctx
->Fog
.Density
* ctx
->Fog
.Density
);
472 if (ctx
->Fog
.Mode
== GL_LINEAR
) {
473 if (ctx
->Fog
.Start
== ctx
->Fog
.End
) {
477 c
.f
= ctx
->Fog
.End
/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
478 d
.f
= -1.0/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
483 R200_STATECHANGE( rmesa
, ctx
);
484 UNCLAMPED_FLOAT_TO_RGB_CHAN( col
, ctx
->Fog
.Color
);
485 i
= radeonPackColor( 4, col
[0], col
[1], col
[2], 0 );
486 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] &= ~R200_FOG_COLOR_MASK
;
487 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] |= i
;
489 case GL_FOG_COORD_SRC
: {
490 GLuint out_0
= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
];
491 GLuint fog
= rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
];
493 fog
&= ~R200_FOG_USE_MASK
;
494 if ( ctx
->Fog
.FogCoordinateSource
== GL_FOG_COORD
|| ctx
->VertexProgram
.Enabled
) {
495 fog
|= R200_FOG_USE_VTX_FOG
;
496 out_0
|= R200_VTX_DISCRETE_FOG
;
499 fog
|= R200_FOG_USE_SPEC_ALPHA
;
500 out_0
&= ~R200_VTX_DISCRETE_FOG
;
503 if ( fog
!= rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] ) {
504 R200_STATECHANGE( rmesa
, ctx
);
505 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] = fog
;
508 if (out_0
!= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
]) {
509 R200_STATECHANGE( rmesa
, vtx
);
510 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] = out_0
;
519 if (c
.i
!= rmesa
->hw
.fog
.cmd
[FOG_C
] || d
.i
!= rmesa
->hw
.fog
.cmd
[FOG_D
]) {
520 R200_STATECHANGE( rmesa
, fog
);
521 rmesa
->hw
.fog
.cmd
[FOG_C
] = c
.i
;
522 rmesa
->hw
.fog
.cmd
[FOG_D
] = d
.i
;
526 /* =============================================================
530 static void r200CullFace( GLcontext
*ctx
, GLenum unused
)
532 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
533 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
534 GLuint t
= rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
];
536 s
|= R200_FFACE_SOLID
| R200_BFACE_SOLID
;
537 t
&= ~(R200_CULL_FRONT
| R200_CULL_BACK
);
539 if ( ctx
->Polygon
.CullFlag
) {
540 switch ( ctx
->Polygon
.CullFaceMode
) {
542 s
&= ~R200_FFACE_SOLID
;
543 t
|= R200_CULL_FRONT
;
546 s
&= ~R200_BFACE_SOLID
;
549 case GL_FRONT_AND_BACK
:
550 s
&= ~(R200_FFACE_SOLID
| R200_BFACE_SOLID
);
551 t
|= (R200_CULL_FRONT
| R200_CULL_BACK
);
556 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
557 R200_STATECHANGE(rmesa
, set
);
558 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
561 if ( rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] != t
) {
562 R200_STATECHANGE(rmesa
, tcl
);
563 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] = t
;
567 static void r200FrontFace( GLcontext
*ctx
, GLenum mode
)
569 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
571 R200_STATECHANGE( rmesa
, set
);
572 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_FFACE_CULL_DIR_MASK
;
574 R200_STATECHANGE( rmesa
, tcl
);
575 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_CULL_FRONT_IS_CCW
;
577 /* Winding is inverted when rendering to FBO */
578 if (ctx
->DrawBuffer
&& ctx
->DrawBuffer
->Name
)
579 mode
= (mode
== GL_CW
) ? GL_CCW
: GL_CW
;
583 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_FFACE_CULL_CW
;
586 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_FFACE_CULL_CCW
;
587 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_CULL_FRONT_IS_CCW
;
592 /* =============================================================
595 static void r200PointSize( GLcontext
*ctx
, GLfloat size
)
597 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
598 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.ptp
.cmd
;
600 R200_STATECHANGE( rmesa
, cst
);
601 R200_STATECHANGE( rmesa
, ptp
);
602 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] &= ~0xffff;
603 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] |= ((GLuint
)(ctx
->Point
.Size
* 16.0));
604 /* this is the size param of the point size calculation (point size reg value
605 is not used when calculation is active). */
606 fcmd
[PTP_VPORT_SCALE_PTSIZE
] = ctx
->Point
.Size
;
609 static void r200PointParameter( GLcontext
*ctx
, GLenum pname
, const GLfloat
*params
)
611 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
612 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.ptp
.cmd
;
615 case GL_POINT_SIZE_MIN
:
616 /* Can clamp both in tcl and setup - just set both (as does fglrx) */
617 R200_STATECHANGE( rmesa
, lin
);
618 R200_STATECHANGE( rmesa
, ptp
);
619 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] &= 0xffff;
620 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] |= (GLuint
)(ctx
->Point
.MinSize
* 16.0) << 16;
621 fcmd
[PTP_CLAMP_MIN
] = ctx
->Point
.MinSize
;
623 case GL_POINT_SIZE_MAX
:
624 R200_STATECHANGE( rmesa
, cst
);
625 R200_STATECHANGE( rmesa
, ptp
);
626 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] &= 0xffff;
627 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] |= (GLuint
)(ctx
->Point
.MaxSize
* 16.0) << 16;
628 fcmd
[PTP_CLAMP_MAX
] = ctx
->Point
.MaxSize
;
630 case GL_POINT_DISTANCE_ATTENUATION
:
631 R200_STATECHANGE( rmesa
, vtx
);
632 R200_STATECHANGE( rmesa
, spr
);
633 R200_STATECHANGE( rmesa
, ptp
);
634 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.ptp
.cmd
;
635 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] &=
636 ~(R200_PS_MULT_MASK
| R200_PS_LIN_ATT_ZERO
| R200_PS_SE_SEL_STATE
);
637 /* can't rely on ctx->Point._Attenuated here and test for NEW_POINT in
638 r200ValidateState looks like overkill */
639 if (ctx
->Point
.Params
[0] != 1.0 ||
640 ctx
->Point
.Params
[1] != 0.0 ||
641 ctx
->Point
.Params
[2] != 0.0 ||
642 (ctx
->VertexProgram
.Enabled
&& ctx
->VertexProgram
.PointSizeEnabled
)) {
643 /* all we care for vp would be the ps_se_sel_state setting */
644 fcmd
[PTP_ATT_CONST_QUAD
] = ctx
->Point
.Params
[2];
645 fcmd
[PTP_ATT_CONST_LIN
] = ctx
->Point
.Params
[1];
646 fcmd
[PTP_ATT_CONST_CON
] = ctx
->Point
.Params
[0];
647 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |= R200_PS_MULT_ATTENCONST
;
648 if (ctx
->Point
.Params
[1] == 0.0)
649 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |= R200_PS_LIN_ATT_ZERO
;
650 /* FIXME: setting this here doesn't look quite ok - we only want to do
651 that if we're actually drawing points probably */
652 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_PT_SIZE
;
653 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |= R200_VTX_POINT_SIZE
;
656 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |=
657 R200_PS_SE_SEL_STATE
| R200_PS_MULT_CONST
;
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 case GL_POINT_FADE_THRESHOLD_SIZE
:
663 /* don't support multisampling, so doesn't matter. */
665 /* can't do these but don't need them.
666 case GL_POINT_SPRITE_R_MODE_NV:
667 case GL_POINT_SPRITE_COORD_ORIGIN: */
669 fprintf(stderr
, "bad pname parameter in r200PointParameter\n");
674 /* =============================================================
677 static void r200LineWidth( GLcontext
*ctx
, GLfloat widthf
)
679 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
681 R200_STATECHANGE( rmesa
, lin
);
682 R200_STATECHANGE( rmesa
, set
);
684 /* Line width is stored in U6.4 format.
685 * Same min/max limits for AA, non-AA lines.
687 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] &= ~0xffff;
688 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] |= (GLuint
)
689 (CLAMP(widthf
, ctx
->Const
.MinLineWidth
, ctx
->Const
.MaxLineWidth
) * 16.0);
691 if ( widthf
> 1.0 ) {
692 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_WIDELINE_ENABLE
;
694 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_WIDELINE_ENABLE
;
698 static void r200LineStipple( GLcontext
*ctx
, GLint factor
, GLushort pattern
)
700 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
702 R200_STATECHANGE( rmesa
, lin
);
703 rmesa
->hw
.lin
.cmd
[LIN_RE_LINE_PATTERN
] =
704 ((((GLuint
)factor
& 0xff) << 16) | ((GLuint
)pattern
));
708 /* =============================================================
711 static void r200ColorMask( GLcontext
*ctx
,
712 GLboolean r
, GLboolean g
,
713 GLboolean b
, GLboolean a
)
715 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
717 struct radeon_renderbuffer
*rrb
;
718 GLuint flag
= rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] & ~R200_PLANE_MASK_ENABLE
;
720 rrb
= radeon_get_colorbuffer(&rmesa
->radeon
);
723 mask
= radeonPackColor( rrb
->cpp
,
724 ctx
->Color
.ColorMask
[0][RCOMP
],
725 ctx
->Color
.ColorMask
[0][GCOMP
],
726 ctx
->Color
.ColorMask
[0][BCOMP
],
727 ctx
->Color
.ColorMask
[0][ACOMP
] );
730 if (!(r
&& g
&& b
&& a
))
731 flag
|= R200_PLANE_MASK_ENABLE
;
733 if ( rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] != flag
) {
734 R200_STATECHANGE( rmesa
, ctx
);
735 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = flag
;
738 if ( rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
] != mask
) {
739 R200_STATECHANGE( rmesa
, msk
);
740 rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
] = mask
;
745 /* =============================================================
749 static void r200PolygonOffset( GLcontext
*ctx
,
750 GLfloat factor
, GLfloat units
)
752 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
753 const GLfloat depthScale
= 1.0F
/ ctx
->DrawBuffer
->_DepthMaxF
;
754 float_ui32_type constant
= { units
* depthScale
};
755 float_ui32_type factoru
= { factor
};
760 /* fprintf(stderr, "%s f:%f u:%f\n", __FUNCTION__, factor, constant); */
762 R200_STATECHANGE( rmesa
, zbs
);
763 rmesa
->hw
.zbs
.cmd
[ZBS_SE_ZBIAS_FACTOR
] = factoru
.ui32
;
764 rmesa
->hw
.zbs
.cmd
[ZBS_SE_ZBIAS_CONSTANT
] = constant
.ui32
;
767 static void r200PolygonMode( GLcontext
*ctx
, GLenum face
, GLenum mode
)
769 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
770 GLboolean flag
= (ctx
->_TriangleCaps
& DD_TRI_UNFILLED
) != 0;
772 /* Can't generally do unfilled via tcl, but some good special
775 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_UNFILLED
, flag
);
776 if (rmesa
->radeon
.TclFallback
) {
777 r200ChooseRenderState( ctx
);
778 r200ChooseVertexState( ctx
);
783 /* =============================================================
784 * Rendering attributes
786 * We really don't want to recalculate all this every time we bind a
787 * texture. These things shouldn't change all that often, so it makes
788 * sense to break them out of the core texture state update routines.
791 /* Examine lighting and texture state to determine if separate specular
794 static void r200UpdateSpecular( GLcontext
*ctx
)
796 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
797 uint32_t p
= rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
];
799 R200_STATECHANGE( rmesa
, tcl
);
800 R200_STATECHANGE( rmesa
, vtx
);
802 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~(3<<R200_VTX_COLOR_0_SHIFT
);
803 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~(3<<R200_VTX_COLOR_1_SHIFT
);
804 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_COLOR_0
;
805 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_COLOR_1
;
806 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LIGHTING_ENABLE
;
808 p
&= ~R200_SPECULAR_ENABLE
;
810 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_DIFFUSE_SPECULAR_COMBINE
;
813 if (ctx
->Light
.Enabled
&&
814 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
) {
815 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
816 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
) |
817 (R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
818 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_0
;
819 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_1
;
820 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHTING_ENABLE
;
821 p
|= R200_SPECULAR_ENABLE
;
822 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &=
823 ~R200_DIFFUSE_SPECULAR_COMBINE
;
825 else if (ctx
->Light
.Enabled
) {
826 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
827 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
));
828 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_0
;
829 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHTING_ENABLE
;
830 } else if (ctx
->Fog
.ColorSumEnabled
) {
831 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
832 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
) |
833 (R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
834 p
|= R200_SPECULAR_ENABLE
;
836 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
837 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
));
840 if (ctx
->Fog
.Enabled
) {
841 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
842 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
843 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_1
;
846 if ( rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] != p
) {
847 R200_STATECHANGE( rmesa
, ctx
);
848 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] = p
;
851 /* Update vertex/render formats
853 if (rmesa
->radeon
.TclFallback
) {
854 r200ChooseRenderState( ctx
);
855 r200ChooseVertexState( ctx
);
860 /* =============================================================
865 /* Update on colormaterial, material emmissive/ambient,
866 * lightmodel.globalambient
868 static void update_global_ambient( GLcontext
*ctx
)
870 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
871 float *fcmd
= (float *)R200_DB_STATE( glt
);
873 /* Need to do more if both emmissive & ambient are PREMULT:
874 * I believe this is not nessary when using source_material. This condition thus
875 * will never happen currently, and the function has no dependencies on materials now
877 if ((rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
] &
878 ((3 << R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
879 (3 << R200_FRONT_AMBIENT_SOURCE_SHIFT
))) == 0)
881 COPY_3V( &fcmd
[GLT_RED
],
882 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_EMISSION
]);
883 ACC_SCALE_3V( &fcmd
[GLT_RED
],
884 ctx
->Light
.Model
.Ambient
,
885 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_AMBIENT
]);
889 COPY_3V( &fcmd
[GLT_RED
], ctx
->Light
.Model
.Ambient
);
892 R200_DB_STATECHANGE(rmesa
, &rmesa
->hw
.glt
);
895 /* Update on change to
899 static void update_light_colors( GLcontext
*ctx
, GLuint p
)
901 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
903 /* fprintf(stderr, "%s\n", __FUNCTION__); */
906 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
907 float *fcmd
= (float *)R200_DB_STATE( lit
[p
] );
909 COPY_4V( &fcmd
[LIT_AMBIENT_RED
], l
->Ambient
);
910 COPY_4V( &fcmd
[LIT_DIFFUSE_RED
], l
->Diffuse
);
911 COPY_4V( &fcmd
[LIT_SPECULAR_RED
], l
->Specular
);
913 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
917 static void r200ColorMaterial( GLcontext
*ctx
, GLenum face
, GLenum mode
)
919 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
920 GLuint light_model_ctl1
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
];
921 light_model_ctl1
&= ~((0xf << R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
922 (0xf << R200_FRONT_AMBIENT_SOURCE_SHIFT
) |
923 (0xf << R200_FRONT_DIFFUSE_SOURCE_SHIFT
) |
924 (0xf << R200_FRONT_SPECULAR_SOURCE_SHIFT
) |
925 (0xf << R200_BACK_EMISSIVE_SOURCE_SHIFT
) |
926 (0xf << R200_BACK_AMBIENT_SOURCE_SHIFT
) |
927 (0xf << R200_BACK_DIFFUSE_SOURCE_SHIFT
) |
928 (0xf << R200_BACK_SPECULAR_SOURCE_SHIFT
));
930 if (ctx
->Light
.ColorMaterialEnabled
) {
931 GLuint mask
= ctx
->Light
.ColorMaterialBitmask
;
933 if (mask
& MAT_BIT_FRONT_EMISSION
) {
934 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
935 R200_FRONT_EMISSIVE_SOURCE_SHIFT
);
938 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
939 R200_FRONT_EMISSIVE_SOURCE_SHIFT
);
941 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
942 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
943 R200_FRONT_AMBIENT_SOURCE_SHIFT
);
946 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
947 R200_FRONT_AMBIENT_SOURCE_SHIFT
);
949 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
950 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
951 R200_FRONT_DIFFUSE_SOURCE_SHIFT
);
954 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
955 R200_FRONT_DIFFUSE_SOURCE_SHIFT
);
957 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
958 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
959 R200_FRONT_SPECULAR_SOURCE_SHIFT
);
962 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
963 R200_FRONT_SPECULAR_SOURCE_SHIFT
);
966 if (mask
& MAT_BIT_BACK_EMISSION
) {
967 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
968 R200_BACK_EMISSIVE_SOURCE_SHIFT
);
971 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
972 R200_BACK_EMISSIVE_SOURCE_SHIFT
);
974 if (mask
& MAT_BIT_BACK_AMBIENT
) {
975 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
976 R200_BACK_AMBIENT_SOURCE_SHIFT
);
978 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
979 R200_BACK_AMBIENT_SOURCE_SHIFT
);
981 if (mask
& MAT_BIT_BACK_DIFFUSE
) {
982 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
983 R200_BACK_DIFFUSE_SOURCE_SHIFT
);
985 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
986 R200_BACK_DIFFUSE_SOURCE_SHIFT
);
988 if (mask
& MAT_BIT_BACK_SPECULAR
) {
989 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
990 R200_BACK_SPECULAR_SOURCE_SHIFT
);
993 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
994 R200_BACK_SPECULAR_SOURCE_SHIFT
);
998 /* Default to SOURCE_MATERIAL:
1001 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
1002 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_AMBIENT_SOURCE_SHIFT
) |
1003 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_DIFFUSE_SOURCE_SHIFT
) |
1004 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_SPECULAR_SOURCE_SHIFT
) |
1005 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_EMISSIVE_SOURCE_SHIFT
) |
1006 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_AMBIENT_SOURCE_SHIFT
) |
1007 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_DIFFUSE_SOURCE_SHIFT
) |
1008 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_SPECULAR_SOURCE_SHIFT
);
1011 if (light_model_ctl1
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
]) {
1012 R200_STATECHANGE( rmesa
, tcl
);
1013 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
] = light_model_ctl1
;
1019 void r200UpdateMaterial( GLcontext
*ctx
)
1021 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1022 GLfloat (*mat
)[4] = ctx
->Light
.Material
.Attrib
;
1023 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( mtl
[0] );
1024 GLfloat
*fcmd2
= (GLfloat
*)R200_DB_STATE( mtl
[1] );
1027 /* Might be possible and faster to update everything unconditionally? */
1028 if (ctx
->Light
.ColorMaterialEnabled
)
1029 mask
&= ~ctx
->Light
.ColorMaterialBitmask
;
1031 if (R200_DEBUG
& RADEON_STATE
)
1032 fprintf(stderr
, "%s\n", __FUNCTION__
);
1034 if (mask
& MAT_BIT_FRONT_EMISSION
) {
1035 fcmd
[MTL_EMMISSIVE_RED
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][0];
1036 fcmd
[MTL_EMMISSIVE_GREEN
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][1];
1037 fcmd
[MTL_EMMISSIVE_BLUE
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][2];
1038 fcmd
[MTL_EMMISSIVE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][3];
1040 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
1041 fcmd
[MTL_AMBIENT_RED
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][0];
1042 fcmd
[MTL_AMBIENT_GREEN
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][1];
1043 fcmd
[MTL_AMBIENT_BLUE
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][2];
1044 fcmd
[MTL_AMBIENT_ALPHA
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][3];
1046 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
1047 fcmd
[MTL_DIFFUSE_RED
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][0];
1048 fcmd
[MTL_DIFFUSE_GREEN
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][1];
1049 fcmd
[MTL_DIFFUSE_BLUE
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][2];
1050 fcmd
[MTL_DIFFUSE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][3];
1052 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
1053 fcmd
[MTL_SPECULAR_RED
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][0];
1054 fcmd
[MTL_SPECULAR_GREEN
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][1];
1055 fcmd
[MTL_SPECULAR_BLUE
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][2];
1056 fcmd
[MTL_SPECULAR_ALPHA
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][3];
1058 if (mask
& MAT_BIT_FRONT_SHININESS
) {
1059 fcmd
[MTL_SHININESS
] = mat
[MAT_ATTRIB_FRONT_SHININESS
][0];
1062 if (mask
& MAT_BIT_BACK_EMISSION
) {
1063 fcmd2
[MTL_EMMISSIVE_RED
] = mat
[MAT_ATTRIB_BACK_EMISSION
][0];
1064 fcmd2
[MTL_EMMISSIVE_GREEN
] = mat
[MAT_ATTRIB_BACK_EMISSION
][1];
1065 fcmd2
[MTL_EMMISSIVE_BLUE
] = mat
[MAT_ATTRIB_BACK_EMISSION
][2];
1066 fcmd2
[MTL_EMMISSIVE_ALPHA
] = mat
[MAT_ATTRIB_BACK_EMISSION
][3];
1068 if (mask
& MAT_BIT_BACK_AMBIENT
) {
1069 fcmd2
[MTL_AMBIENT_RED
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][0];
1070 fcmd2
[MTL_AMBIENT_GREEN
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][1];
1071 fcmd2
[MTL_AMBIENT_BLUE
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][2];
1072 fcmd2
[MTL_AMBIENT_ALPHA
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][3];
1074 if (mask
& MAT_BIT_BACK_DIFFUSE
) {
1075 fcmd2
[MTL_DIFFUSE_RED
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][0];
1076 fcmd2
[MTL_DIFFUSE_GREEN
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][1];
1077 fcmd2
[MTL_DIFFUSE_BLUE
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][2];
1078 fcmd2
[MTL_DIFFUSE_ALPHA
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][3];
1080 if (mask
& MAT_BIT_BACK_SPECULAR
) {
1081 fcmd2
[MTL_SPECULAR_RED
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][0];
1082 fcmd2
[MTL_SPECULAR_GREEN
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][1];
1083 fcmd2
[MTL_SPECULAR_BLUE
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][2];
1084 fcmd2
[MTL_SPECULAR_ALPHA
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][3];
1086 if (mask
& MAT_BIT_BACK_SHININESS
) {
1087 fcmd2
[MTL_SHININESS
] = mat
[MAT_ATTRIB_BACK_SHININESS
][0];
1090 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mtl
[0] );
1091 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mtl
[1] );
1093 /* currently material changes cannot trigger a global ambient change, I believe this is correct
1094 update_global_ambient( ctx ); */
1099 * _MESA_NEW_NEED_EYE_COORDS
1101 * Uses derived state from mesa:
1105 * _NormSpotDirection
1106 * _ModelViewInvScale
1110 * which are calculated in light.c and are correct for the current
1111 * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
1112 * and _MESA_NEW_NEED_EYE_COORDS.
1114 static void update_light( GLcontext
*ctx
)
1116 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1118 /* Have to check these, or have an automatic shortcircuit mechanism
1119 * to remove noop statechanges. (Or just do a better job on the
1123 GLuint tmp
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
];
1125 if (ctx
->_NeedEyeCoords
)
1126 tmp
&= ~R200_LIGHT_IN_MODELSPACE
;
1128 tmp
|= R200_LIGHT_IN_MODELSPACE
;
1130 if (tmp
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
])
1132 R200_STATECHANGE( rmesa
, tcl
);
1133 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] = tmp
;
1138 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( eye
);
1139 fcmd
[EYE_X
] = ctx
->_EyeZDir
[0];
1140 fcmd
[EYE_Y
] = ctx
->_EyeZDir
[1];
1141 fcmd
[EYE_Z
] = - ctx
->_EyeZDir
[2];
1142 fcmd
[EYE_RESCALE_FACTOR
] = ctx
->_ModelViewInvScale
;
1143 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.eye
);
1148 if (ctx
->Light
.Enabled
) {
1150 for (p
= 0 ; p
< MAX_LIGHTS
; p
++) {
1151 if (ctx
->Light
.Light
[p
].Enabled
) {
1152 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1153 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( lit
[p
] );
1155 if (l
->EyePosition
[3] == 0.0) {
1156 COPY_3FV( &fcmd
[LIT_POSITION_X
], l
->_VP_inf_norm
);
1157 COPY_3FV( &fcmd
[LIT_DIRECTION_X
], l
->_h_inf_norm
);
1158 fcmd
[LIT_POSITION_W
] = 0;
1159 fcmd
[LIT_DIRECTION_W
] = 0;
1161 COPY_4V( &fcmd
[LIT_POSITION_X
], l
->_Position
);
1162 fcmd
[LIT_DIRECTION_X
] = -l
->_NormSpotDirection
[0];
1163 fcmd
[LIT_DIRECTION_Y
] = -l
->_NormSpotDirection
[1];
1164 fcmd
[LIT_DIRECTION_Z
] = -l
->_NormSpotDirection
[2];
1165 fcmd
[LIT_DIRECTION_W
] = 0;
1168 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
1174 static void r200Lightfv( GLcontext
*ctx
, GLenum light
,
1175 GLenum pname
, const GLfloat
*params
)
1177 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1178 GLint p
= light
- GL_LIGHT0
;
1179 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1180 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.lit
[p
].cmd
;
1187 update_light_colors( ctx
, p
);
1190 case GL_SPOT_DIRECTION
:
1191 /* picked up in update_light */
1195 /* positions picked up in update_light, but can do flag here */
1196 GLuint flag
= (p
&1)? R200_LIGHT_1_IS_LOCAL
: R200_LIGHT_0_IS_LOCAL
;
1197 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1199 R200_STATECHANGE(rmesa
, tcl
);
1200 if (l
->EyePosition
[3] != 0.0F
)
1201 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1203 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1207 case GL_SPOT_EXPONENT
:
1208 R200_STATECHANGE(rmesa
, lit
[p
]);
1209 fcmd
[LIT_SPOT_EXPONENT
] = params
[0];
1212 case GL_SPOT_CUTOFF
: {
1213 GLuint flag
= (p
&1) ? R200_LIGHT_1_IS_SPOT
: R200_LIGHT_0_IS_SPOT
;
1214 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1216 R200_STATECHANGE(rmesa
, lit
[p
]);
1217 fcmd
[LIT_SPOT_CUTOFF
] = l
->_CosCutoff
;
1219 R200_STATECHANGE(rmesa
, tcl
);
1220 if (l
->SpotCutoff
!= 180.0F
)
1221 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1223 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1228 case GL_CONSTANT_ATTENUATION
:
1229 R200_STATECHANGE(rmesa
, lit
[p
]);
1230 fcmd
[LIT_ATTEN_CONST
] = params
[0];
1231 if ( params
[0] == 0.0 )
1232 fcmd
[LIT_ATTEN_CONST_INV
] = FLT_MAX
;
1234 fcmd
[LIT_ATTEN_CONST_INV
] = 1.0 / params
[0];
1236 case GL_LINEAR_ATTENUATION
:
1237 R200_STATECHANGE(rmesa
, lit
[p
]);
1238 fcmd
[LIT_ATTEN_LINEAR
] = params
[0];
1240 case GL_QUADRATIC_ATTENUATION
:
1241 R200_STATECHANGE(rmesa
, lit
[p
]);
1242 fcmd
[LIT_ATTEN_QUADRATIC
] = params
[0];
1248 /* Set RANGE_ATTEN only when needed */
1251 case GL_CONSTANT_ATTENUATION
:
1252 case GL_LINEAR_ATTENUATION
:
1253 case GL_QUADRATIC_ATTENUATION
: {
1254 GLuint
*icmd
= (GLuint
*)R200_DB_STATE( tcl
);
1255 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1256 GLuint atten_flag
= ( p
&1 ) ? R200_LIGHT_1_ENABLE_RANGE_ATTEN
1257 : R200_LIGHT_0_ENABLE_RANGE_ATTEN
;
1258 GLuint atten_const_flag
= ( p
&1 ) ? R200_LIGHT_1_CONSTANT_RANGE_ATTEN
1259 : R200_LIGHT_0_CONSTANT_RANGE_ATTEN
;
1261 if ( l
->EyePosition
[3] == 0.0F
||
1262 ( ( fcmd
[LIT_ATTEN_CONST
] == 0.0 || fcmd
[LIT_ATTEN_CONST
] == 1.0 ) &&
1263 fcmd
[LIT_ATTEN_QUADRATIC
] == 0.0 && fcmd
[LIT_ATTEN_LINEAR
] == 0.0 ) ) {
1264 /* Disable attenuation */
1265 icmd
[idx
] &= ~atten_flag
;
1267 if ( fcmd
[LIT_ATTEN_QUADRATIC
] == 0.0 && fcmd
[LIT_ATTEN_LINEAR
] == 0.0 ) {
1268 /* Enable only constant portion of attenuation calculation */
1269 icmd
[idx
] |= ( atten_flag
| atten_const_flag
);
1271 /* Enable full attenuation calculation */
1272 icmd
[idx
] &= ~atten_const_flag
;
1273 icmd
[idx
] |= atten_flag
;
1277 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.tcl
);
1285 static void r200UpdateLocalViewer ( GLcontext
*ctx
)
1287 /* It looks like for the texgen modes GL_SPHERE_MAP, GL_NORMAL_MAP and
1288 GL_REFLECTION_MAP we need R200_LOCAL_VIEWER set (fglrx does exactly that
1289 for these and only these modes). This means specular highlights may turn out
1290 wrong in some cases when lighting is enabled but GL_LIGHT_MODEL_LOCAL_VIEWER
1291 is not set, though it seems to happen rarely and the effect seems quite
1292 subtle. May need TCL fallback to fix it completely, though I'm not sure
1293 how you'd identify the cases where the specular highlights indeed will
1294 be wrong. Don't know if fglrx does something special in that case.
1296 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1297 R200_STATECHANGE( rmesa
, tcl
);
1298 if (ctx
->Light
.Model
.LocalViewer
||
1299 ctx
->Texture
._GenFlags
& TEXGEN_NEED_NORMALS
)
1300 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LOCAL_VIEWER
;
1302 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LOCAL_VIEWER
;
1305 static void r200LightModelfv( GLcontext
*ctx
, GLenum pname
,
1306 const GLfloat
*param
)
1308 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1311 case GL_LIGHT_MODEL_AMBIENT
:
1312 update_global_ambient( ctx
);
1315 case GL_LIGHT_MODEL_LOCAL_VIEWER
:
1316 r200UpdateLocalViewer( ctx
);
1319 case GL_LIGHT_MODEL_TWO_SIDE
:
1320 R200_STATECHANGE( rmesa
, tcl
);
1321 if (ctx
->Light
.Model
.TwoSide
)
1322 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHT_TWOSIDE
;
1324 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~(R200_LIGHT_TWOSIDE
);
1325 if (rmesa
->radeon
.TclFallback
) {
1326 r200ChooseRenderState( ctx
);
1327 r200ChooseVertexState( ctx
);
1331 case GL_LIGHT_MODEL_COLOR_CONTROL
:
1332 r200UpdateSpecular(ctx
);
1340 static void r200ShadeModel( GLcontext
*ctx
, GLenum mode
)
1342 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1343 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
1345 s
&= ~(R200_DIFFUSE_SHADE_MASK
|
1346 R200_ALPHA_SHADE_MASK
|
1347 R200_SPECULAR_SHADE_MASK
|
1348 R200_FOG_SHADE_MASK
|
1349 R200_DISC_FOG_SHADE_MASK
);
1353 s
|= (R200_DIFFUSE_SHADE_FLAT
|
1354 R200_ALPHA_SHADE_FLAT
|
1355 R200_SPECULAR_SHADE_FLAT
|
1356 R200_FOG_SHADE_FLAT
|
1357 R200_DISC_FOG_SHADE_FLAT
);
1360 s
|= (R200_DIFFUSE_SHADE_GOURAUD
|
1361 R200_ALPHA_SHADE_GOURAUD
|
1362 R200_SPECULAR_SHADE_GOURAUD
|
1363 R200_FOG_SHADE_GOURAUD
|
1364 R200_DISC_FOG_SHADE_GOURAUD
);
1370 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
1371 R200_STATECHANGE( rmesa
, set
);
1372 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
1377 /* =============================================================
1381 static void r200ClipPlane( GLcontext
*ctx
, GLenum plane
, const GLfloat
*eq
)
1383 GLint p
= (GLint
) plane
- (GLint
) GL_CLIP_PLANE0
;
1384 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1385 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1387 R200_STATECHANGE( rmesa
, ucp
[p
] );
1388 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1389 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1390 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1391 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1394 static void r200UpdateClipPlanes( GLcontext
*ctx
)
1396 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1399 for (p
= 0; p
< ctx
->Const
.MaxClipPlanes
; p
++) {
1400 if (ctx
->Transform
.ClipPlanesEnabled
& (1 << p
)) {
1401 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1403 R200_STATECHANGE( rmesa
, ucp
[p
] );
1404 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1405 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1406 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1407 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1413 /* =============================================================
1418 r200StencilFuncSeparate( GLcontext
*ctx
, GLenum face
, GLenum func
,
1419 GLint ref
, GLuint mask
)
1421 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1422 GLuint refmask
= (((ctx
->Stencil
.Ref
[0] & 0xff) << R200_STENCIL_REF_SHIFT
) |
1423 ((ctx
->Stencil
.ValueMask
[0] & 0xff) << R200_STENCIL_MASK_SHIFT
));
1425 R200_STATECHANGE( rmesa
, ctx
);
1426 R200_STATECHANGE( rmesa
, msk
);
1428 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_STENCIL_TEST_MASK
;
1429 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~(R200_STENCIL_REF_MASK
|
1430 R200_STENCIL_VALUE_MASK
);
1432 switch ( ctx
->Stencil
.Function
[0] ) {
1434 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEVER
;
1437 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LESS
;
1440 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_EQUAL
;
1443 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LEQUAL
;
1446 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GREATER
;
1449 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEQUAL
;
1452 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GEQUAL
;
1455 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_ALWAYS
;
1459 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |= refmask
;
1463 r200StencilMaskSeparate( GLcontext
*ctx
, GLenum face
, GLuint mask
)
1465 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1467 R200_STATECHANGE( rmesa
, msk
);
1468 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~R200_STENCIL_WRITE_MASK
;
1469 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |=
1470 ((ctx
->Stencil
.WriteMask
[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT
);
1474 r200StencilOpSeparate( GLcontext
*ctx
, GLenum face
, GLenum fail
,
1475 GLenum zfail
, GLenum zpass
)
1477 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1479 R200_STATECHANGE( rmesa
, ctx
);
1480 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~(R200_STENCIL_FAIL_MASK
|
1481 R200_STENCIL_ZFAIL_MASK
|
1482 R200_STENCIL_ZPASS_MASK
);
1484 switch ( ctx
->Stencil
.FailFunc
[0] ) {
1486 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_KEEP
;
1489 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_ZERO
;
1492 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_REPLACE
;
1495 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC
;
1498 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC
;
1500 case GL_INCR_WRAP_EXT
:
1501 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC_WRAP
;
1503 case GL_DECR_WRAP_EXT
:
1504 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC_WRAP
;
1507 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INVERT
;
1511 switch ( ctx
->Stencil
.ZFailFunc
[0] ) {
1513 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_KEEP
;
1516 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_ZERO
;
1519 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_REPLACE
;
1522 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC
;
1525 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC
;
1527 case GL_INCR_WRAP_EXT
:
1528 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC_WRAP
;
1530 case GL_DECR_WRAP_EXT
:
1531 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC_WRAP
;
1534 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INVERT
;
1538 switch ( ctx
->Stencil
.ZPassFunc
[0] ) {
1540 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_KEEP
;
1543 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_ZERO
;
1546 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_REPLACE
;
1549 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC
;
1552 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC
;
1554 case GL_INCR_WRAP_EXT
:
1555 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC_WRAP
;
1557 case GL_DECR_WRAP_EXT
:
1558 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC_WRAP
;
1561 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INVERT
;
1566 static void r200ClearStencil( GLcontext
*ctx
, GLint s
)
1568 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1570 rmesa
->radeon
.state
.stencil
.clear
=
1571 ((GLuint
) (ctx
->Stencil
.Clear
& 0xff) |
1572 (0xff << R200_STENCIL_MASK_SHIFT
) |
1573 ((ctx
->Stencil
.WriteMask
[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT
));
1577 /* =============================================================
1578 * Window position and viewport transformation
1582 * Called when window size or position changes or viewport or depth range
1583 * state is changed. We update the hardware viewport state here.
1585 void r200UpdateWindow( GLcontext
*ctx
)
1587 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1588 __DRIdrawable
*dPriv
= radeon_get_drawable(&rmesa
->radeon
);
1589 GLfloat xoffset
= dPriv
? (GLfloat
) dPriv
->x
: 0;
1590 GLfloat yoffset
= dPriv
? (GLfloat
) dPriv
->y
+ dPriv
->h
: 0;
1591 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1592 const GLboolean render_to_fbo
= (ctx
->DrawBuffer
? (ctx
->DrawBuffer
->Name
!= 0) : 0);
1593 const GLfloat depthScale
= 1.0F
/ ctx
->DrawBuffer
->_DepthMaxF
;
1594 GLfloat y_scale
, y_bias
;
1596 if (render_to_fbo
) {
1604 float_ui32_type sx
= { v
[MAT_SX
] };
1605 float_ui32_type tx
= { v
[MAT_TX
] + xoffset
};
1606 float_ui32_type sy
= { v
[MAT_SY
] * y_scale
};
1607 float_ui32_type ty
= { (v
[MAT_TY
] * y_scale
) + y_bias
};
1608 float_ui32_type sz
= { v
[MAT_SZ
] * depthScale
};
1609 float_ui32_type tz
= { v
[MAT_TZ
] * depthScale
};
1611 R200_STATECHANGE( rmesa
, vpt
);
1613 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XSCALE
] = sx
.ui32
;
1614 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = tx
.ui32
;
1615 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YSCALE
] = sy
.ui32
;
1616 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = ty
.ui32
;
1617 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZSCALE
] = sz
.ui32
;
1618 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZOFFSET
] = tz
.ui32
;
1621 void r200_vtbl_update_scissor( GLcontext
*ctx
)
1623 r200ContextPtr r200
= R200_CONTEXT(ctx
);
1624 unsigned x1
, y1
, x2
, y2
;
1625 struct radeon_renderbuffer
*rrb
;
1627 R200_SET_STATE(r200
, set
, SET_RE_CNTL
, R200_SCISSOR_ENABLE
| r200
->hw
.set
.cmd
[SET_RE_CNTL
]);
1629 if (r200
->radeon
.state
.scissor
.enabled
) {
1630 x1
= r200
->radeon
.state
.scissor
.rect
.x1
;
1631 y1
= r200
->radeon
.state
.scissor
.rect
.y1
;
1632 x2
= r200
->radeon
.state
.scissor
.rect
.x2
;
1633 y2
= r200
->radeon
.state
.scissor
.rect
.y2
;
1635 rrb
= radeon_get_colorbuffer(&r200
->radeon
);
1638 x2
= rrb
->base
.Width
- 1;
1639 y2
= rrb
->base
.Height
- 1;
1642 R200_SET_STATE(r200
, sci
, SCI_XY_1
, x1
| (y1
<< 16));
1643 R200_SET_STATE(r200
, sci
, SCI_XY_2
, x2
| (y2
<< 16));
1647 static void r200Viewport( GLcontext
*ctx
, GLint x
, GLint y
,
1648 GLsizei width
, GLsizei height
)
1650 /* Don't pipeline viewport changes, conflict with window offset
1651 * setting below. Could apply deltas to rescue pipelined viewport
1652 * values, or keep the originals hanging around.
1654 r200UpdateWindow( ctx
);
1656 radeon_viewport(ctx
, x
, y
, width
, height
);
1659 static void r200DepthRange( GLcontext
*ctx
, GLclampd nearval
,
1662 r200UpdateWindow( ctx
);
1665 void r200UpdateViewportOffset( GLcontext
*ctx
)
1667 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1668 __DRIdrawable
*dPriv
= radeon_get_drawable(&rmesa
->radeon
);
1669 GLfloat xoffset
= (GLfloat
)dPriv
->x
;
1670 GLfloat yoffset
= (GLfloat
)dPriv
->y
+ dPriv
->h
;
1671 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1676 tx
.f
= v
[MAT_TX
] + xoffset
;
1677 ty
.f
= (- v
[MAT_TY
]) + yoffset
;
1679 if ( rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] != tx
.ui32
||
1680 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] != ty
.ui32
)
1682 /* Note: this should also modify whatever data the context reset
1685 R200_STATECHANGE( rmesa
, vpt
);
1686 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = tx
.ui32
;
1687 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = ty
.ui32
;
1689 /* update polygon stipple x/y screen offset */
1692 GLuint m
= rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
];
1694 m
&= ~(R200_STIPPLE_X_OFFSET_MASK
|
1695 R200_STIPPLE_Y_OFFSET_MASK
);
1697 /* add magic offsets, then invert */
1698 stx
= 31 - ((dPriv
->x
- 1) & R200_STIPPLE_COORD_MASK
);
1699 sty
= 31 - ((dPriv
->y
+ dPriv
->h
- 1)
1700 & R200_STIPPLE_COORD_MASK
);
1702 m
|= ((stx
<< R200_STIPPLE_X_OFFSET_SHIFT
) |
1703 (sty
<< R200_STIPPLE_Y_OFFSET_SHIFT
));
1705 if ( rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] != m
) {
1706 R200_STATECHANGE( rmesa
, msc
);
1707 rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] = m
;
1712 radeonUpdateScissor( ctx
);
1717 /* =============================================================
1721 static void r200ClearColor( GLcontext
*ctx
, const GLfloat c
[4] )
1723 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1725 struct radeon_renderbuffer
*rrb
;
1727 rrb
= radeon_get_colorbuffer(&rmesa
->radeon
);
1730 CLAMPED_FLOAT_TO_UBYTE(color
[0], c
[0]);
1731 CLAMPED_FLOAT_TO_UBYTE(color
[1], c
[1]);
1732 CLAMPED_FLOAT_TO_UBYTE(color
[2], c
[2]);
1733 CLAMPED_FLOAT_TO_UBYTE(color
[3], c
[3]);
1734 rmesa
->radeon
.state
.color
.clear
= radeonPackColor( rrb
->cpp
,
1736 color
[2], color
[3] );
1740 static void r200RenderMode( GLcontext
*ctx
, GLenum mode
)
1742 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1743 FALLBACK( rmesa
, R200_FALLBACK_RENDER_MODE
, (mode
!= GL_RENDER
) );
1747 static GLuint r200_rop_tab
[] = {
1750 R200_ROP_AND_REVERSE
,
1752 R200_ROP_AND_INVERTED
,
1759 R200_ROP_OR_REVERSE
,
1760 R200_ROP_COPY_INVERTED
,
1761 R200_ROP_OR_INVERTED
,
1766 static void r200LogicOpCode( GLcontext
*ctx
, GLenum opcode
)
1768 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1769 GLuint rop
= (GLuint
)opcode
- GL_CLEAR
;
1773 R200_STATECHANGE( rmesa
, msk
);
1774 rmesa
->hw
.msk
.cmd
[MSK_RB3D_ROPCNTL
] = r200_rop_tab
[rop
];
1777 /* =============================================================
1778 * State enable/disable
1781 static void r200Enable( GLcontext
*ctx
, GLenum cap
, GLboolean state
)
1783 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1786 if ( R200_DEBUG
& RADEON_STATE
)
1787 fprintf( stderr
, "%s( %s = %s )\n", __FUNCTION__
,
1788 _mesa_lookup_enum_by_nr( cap
),
1789 state
? "GL_TRUE" : "GL_FALSE" );
1792 /* Fast track this one...
1800 R200_STATECHANGE( rmesa
, ctx
);
1802 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ALPHA_TEST_ENABLE
;
1804 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ALPHA_TEST_ENABLE
;
1809 case GL_COLOR_LOGIC_OP
:
1810 r200_set_blend_state( ctx
);
1813 case GL_CLIP_PLANE0
:
1814 case GL_CLIP_PLANE1
:
1815 case GL_CLIP_PLANE2
:
1816 case GL_CLIP_PLANE3
:
1817 case GL_CLIP_PLANE4
:
1818 case GL_CLIP_PLANE5
:
1819 p
= cap
-GL_CLIP_PLANE0
;
1820 R200_STATECHANGE( rmesa
, tcl
);
1822 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= (R200_UCP_ENABLE_0
<<p
);
1823 r200ClipPlane( ctx
, cap
, NULL
);
1826 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~(R200_UCP_ENABLE_0
<<p
);
1830 case GL_COLOR_MATERIAL
:
1831 r200ColorMaterial( ctx
, 0, 0 );
1832 r200UpdateMaterial( ctx
);
1836 r200CullFace( ctx
, 0 );
1840 R200_STATECHANGE(rmesa
, ctx
);
1842 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_Z_ENABLE
;
1844 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_Z_ENABLE
;
1849 R200_STATECHANGE(rmesa
, ctx
);
1851 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_DITHER_ENABLE
;
1852 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~rmesa
->radeon
.state
.color
.roundEnable
;
1854 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_DITHER_ENABLE
;
1855 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= rmesa
->radeon
.state
.color
.roundEnable
;
1860 R200_STATECHANGE(rmesa
, ctx
);
1862 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_FOG_ENABLE
;
1863 r200Fogfv( ctx
, GL_FOG_MODE
, NULL
);
1865 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_FOG_ENABLE
;
1866 R200_STATECHANGE(rmesa
, tcl
);
1867 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_TCL_FOG_MASK
;
1869 r200UpdateSpecular( ctx
); /* for PK_SPEC */
1870 if (rmesa
->radeon
.TclFallback
)
1871 r200ChooseVertexState( ctx
);
1872 _mesa_allow_light_in_model( ctx
, !state
);
1883 R200_STATECHANGE(rmesa
, tcl
);
1884 p
= cap
- GL_LIGHT0
;
1886 flag
= (R200_LIGHT_1_ENABLE
|
1887 R200_LIGHT_1_ENABLE_AMBIENT
|
1888 R200_LIGHT_1_ENABLE_SPECULAR
);
1890 flag
= (R200_LIGHT_0_ENABLE
|
1891 R200_LIGHT_0_ENABLE_AMBIENT
|
1892 R200_LIGHT_0_ENABLE_SPECULAR
);
1895 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] |= flag
;
1897 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] &= ~flag
;
1901 update_light_colors( ctx
, p
);
1905 r200UpdateSpecular(ctx
);
1906 /* for reflection map fixup - might set recheck_texgen for all units too */
1907 rmesa
->radeon
.NewGLState
|= _NEW_TEXTURE
;
1910 case GL_LINE_SMOOTH
:
1911 R200_STATECHANGE( rmesa
, ctx
);
1913 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_LINE
;
1915 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_LINE
;
1919 case GL_LINE_STIPPLE
:
1920 R200_STATECHANGE( rmesa
, set
);
1922 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_PATTERN_ENABLE
;
1924 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_PATTERN_ENABLE
;
1929 R200_STATECHANGE( rmesa
, tcl
);
1931 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_NORMALIZE_NORMALS
;
1933 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_NORMALIZE_NORMALS
;
1937 /* Pointsize registers on r200 only work for point sprites, and point smooth
1938 * doesn't work for point sprites (and isn't needed for 1.0 sized aa points).
1939 * In any case, setting pointmin == pointsizemax == 1.0 for aa points
1940 * is enough to satisfy conform.
1942 case GL_POINT_SMOOTH
:
1945 /* These don't really do anything, as we don't use the 3vtx
1949 case GL_POLYGON_OFFSET_POINT
:
1950 R200_STATECHANGE( rmesa
, set
);
1952 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_POINT
;
1954 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_POINT
;
1958 case GL_POLYGON_OFFSET_LINE
:
1959 R200_STATECHANGE( rmesa
, set
);
1961 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_LINE
;
1963 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_LINE
;
1968 case GL_POINT_SPRITE_ARB
:
1969 R200_STATECHANGE( rmesa
, spr
);
1972 for (i
= 0; i
< 6; i
++) {
1973 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |=
1974 ctx
->Point
.CoordReplace
[i
] << (R200_PS_GEN_TEX_0_SHIFT
+ i
);
1977 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] &= ~R200_PS_GEN_TEX_MASK
;
1981 case GL_POLYGON_OFFSET_FILL
:
1982 R200_STATECHANGE( rmesa
, set
);
1984 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_TRI
;
1986 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_TRI
;
1990 case GL_POLYGON_SMOOTH
:
1991 R200_STATECHANGE( rmesa
, ctx
);
1993 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_POLY
;
1995 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_POLY
;
1999 case GL_POLYGON_STIPPLE
:
2000 R200_STATECHANGE(rmesa
, set
);
2002 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_STIPPLE_ENABLE
;
2004 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_STIPPLE_ENABLE
;
2008 case GL_RESCALE_NORMAL_EXT
: {
2009 GLboolean tmp
= ctx
->_NeedEyeCoords
? state
: !state
;
2010 R200_STATECHANGE( rmesa
, tcl
);
2012 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
2014 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
2019 case GL_SCISSOR_TEST
:
2020 radeon_firevertices(&rmesa
->radeon
);
2021 rmesa
->radeon
.state
.scissor
.enabled
= state
;
2022 radeonUpdateScissor( ctx
);
2025 case GL_STENCIL_TEST
:
2027 GLboolean hw_stencil
= GL_FALSE
;
2028 if (ctx
->DrawBuffer
) {
2029 struct radeon_renderbuffer
*rrbStencil
2030 = radeon_get_renderbuffer(ctx
->DrawBuffer
, BUFFER_STENCIL
);
2031 hw_stencil
= (rrbStencil
&& rrbStencil
->bo
);
2035 R200_STATECHANGE( rmesa
, ctx
);
2037 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_STENCIL_ENABLE
;
2039 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_STENCIL_ENABLE
;
2042 FALLBACK( rmesa
, R200_FALLBACK_STENCIL
, state
);
2047 case GL_TEXTURE_GEN_Q
:
2048 case GL_TEXTURE_GEN_R
:
2049 case GL_TEXTURE_GEN_S
:
2050 case GL_TEXTURE_GEN_T
:
2051 /* Picked up in r200UpdateTextureState.
2053 rmesa
->recheck_texgen
[ctx
->Texture
.CurrentUnit
] = GL_TRUE
;
2056 case GL_COLOR_SUM_EXT
:
2057 r200UpdateSpecular ( ctx
);
2060 case GL_VERTEX_PROGRAM_ARB
:
2063 rmesa
->curr_vp_hw
= NULL
;
2064 R200_STATECHANGE( rmesa
, vap
);
2065 rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
] &= ~R200_VAP_PROG_VTX_SHADER_ENABLE
;
2066 /* mark all tcl atoms (tcl vector state got overwritten) dirty
2067 not sure about tcl scalar state - we need at least grd
2068 with vert progs too.
2069 ucp looks like it doesn't get overwritten (may even work
2070 with vp for pos-invariant progs if we're lucky) */
2071 R200_STATECHANGE( rmesa
, mtl
[0] );
2072 R200_STATECHANGE( rmesa
, mtl
[1] );
2073 R200_STATECHANGE( rmesa
, fog
);
2074 R200_STATECHANGE( rmesa
, glt
);
2075 R200_STATECHANGE( rmesa
, eye
);
2076 for (i
= R200_MTX_MV
; i
<= R200_MTX_TEX5
; i
++) {
2077 R200_STATECHANGE( rmesa
, mat
[i
] );
2079 for (i
= 0 ; i
< 8; i
++) {
2080 R200_STATECHANGE( rmesa
, lit
[i
] );
2082 R200_STATECHANGE( rmesa
, tcl
);
2083 for (i
= 0; i
<= ctx
->Const
.MaxClipPlanes
; i
++) {
2084 if (ctx
->Transform
.ClipPlanesEnabled
& (1 << i
)) {
2085 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= (R200_UCP_ENABLE_0
<< i
);
2088 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0 << i);
2091 /* ugly. Need to call everything which might change compsel. */
2092 r200UpdateSpecular( ctx
);
2094 /* shouldn't be necessary, as it's picked up anyway in r200ValidateState (_NEW_PROGRAM),
2095 but without it doom3 locks up at always the same places. Why? */
2096 /* FIXME: This can (and should) be replaced by a call to the TCL_STATE_FLUSH reg before
2097 accessing VAP_SE_VAP_CNTL. Requires drm changes (done). Remove after some time... */
2098 r200UpdateTextureState( ctx
);
2099 /* if we call r200UpdateTextureState we need the code below because we are calling it with
2100 non-current derived enabled values which may revert the state atoms for frag progs even when
2101 they already got disabled... ugh
2102 Should really figure out why we need to call r200UpdateTextureState in the first place */
2104 for (unit
= 0; unit
< R200_MAX_TEXTURE_UNITS
; unit
++) {
2105 R200_STATECHANGE( rmesa
, pix
[unit
] );
2106 R200_STATECHANGE( rmesa
, tex
[unit
] );
2107 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] &=
2108 ~(R200_TXFORMAT_ST_ROUTE_MASK
| R200_TXFORMAT_LOOKUP_DISABLE
);
2109 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] |= unit
<< R200_TXFORMAT_ST_ROUTE_SHIFT
;
2110 /* need to guard this with drmSupportsFragmentShader? Should never get here if
2111 we don't announce ATI_fs, right? */
2112 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXMULTI_CTL
] = 0;
2114 R200_STATECHANGE( rmesa
, cst
);
2115 R200_STATECHANGE( rmesa
, tf
);
2116 rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] = 0;
2120 /* picked up later */
2122 /* call functions which change hw state based on ARB_vp enabled or not. */
2123 r200PointParameter( ctx
, GL_POINT_DISTANCE_ATTENUATION
, NULL
);
2124 r200Fogfv( ctx
, GL_FOG_COORD_SRC
, NULL
);
2127 case GL_VERTEX_PROGRAM_POINT_SIZE_ARB
:
2128 r200PointParameter( ctx
, GL_POINT_DISTANCE_ATTENUATION
, NULL
);
2131 case GL_FRAGMENT_SHADER_ATI
:
2133 /* restore normal tex env colors and make sure tex env combine will get updated
2134 mark env atoms dirty (as their data was overwritten by afs even
2135 if they didn't change) and restore tex coord routing */
2137 for (unit
= 0; unit
< R200_MAX_TEXTURE_UNITS
; unit
++) {
2138 R200_STATECHANGE( rmesa
, pix
[unit
] );
2139 R200_STATECHANGE( rmesa
, tex
[unit
] );
2140 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] &=
2141 ~(R200_TXFORMAT_ST_ROUTE_MASK
| R200_TXFORMAT_LOOKUP_DISABLE
);
2142 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] |= unit
<< R200_TXFORMAT_ST_ROUTE_SHIFT
;
2143 /* need to guard this with drmSupportsFragmentShader? Should never get here if
2144 we don't announce ATI_fs, right? */
2145 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXMULTI_CTL
] = 0;
2147 R200_STATECHANGE( rmesa
, cst
);
2148 R200_STATECHANGE( rmesa
, tf
);
2149 rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] = 0;
2152 /* need to mark this dirty as pix/tf atoms have overwritten the data
2153 even if the data in the atoms didn't change */
2154 R200_STATECHANGE( rmesa
, atf
);
2155 R200_STATECHANGE( rmesa
, afs
[1] );
2156 /* everything else picked up in r200UpdateTextureState hopefully */
2165 void r200LightingSpaceChange( GLcontext
*ctx
)
2167 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2170 if (R200_DEBUG
& RADEON_STATE
)
2171 fprintf(stderr
, "%s %d BEFORE %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
2172 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
2174 if (ctx
->_NeedEyeCoords
)
2175 tmp
= ctx
->Transform
.RescaleNormals
;
2177 tmp
= !ctx
->Transform
.RescaleNormals
;
2179 R200_STATECHANGE( rmesa
, tcl
);
2181 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
2183 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
2186 if (R200_DEBUG
& RADEON_STATE
)
2187 fprintf(stderr
, "%s %d AFTER %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
2188 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
2191 /* =============================================================
2192 * Deferred state management - matrices, textures, other?
2198 static void upload_matrix( r200ContextPtr rmesa
, GLfloat
*src
, int idx
)
2200 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
2204 for (i
= 0 ; i
< 4 ; i
++) {
2208 *dest
++ = src
[i
+12];
2211 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
2214 static void upload_matrix_t( r200ContextPtr rmesa
, const GLfloat
*src
, int idx
)
2216 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
2217 memcpy(dest
, src
, 16*sizeof(float));
2218 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
2222 static void update_texturematrix( GLcontext
*ctx
)
2224 r200ContextPtr rmesa
= R200_CONTEXT( ctx
);
2225 GLuint tpc
= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
];
2226 GLuint compsel
= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
];
2229 if (R200_DEBUG
& RADEON_STATE
)
2230 fprintf(stderr
, "%s before COMPSEL: %x\n", __FUNCTION__
,
2231 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]);
2233 rmesa
->TexMatEnabled
= 0;
2234 rmesa
->TexMatCompSel
= 0;
2236 for (unit
= 0 ; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
2237 if (!ctx
->Texture
.Unit
[unit
]._ReallyEnabled
)
2240 if (ctx
->TextureMatrixStack
[unit
].Top
->type
!= MATRIX_IDENTITY
) {
2241 rmesa
->TexMatEnabled
|= (R200_TEXGEN_TEXMAT_0_ENABLE
|
2242 R200_TEXMAT_0_ENABLE
) << unit
;
2244 rmesa
->TexMatCompSel
|= R200_OUTPUT_TEX_0
<< unit
;
2246 if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2247 /* Need to preconcatenate any active texgen
2248 * obj/eyeplane matrices:
2250 _math_matrix_mul_matrix( &rmesa
->tmpmat
,
2251 ctx
->TextureMatrixStack
[unit
].Top
,
2252 &rmesa
->TexGenMatrix
[unit
] );
2253 upload_matrix( rmesa
, rmesa
->tmpmat
.m
, R200_MTX_TEX0
+unit
);
2256 upload_matrix( rmesa
, ctx
->TextureMatrixStack
[unit
].Top
->m
,
2257 R200_MTX_TEX0
+unit
);
2260 else if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2261 upload_matrix( rmesa
, rmesa
->TexGenMatrix
[unit
].m
,
2262 R200_MTX_TEX0
+unit
);
2266 tpc
= (rmesa
->TexMatEnabled
| rmesa
->TexGenEnabled
);
2267 if (tpc
!= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
]) {
2268 R200_STATECHANGE(rmesa
, tcg
);
2269 rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
] = tpc
;
2272 compsel
&= ~R200_OUTPUT_TEX_MASK
;
2273 compsel
|= rmesa
->TexMatCompSel
| rmesa
->TexGenCompSel
;
2274 if (compsel
!= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]) {
2275 R200_STATECHANGE(rmesa
, vtx
);
2276 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] = compsel
;
2280 static GLboolean
r200ValidateBuffers(GLcontext
*ctx
)
2282 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2283 struct radeon_renderbuffer
*rrb
;
2284 struct radeon_dma_bo
*dma_bo
;
2287 if (RADEON_DEBUG
& RADEON_IOCTL
)
2288 fprintf(stderr
, "%s\n", __FUNCTION__
);
2289 radeon_cs_space_reset_bos(rmesa
->radeon
.cmdbuf
.cs
);
2291 rrb
= radeon_get_colorbuffer(&rmesa
->radeon
);
2293 if (rrb
&& rrb
->bo
) {
2294 radeon_cs_space_add_persistent_bo(rmesa
->radeon
.cmdbuf
.cs
, rrb
->bo
,
2295 0, RADEON_GEM_DOMAIN_VRAM
);
2299 rrb
= radeon_get_depthbuffer(&rmesa
->radeon
);
2301 if (rrb
&& rrb
->bo
) {
2302 radeon_cs_space_add_persistent_bo(rmesa
->radeon
.cmdbuf
.cs
, rrb
->bo
,
2303 0, RADEON_GEM_DOMAIN_VRAM
);
2306 for (i
= 0; i
< ctx
->Const
.MaxTextureImageUnits
; ++i
) {
2309 if (!ctx
->Texture
.Unit
[i
]._ReallyEnabled
)
2312 t
= radeon_tex_obj(ctx
->Texture
.Unit
[i
]._Current
);
2313 if (t
->image_override
&& t
->bo
)
2314 radeon_cs_space_add_persistent_bo(rmesa
->radeon
.cmdbuf
.cs
, t
->bo
,
2315 RADEON_GEM_DOMAIN_GTT
| RADEON_GEM_DOMAIN_VRAM
, 0);
2317 radeon_cs_space_add_persistent_bo(rmesa
->radeon
.cmdbuf
.cs
, t
->mt
->bo
,
2318 RADEON_GEM_DOMAIN_GTT
| RADEON_GEM_DOMAIN_VRAM
, 0);
2321 dma_bo
= first_elem(&rmesa
->radeon
.dma
.reserved
);
2323 ret
= radeon_cs_space_check_with_bo(rmesa
->radeon
.cmdbuf
.cs
, dma_bo
->bo
, RADEON_GEM_DOMAIN_GTT
, 0);
2330 GLboolean
r200ValidateState( GLcontext
*ctx
)
2332 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2333 GLuint new_state
= rmesa
->radeon
.NewGLState
;
2335 if (new_state
& _NEW_BUFFERS
) {
2336 _mesa_update_framebuffer(ctx
);
2337 /* this updates the DrawBuffer's Width/Height if it's a FBO */
2338 _mesa_update_draw_buffer_bounds(ctx
);
2340 R200_STATECHANGE(rmesa
, ctx
);
2343 if (new_state
& (_NEW_TEXTURE
| _NEW_PROGRAM
| _NEW_PROGRAM_CONSTANTS
)) {
2344 r200UpdateTextureState( ctx
);
2345 new_state
|= rmesa
->radeon
.NewGLState
; /* may add TEXTURE_MATRIX */
2346 r200UpdateLocalViewer( ctx
);
2349 /* we need to do a space check here */
2350 if (!r200ValidateBuffers(ctx
))
2353 /* FIXME: don't really need most of these when vertex progs are enabled */
2355 /* Need an event driven matrix update?
2357 if (new_state
& (_NEW_MODELVIEW
|_NEW_PROJECTION
))
2358 upload_matrix( rmesa
, ctx
->_ModelProjectMatrix
.m
, R200_MTX_MVP
);
2360 /* Need these for lighting (shouldn't upload otherwise)
2362 if (new_state
& (_NEW_MODELVIEW
)) {
2363 upload_matrix( rmesa
, ctx
->ModelviewMatrixStack
.Top
->m
, R200_MTX_MV
);
2364 upload_matrix_t( rmesa
, ctx
->ModelviewMatrixStack
.Top
->inv
, R200_MTX_IMV
);
2367 /* Does this need to be triggered on eg. modelview for
2368 * texgen-derived objplane/eyeplane matrices?
2370 if (new_state
& (_NEW_TEXTURE
|_NEW_TEXTURE_MATRIX
)) {
2371 update_texturematrix( ctx
);
2374 if (new_state
& (_NEW_LIGHT
|_NEW_MODELVIEW
|_MESA_NEW_NEED_EYE_COORDS
)) {
2375 update_light( ctx
);
2378 /* emit all active clip planes if projection matrix changes.
2380 if (new_state
& (_NEW_PROJECTION
)) {
2381 if (ctx
->Transform
.ClipPlanesEnabled
)
2382 r200UpdateClipPlanes( ctx
);
2385 if (new_state
& (_NEW_PROGRAM
|
2386 _NEW_PROGRAM_CONSTANTS
|
2387 /* need to test for pretty much anything due to possible parameter bindings */
2388 _NEW_MODELVIEW
|_NEW_PROJECTION
|_NEW_TRANSFORM
|
2389 _NEW_LIGHT
|_NEW_TEXTURE
|_NEW_TEXTURE_MATRIX
|
2390 _NEW_FOG
|_NEW_POINT
|_NEW_TRACK_MATRIX
)) {
2391 if (ctx
->VertexProgram
._Enabled
) {
2392 r200SetupVertexProg( ctx
);
2394 else TCL_FALLBACK(ctx
, R200_TCL_FALLBACK_VERTEX_PROGRAM
, 0);
2397 rmesa
->radeon
.NewGLState
= 0;
2402 static void r200InvalidateState( GLcontext
*ctx
, GLuint new_state
)
2404 _swrast_InvalidateState( ctx
, new_state
);
2405 _swsetup_InvalidateState( ctx
, new_state
);
2406 _vbo_InvalidateState( ctx
, new_state
);
2407 _tnl_InvalidateState( ctx
, new_state
);
2408 _ae_invalidate_state( ctx
, new_state
);
2409 R200_CONTEXT(ctx
)->radeon
.NewGLState
|= new_state
;
2412 /* A hack. The r200 can actually cope just fine with materials
2413 * between begin/ends, so fix this.
2414 * Should map to inputs just like the generic vertex arrays for vertex progs.
2415 * In theory there could still be too many and we'd still need a fallback.
2417 static GLboolean
check_material( GLcontext
*ctx
)
2419 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
2422 for (i
= _TNL_ATTRIB_MAT_FRONT_AMBIENT
;
2423 i
< _TNL_ATTRIB_MAT_BACK_INDEXES
;
2425 if (tnl
->vb
.AttribPtr
[i
] &&
2426 tnl
->vb
.AttribPtr
[i
]->stride
)
2432 static void r200WrapRunPipeline( GLcontext
*ctx
)
2434 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2435 GLboolean has_material
;
2438 fprintf(stderr
, "%s, newstate: %x\n", __FUNCTION__
, rmesa
->radeon
.NewGLState
);
2442 if (rmesa
->radeon
.NewGLState
)
2443 if (!r200ValidateState( ctx
))
2444 FALLBACK(rmesa
, RADEON_FALLBACK_TEXTURE
, GL_TRUE
);
2446 has_material
= !ctx
->VertexProgram
._Enabled
&& ctx
->Light
.Enabled
&& check_material( ctx
);
2449 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_TRUE
);
2452 /* Run the pipeline.
2454 _tnl_run_pipeline( ctx
);
2457 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_FALSE
);
2462 static void r200PolygonStipple( GLcontext
*ctx
, const GLubyte
*mask
)
2464 r200ContextPtr r200
= R200_CONTEXT(ctx
);
2467 radeon_firevertices(&r200
->radeon
);
2469 R200_STATECHANGE(r200
, stp
);
2471 /* Must flip pattern upside down.
2473 for ( i
= 31 ; i
>= 0; i
--) {
2474 r200
->hw
.stp
.cmd
[3 + i
] = ((GLuint
*) mask
)[i
];
2477 /* Initialize the driver's state functions.
2479 void r200InitStateFuncs( struct dd_function_table
*functions
)
2481 functions
->UpdateState
= r200InvalidateState
;
2482 functions
->LightingSpaceChange
= r200LightingSpaceChange
;
2484 functions
->DrawBuffer
= radeonDrawBuffer
;
2485 functions
->ReadBuffer
= radeonReadBuffer
;
2487 functions
->AlphaFunc
= r200AlphaFunc
;
2488 functions
->BlendColor
= r200BlendColor
;
2489 functions
->BlendEquationSeparate
= r200BlendEquationSeparate
;
2490 functions
->BlendFuncSeparate
= r200BlendFuncSeparate
;
2491 functions
->ClearColor
= r200ClearColor
;
2492 functions
->ClearDepth
= r200ClearDepth
;
2493 functions
->ClearIndex
= NULL
;
2494 functions
->ClearStencil
= r200ClearStencil
;
2495 functions
->ClipPlane
= r200ClipPlane
;
2496 functions
->ColorMask
= r200ColorMask
;
2497 functions
->CullFace
= r200CullFace
;
2498 functions
->DepthFunc
= r200DepthFunc
;
2499 functions
->DepthMask
= r200DepthMask
;
2500 functions
->DepthRange
= r200DepthRange
;
2501 functions
->Enable
= r200Enable
;
2502 functions
->Fogfv
= r200Fogfv
;
2503 functions
->FrontFace
= r200FrontFace
;
2504 functions
->Hint
= NULL
;
2505 functions
->IndexMask
= NULL
;
2506 functions
->LightModelfv
= r200LightModelfv
;
2507 functions
->Lightfv
= r200Lightfv
;
2508 functions
->LineStipple
= r200LineStipple
;
2509 functions
->LineWidth
= r200LineWidth
;
2510 functions
->LogicOpcode
= r200LogicOpCode
;
2511 functions
->PolygonMode
= r200PolygonMode
;
2512 functions
->PolygonOffset
= r200PolygonOffset
;
2513 functions
->PolygonStipple
= r200PolygonStipple
;
2514 functions
->PointParameterfv
= r200PointParameter
;
2515 functions
->PointSize
= r200PointSize
;
2516 functions
->RenderMode
= r200RenderMode
;
2517 functions
->Scissor
= radeonScissor
;
2518 functions
->ShadeModel
= r200ShadeModel
;
2519 functions
->StencilFuncSeparate
= r200StencilFuncSeparate
;
2520 functions
->StencilMaskSeparate
= r200StencilMaskSeparate
;
2521 functions
->StencilOpSeparate
= r200StencilOpSeparate
;
2522 functions
->Viewport
= r200Viewport
;
2526 void r200InitTnlFuncs( GLcontext
*ctx
)
2528 TNL_CONTEXT(ctx
)->Driver
.NotifyMaterialChange
= r200UpdateMaterial
;
2529 TNL_CONTEXT(ctx
)->Driver
.RunPipeline
= r200WrapRunPipeline
;