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
;
579 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_FFACE_CULL_CW
;
582 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_FFACE_CULL_CCW
;
583 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_CULL_FRONT_IS_CCW
;
588 /* =============================================================
591 static void r200PointSize( GLcontext
*ctx
, GLfloat size
)
593 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
594 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.ptp
.cmd
;
596 R200_STATECHANGE( rmesa
, cst
);
597 R200_STATECHANGE( rmesa
, ptp
);
598 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] &= ~0xffff;
599 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] |= ((GLuint
)(ctx
->Point
.Size
* 16.0));
600 /* this is the size param of the point size calculation (point size reg value
601 is not used when calculation is active). */
602 fcmd
[PTP_VPORT_SCALE_PTSIZE
] = ctx
->Point
.Size
;
605 static void r200PointParameter( GLcontext
*ctx
, GLenum pname
, const GLfloat
*params
)
607 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
608 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.ptp
.cmd
;
611 case GL_POINT_SIZE_MIN
:
612 /* Can clamp both in tcl and setup - just set both (as does fglrx) */
613 R200_STATECHANGE( rmesa
, lin
);
614 R200_STATECHANGE( rmesa
, ptp
);
615 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] &= 0xffff;
616 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] |= (GLuint
)(ctx
->Point
.MinSize
* 16.0) << 16;
617 fcmd
[PTP_CLAMP_MIN
] = ctx
->Point
.MinSize
;
619 case GL_POINT_SIZE_MAX
:
620 R200_STATECHANGE( rmesa
, cst
);
621 R200_STATECHANGE( rmesa
, ptp
);
622 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] &= 0xffff;
623 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] |= (GLuint
)(ctx
->Point
.MaxSize
* 16.0) << 16;
624 fcmd
[PTP_CLAMP_MAX
] = ctx
->Point
.MaxSize
;
626 case GL_POINT_DISTANCE_ATTENUATION
:
627 R200_STATECHANGE( rmesa
, vtx
);
628 R200_STATECHANGE( rmesa
, spr
);
629 R200_STATECHANGE( rmesa
, ptp
);
630 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.ptp
.cmd
;
631 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] &=
632 ~(R200_PS_MULT_MASK
| R200_PS_LIN_ATT_ZERO
| R200_PS_SE_SEL_STATE
);
633 /* can't rely on ctx->Point._Attenuated here and test for NEW_POINT in
634 r200ValidateState looks like overkill */
635 if (ctx
->Point
.Params
[0] != 1.0 ||
636 ctx
->Point
.Params
[1] != 0.0 ||
637 ctx
->Point
.Params
[2] != 0.0 ||
638 (ctx
->VertexProgram
.Enabled
&& ctx
->VertexProgram
.PointSizeEnabled
)) {
639 /* all we care for vp would be the ps_se_sel_state setting */
640 fcmd
[PTP_ATT_CONST_QUAD
] = ctx
->Point
.Params
[2];
641 fcmd
[PTP_ATT_CONST_LIN
] = ctx
->Point
.Params
[1];
642 fcmd
[PTP_ATT_CONST_CON
] = ctx
->Point
.Params
[0];
643 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |= R200_PS_MULT_ATTENCONST
;
644 if (ctx
->Point
.Params
[1] == 0.0)
645 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |= R200_PS_LIN_ATT_ZERO
;
646 /* FIXME: setting this here doesn't look quite ok - we only want to do
647 that if we're actually drawing points probably */
648 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_PT_SIZE
;
649 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |= R200_VTX_POINT_SIZE
;
652 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |=
653 R200_PS_SE_SEL_STATE
| R200_PS_MULT_CONST
;
654 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_PT_SIZE
;
655 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~R200_VTX_POINT_SIZE
;
658 case GL_POINT_FADE_THRESHOLD_SIZE
:
659 /* don't support multisampling, so doesn't matter. */
661 /* can't do these but don't need them.
662 case GL_POINT_SPRITE_R_MODE_NV:
663 case GL_POINT_SPRITE_COORD_ORIGIN: */
665 fprintf(stderr
, "bad pname parameter in r200PointParameter\n");
670 /* =============================================================
673 static void r200LineWidth( GLcontext
*ctx
, GLfloat widthf
)
675 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
677 R200_STATECHANGE( rmesa
, lin
);
678 R200_STATECHANGE( rmesa
, set
);
680 /* Line width is stored in U6.4 format.
681 * Same min/max limits for AA, non-AA lines.
683 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] &= ~0xffff;
684 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] |= (GLuint
)
685 (CLAMP(widthf
, ctx
->Const
.MinLineWidth
, ctx
->Const
.MaxLineWidth
) * 16.0);
687 if ( widthf
> 1.0 ) {
688 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_WIDELINE_ENABLE
;
690 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_WIDELINE_ENABLE
;
694 static void r200LineStipple( GLcontext
*ctx
, GLint factor
, GLushort pattern
)
696 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
698 R200_STATECHANGE( rmesa
, lin
);
699 rmesa
->hw
.lin
.cmd
[LIN_RE_LINE_PATTERN
] =
700 ((((GLuint
)factor
& 0xff) << 16) | ((GLuint
)pattern
));
704 /* =============================================================
707 static void r200ColorMask( GLcontext
*ctx
,
708 GLboolean r
, GLboolean g
,
709 GLboolean b
, GLboolean a
)
711 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
712 GLuint mask
= radeonPackColor( rmesa
->radeon
.radeonScreen
->cpp
,
713 ctx
->Color
.ColorMask
[RCOMP
],
714 ctx
->Color
.ColorMask
[GCOMP
],
715 ctx
->Color
.ColorMask
[BCOMP
],
716 ctx
->Color
.ColorMask
[ACOMP
] );
718 GLuint flag
= rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] & ~R200_PLANE_MASK_ENABLE
;
720 if (!(r
&& g
&& b
&& a
))
721 flag
|= R200_PLANE_MASK_ENABLE
;
723 if ( rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] != flag
) {
724 R200_STATECHANGE( rmesa
, ctx
);
725 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = flag
;
728 if ( rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
] != mask
) {
729 R200_STATECHANGE( rmesa
, msk
);
730 rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
] = mask
;
735 /* =============================================================
739 static void r200PolygonOffset( GLcontext
*ctx
,
740 GLfloat factor
, GLfloat units
)
742 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
743 const GLfloat depthScale
= 1.0F
/ ctx
->DrawBuffer
->_DepthMaxF
;
744 float_ui32_type constant
= { units
* depthScale
};
745 float_ui32_type factoru
= { factor
};
750 /* fprintf(stderr, "%s f:%f u:%f\n", __FUNCTION__, factor, constant); */
752 R200_STATECHANGE( rmesa
, zbs
);
753 rmesa
->hw
.zbs
.cmd
[ZBS_SE_ZBIAS_FACTOR
] = factoru
.ui32
;
754 rmesa
->hw
.zbs
.cmd
[ZBS_SE_ZBIAS_CONSTANT
] = constant
.ui32
;
757 static void r200PolygonStipple( GLcontext
*ctx
, const GLubyte
*mask
)
759 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
761 drm_radeon_stipple_t stipple
;
763 /* Must flip pattern upside down.
765 for ( i
= 0 ; i
< 32 ; i
++ ) {
766 rmesa
->state
.stipple
.mask
[31 - i
] = ((GLuint
*) mask
)[i
];
769 /* TODO: push this into cmd mechanism
771 radeon_firevertices(&rmesa
->radeon
);
772 LOCK_HARDWARE( &rmesa
->radeon
);
774 /* FIXME: Use window x,y offsets into stipple RAM.
776 stipple
.mask
= rmesa
->state
.stipple
.mask
;
777 drmCommandWrite( rmesa
->radeon
.dri
.fd
, DRM_RADEON_STIPPLE
,
778 &stipple
, sizeof(stipple
) );
779 UNLOCK_HARDWARE( &rmesa
->radeon
);
782 static void r200PolygonMode( GLcontext
*ctx
, GLenum face
, GLenum mode
)
784 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
785 GLboolean flag
= (ctx
->_TriangleCaps
& DD_TRI_UNFILLED
) != 0;
787 /* Can't generally do unfilled via tcl, but some good special
790 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_UNFILLED
, flag
);
791 if (rmesa
->radeon
.TclFallback
) {
792 r200ChooseRenderState( ctx
);
793 r200ChooseVertexState( ctx
);
798 /* =============================================================
799 * Rendering attributes
801 * We really don't want to recalculate all this every time we bind a
802 * texture. These things shouldn't change all that often, so it makes
803 * sense to break them out of the core texture state update routines.
806 /* Examine lighting and texture state to determine if separate specular
809 static void r200UpdateSpecular( GLcontext
*ctx
)
811 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
812 uint32_t p
= rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
];
814 R200_STATECHANGE( rmesa
, tcl
);
815 R200_STATECHANGE( rmesa
, vtx
);
817 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~(3<<R200_VTX_COLOR_0_SHIFT
);
818 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~(3<<R200_VTX_COLOR_1_SHIFT
);
819 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_COLOR_0
;
820 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_COLOR_1
;
821 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LIGHTING_ENABLE
;
823 p
&= ~R200_SPECULAR_ENABLE
;
825 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_DIFFUSE_SPECULAR_COMBINE
;
828 if (ctx
->Light
.Enabled
&&
829 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
) {
830 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
831 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
) |
832 (R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
833 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_0
;
834 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_1
;
835 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHTING_ENABLE
;
836 p
|= R200_SPECULAR_ENABLE
;
837 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &=
838 ~R200_DIFFUSE_SPECULAR_COMBINE
;
840 else if (ctx
->Light
.Enabled
) {
841 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
842 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
));
843 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_0
;
844 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHTING_ENABLE
;
845 } else if (ctx
->Fog
.ColorSumEnabled
) {
846 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
847 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
) |
848 (R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
849 p
|= R200_SPECULAR_ENABLE
;
851 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
852 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
));
855 if (ctx
->Fog
.Enabled
) {
856 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
857 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
858 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_1
;
861 if ( rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] != p
) {
862 R200_STATECHANGE( rmesa
, ctx
);
863 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] = p
;
866 /* Update vertex/render formats
868 if (rmesa
->radeon
.TclFallback
) {
869 r200ChooseRenderState( ctx
);
870 r200ChooseVertexState( ctx
);
875 /* =============================================================
880 /* Update on colormaterial, material emmissive/ambient,
881 * lightmodel.globalambient
883 static void update_global_ambient( GLcontext
*ctx
)
885 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
886 float *fcmd
= (float *)R200_DB_STATE( glt
);
888 /* Need to do more if both emmissive & ambient are PREMULT:
889 * I believe this is not nessary when using source_material. This condition thus
890 * will never happen currently, and the function has no dependencies on materials now
892 if ((rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
] &
893 ((3 << R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
894 (3 << R200_FRONT_AMBIENT_SOURCE_SHIFT
))) == 0)
896 COPY_3V( &fcmd
[GLT_RED
],
897 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_EMISSION
]);
898 ACC_SCALE_3V( &fcmd
[GLT_RED
],
899 ctx
->Light
.Model
.Ambient
,
900 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_AMBIENT
]);
904 COPY_3V( &fcmd
[GLT_RED
], ctx
->Light
.Model
.Ambient
);
907 R200_DB_STATECHANGE(rmesa
, &rmesa
->hw
.glt
);
910 /* Update on change to
914 static void update_light_colors( GLcontext
*ctx
, GLuint p
)
916 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
918 /* fprintf(stderr, "%s\n", __FUNCTION__); */
921 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
922 float *fcmd
= (float *)R200_DB_STATE( lit
[p
] );
924 COPY_4V( &fcmd
[LIT_AMBIENT_RED
], l
->Ambient
);
925 COPY_4V( &fcmd
[LIT_DIFFUSE_RED
], l
->Diffuse
);
926 COPY_4V( &fcmd
[LIT_SPECULAR_RED
], l
->Specular
);
928 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
932 static void r200ColorMaterial( GLcontext
*ctx
, GLenum face
, GLenum mode
)
934 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
935 GLuint light_model_ctl1
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
];
936 light_model_ctl1
&= ~((0xf << R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
937 (0xf << R200_FRONT_AMBIENT_SOURCE_SHIFT
) |
938 (0xf << R200_FRONT_DIFFUSE_SOURCE_SHIFT
) |
939 (0xf << R200_FRONT_SPECULAR_SOURCE_SHIFT
) |
940 (0xf << R200_BACK_EMISSIVE_SOURCE_SHIFT
) |
941 (0xf << R200_BACK_AMBIENT_SOURCE_SHIFT
) |
942 (0xf << R200_BACK_DIFFUSE_SOURCE_SHIFT
) |
943 (0xf << R200_BACK_SPECULAR_SOURCE_SHIFT
));
945 if (ctx
->Light
.ColorMaterialEnabled
) {
946 GLuint mask
= ctx
->Light
.ColorMaterialBitmask
;
948 if (mask
& MAT_BIT_FRONT_EMISSION
) {
949 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
950 R200_FRONT_EMISSIVE_SOURCE_SHIFT
);
953 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
954 R200_FRONT_EMISSIVE_SOURCE_SHIFT
);
956 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
957 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
958 R200_FRONT_AMBIENT_SOURCE_SHIFT
);
961 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
962 R200_FRONT_AMBIENT_SOURCE_SHIFT
);
964 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
965 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
966 R200_FRONT_DIFFUSE_SOURCE_SHIFT
);
969 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
970 R200_FRONT_DIFFUSE_SOURCE_SHIFT
);
972 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
973 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
974 R200_FRONT_SPECULAR_SOURCE_SHIFT
);
977 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
978 R200_FRONT_SPECULAR_SOURCE_SHIFT
);
981 if (mask
& MAT_BIT_BACK_EMISSION
) {
982 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
983 R200_BACK_EMISSIVE_SOURCE_SHIFT
);
986 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
987 R200_BACK_EMISSIVE_SOURCE_SHIFT
);
989 if (mask
& MAT_BIT_BACK_AMBIENT
) {
990 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
991 R200_BACK_AMBIENT_SOURCE_SHIFT
);
993 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
994 R200_BACK_AMBIENT_SOURCE_SHIFT
);
996 if (mask
& MAT_BIT_BACK_DIFFUSE
) {
997 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
998 R200_BACK_DIFFUSE_SOURCE_SHIFT
);
1000 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
1001 R200_BACK_DIFFUSE_SOURCE_SHIFT
);
1003 if (mask
& MAT_BIT_BACK_SPECULAR
) {
1004 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
1005 R200_BACK_SPECULAR_SOURCE_SHIFT
);
1008 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
1009 R200_BACK_SPECULAR_SOURCE_SHIFT
);
1013 /* Default to SOURCE_MATERIAL:
1016 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
1017 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_AMBIENT_SOURCE_SHIFT
) |
1018 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_DIFFUSE_SOURCE_SHIFT
) |
1019 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_SPECULAR_SOURCE_SHIFT
) |
1020 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_EMISSIVE_SOURCE_SHIFT
) |
1021 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_AMBIENT_SOURCE_SHIFT
) |
1022 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_DIFFUSE_SOURCE_SHIFT
) |
1023 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_SPECULAR_SOURCE_SHIFT
);
1026 if (light_model_ctl1
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
]) {
1027 R200_STATECHANGE( rmesa
, tcl
);
1028 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
] = light_model_ctl1
;
1034 void r200UpdateMaterial( GLcontext
*ctx
)
1036 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1037 GLfloat (*mat
)[4] = ctx
->Light
.Material
.Attrib
;
1038 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( mtl
[0] );
1039 GLfloat
*fcmd2
= (GLfloat
*)R200_DB_STATE( mtl
[1] );
1042 /* Might be possible and faster to update everything unconditionally? */
1043 if (ctx
->Light
.ColorMaterialEnabled
)
1044 mask
&= ~ctx
->Light
.ColorMaterialBitmask
;
1046 if (R200_DEBUG
& DEBUG_STATE
)
1047 fprintf(stderr
, "%s\n", __FUNCTION__
);
1049 if (mask
& MAT_BIT_FRONT_EMISSION
) {
1050 fcmd
[MTL_EMMISSIVE_RED
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][0];
1051 fcmd
[MTL_EMMISSIVE_GREEN
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][1];
1052 fcmd
[MTL_EMMISSIVE_BLUE
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][2];
1053 fcmd
[MTL_EMMISSIVE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][3];
1055 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
1056 fcmd
[MTL_AMBIENT_RED
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][0];
1057 fcmd
[MTL_AMBIENT_GREEN
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][1];
1058 fcmd
[MTL_AMBIENT_BLUE
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][2];
1059 fcmd
[MTL_AMBIENT_ALPHA
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][3];
1061 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
1062 fcmd
[MTL_DIFFUSE_RED
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][0];
1063 fcmd
[MTL_DIFFUSE_GREEN
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][1];
1064 fcmd
[MTL_DIFFUSE_BLUE
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][2];
1065 fcmd
[MTL_DIFFUSE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][3];
1067 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
1068 fcmd
[MTL_SPECULAR_RED
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][0];
1069 fcmd
[MTL_SPECULAR_GREEN
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][1];
1070 fcmd
[MTL_SPECULAR_BLUE
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][2];
1071 fcmd
[MTL_SPECULAR_ALPHA
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][3];
1073 if (mask
& MAT_BIT_FRONT_SHININESS
) {
1074 fcmd
[MTL_SHININESS
] = mat
[MAT_ATTRIB_FRONT_SHININESS
][0];
1077 if (mask
& MAT_BIT_BACK_EMISSION
) {
1078 fcmd2
[MTL_EMMISSIVE_RED
] = mat
[MAT_ATTRIB_BACK_EMISSION
][0];
1079 fcmd2
[MTL_EMMISSIVE_GREEN
] = mat
[MAT_ATTRIB_BACK_EMISSION
][1];
1080 fcmd2
[MTL_EMMISSIVE_BLUE
] = mat
[MAT_ATTRIB_BACK_EMISSION
][2];
1081 fcmd2
[MTL_EMMISSIVE_ALPHA
] = mat
[MAT_ATTRIB_BACK_EMISSION
][3];
1083 if (mask
& MAT_BIT_BACK_AMBIENT
) {
1084 fcmd2
[MTL_AMBIENT_RED
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][0];
1085 fcmd2
[MTL_AMBIENT_GREEN
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][1];
1086 fcmd2
[MTL_AMBIENT_BLUE
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][2];
1087 fcmd2
[MTL_AMBIENT_ALPHA
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][3];
1089 if (mask
& MAT_BIT_BACK_DIFFUSE
) {
1090 fcmd2
[MTL_DIFFUSE_RED
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][0];
1091 fcmd2
[MTL_DIFFUSE_GREEN
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][1];
1092 fcmd2
[MTL_DIFFUSE_BLUE
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][2];
1093 fcmd2
[MTL_DIFFUSE_ALPHA
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][3];
1095 if (mask
& MAT_BIT_BACK_SPECULAR
) {
1096 fcmd2
[MTL_SPECULAR_RED
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][0];
1097 fcmd2
[MTL_SPECULAR_GREEN
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][1];
1098 fcmd2
[MTL_SPECULAR_BLUE
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][2];
1099 fcmd2
[MTL_SPECULAR_ALPHA
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][3];
1101 if (mask
& MAT_BIT_BACK_SHININESS
) {
1102 fcmd2
[MTL_SHININESS
] = mat
[MAT_ATTRIB_BACK_SHININESS
][0];
1105 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mtl
[0] );
1106 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mtl
[1] );
1108 /* currently material changes cannot trigger a global ambient change, I believe this is correct
1109 update_global_ambient( ctx ); */
1114 * _MESA_NEW_NEED_EYE_COORDS
1116 * Uses derived state from mesa:
1121 * _ModelViewInvScale
1125 * which are calculated in light.c and are correct for the current
1126 * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
1127 * and _MESA_NEW_NEED_EYE_COORDS.
1129 static void update_light( GLcontext
*ctx
)
1131 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1133 /* Have to check these, or have an automatic shortcircuit mechanism
1134 * to remove noop statechanges. (Or just do a better job on the
1138 GLuint tmp
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
];
1140 if (ctx
->_NeedEyeCoords
)
1141 tmp
&= ~R200_LIGHT_IN_MODELSPACE
;
1143 tmp
|= R200_LIGHT_IN_MODELSPACE
;
1145 if (tmp
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
])
1147 R200_STATECHANGE( rmesa
, tcl
);
1148 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] = tmp
;
1153 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( eye
);
1154 fcmd
[EYE_X
] = ctx
->_EyeZDir
[0];
1155 fcmd
[EYE_Y
] = ctx
->_EyeZDir
[1];
1156 fcmd
[EYE_Z
] = - ctx
->_EyeZDir
[2];
1157 fcmd
[EYE_RESCALE_FACTOR
] = ctx
->_ModelViewInvScale
;
1158 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.eye
);
1163 if (ctx
->Light
.Enabled
) {
1165 for (p
= 0 ; p
< MAX_LIGHTS
; p
++) {
1166 if (ctx
->Light
.Light
[p
].Enabled
) {
1167 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1168 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( lit
[p
] );
1170 if (l
->EyePosition
[3] == 0.0) {
1171 COPY_3FV( &fcmd
[LIT_POSITION_X
], l
->_VP_inf_norm
);
1172 COPY_3FV( &fcmd
[LIT_DIRECTION_X
], l
->_h_inf_norm
);
1173 fcmd
[LIT_POSITION_W
] = 0;
1174 fcmd
[LIT_DIRECTION_W
] = 0;
1176 COPY_4V( &fcmd
[LIT_POSITION_X
], l
->_Position
);
1177 fcmd
[LIT_DIRECTION_X
] = -l
->_NormDirection
[0];
1178 fcmd
[LIT_DIRECTION_Y
] = -l
->_NormDirection
[1];
1179 fcmd
[LIT_DIRECTION_Z
] = -l
->_NormDirection
[2];
1180 fcmd
[LIT_DIRECTION_W
] = 0;
1183 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
1189 static void r200Lightfv( GLcontext
*ctx
, GLenum light
,
1190 GLenum pname
, const GLfloat
*params
)
1192 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1193 GLint p
= light
- GL_LIGHT0
;
1194 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1195 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.lit
[p
].cmd
;
1202 update_light_colors( ctx
, p
);
1205 case GL_SPOT_DIRECTION
:
1206 /* picked up in update_light */
1210 /* positions picked up in update_light, but can do flag here */
1211 GLuint flag
= (p
&1)? R200_LIGHT_1_IS_LOCAL
: R200_LIGHT_0_IS_LOCAL
;
1212 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1214 R200_STATECHANGE(rmesa
, tcl
);
1215 if (l
->EyePosition
[3] != 0.0F
)
1216 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1218 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1222 case GL_SPOT_EXPONENT
:
1223 R200_STATECHANGE(rmesa
, lit
[p
]);
1224 fcmd
[LIT_SPOT_EXPONENT
] = params
[0];
1227 case GL_SPOT_CUTOFF
: {
1228 GLuint flag
= (p
&1) ? R200_LIGHT_1_IS_SPOT
: R200_LIGHT_0_IS_SPOT
;
1229 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1231 R200_STATECHANGE(rmesa
, lit
[p
]);
1232 fcmd
[LIT_SPOT_CUTOFF
] = l
->_CosCutoff
;
1234 R200_STATECHANGE(rmesa
, tcl
);
1235 if (l
->SpotCutoff
!= 180.0F
)
1236 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1238 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1243 case GL_CONSTANT_ATTENUATION
:
1244 R200_STATECHANGE(rmesa
, lit
[p
]);
1245 fcmd
[LIT_ATTEN_CONST
] = params
[0];
1246 if ( params
[0] == 0.0 )
1247 fcmd
[LIT_ATTEN_CONST_INV
] = FLT_MAX
;
1249 fcmd
[LIT_ATTEN_CONST_INV
] = 1.0 / params
[0];
1251 case GL_LINEAR_ATTENUATION
:
1252 R200_STATECHANGE(rmesa
, lit
[p
]);
1253 fcmd
[LIT_ATTEN_LINEAR
] = params
[0];
1255 case GL_QUADRATIC_ATTENUATION
:
1256 R200_STATECHANGE(rmesa
, lit
[p
]);
1257 fcmd
[LIT_ATTEN_QUADRATIC
] = params
[0];
1263 /* Set RANGE_ATTEN only when needed */
1266 case GL_CONSTANT_ATTENUATION
:
1267 case GL_LINEAR_ATTENUATION
:
1268 case GL_QUADRATIC_ATTENUATION
: {
1269 GLuint
*icmd
= (GLuint
*)R200_DB_STATE( tcl
);
1270 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1271 GLuint atten_flag
= ( p
&1 ) ? R200_LIGHT_1_ENABLE_RANGE_ATTEN
1272 : R200_LIGHT_0_ENABLE_RANGE_ATTEN
;
1273 GLuint atten_const_flag
= ( p
&1 ) ? R200_LIGHT_1_CONSTANT_RANGE_ATTEN
1274 : R200_LIGHT_0_CONSTANT_RANGE_ATTEN
;
1276 if ( l
->EyePosition
[3] == 0.0F
||
1277 ( ( fcmd
[LIT_ATTEN_CONST
] == 0.0 || fcmd
[LIT_ATTEN_CONST
] == 1.0 ) &&
1278 fcmd
[LIT_ATTEN_QUADRATIC
] == 0.0 && fcmd
[LIT_ATTEN_LINEAR
] == 0.0 ) ) {
1279 /* Disable attenuation */
1280 icmd
[idx
] &= ~atten_flag
;
1282 if ( fcmd
[LIT_ATTEN_QUADRATIC
] == 0.0 && fcmd
[LIT_ATTEN_LINEAR
] == 0.0 ) {
1283 /* Enable only constant portion of attenuation calculation */
1284 icmd
[idx
] |= ( atten_flag
| atten_const_flag
);
1286 /* Enable full attenuation calculation */
1287 icmd
[idx
] &= ~atten_const_flag
;
1288 icmd
[idx
] |= atten_flag
;
1292 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.tcl
);
1300 static void r200UpdateLocalViewer ( GLcontext
*ctx
)
1302 /* It looks like for the texgen modes GL_SPHERE_MAP, GL_NORMAL_MAP and
1303 GL_REFLECTION_MAP we need R200_LOCAL_VIEWER set (fglrx does exactly that
1304 for these and only these modes). This means specular highlights may turn out
1305 wrong in some cases when lighting is enabled but GL_LIGHT_MODEL_LOCAL_VIEWER
1306 is not set, though it seems to happen rarely and the effect seems quite
1307 subtle. May need TCL fallback to fix it completely, though I'm not sure
1308 how you'd identify the cases where the specular highlights indeed will
1309 be wrong. Don't know if fglrx does something special in that case.
1311 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1312 R200_STATECHANGE( rmesa
, tcl
);
1313 if (ctx
->Light
.Model
.LocalViewer
||
1314 ctx
->Texture
._GenFlags
& TEXGEN_NEED_NORMALS
)
1315 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LOCAL_VIEWER
;
1317 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LOCAL_VIEWER
;
1320 static void r200LightModelfv( GLcontext
*ctx
, GLenum pname
,
1321 const GLfloat
*param
)
1323 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1326 case GL_LIGHT_MODEL_AMBIENT
:
1327 update_global_ambient( ctx
);
1330 case GL_LIGHT_MODEL_LOCAL_VIEWER
:
1331 r200UpdateLocalViewer( ctx
);
1334 case GL_LIGHT_MODEL_TWO_SIDE
:
1335 R200_STATECHANGE( rmesa
, tcl
);
1336 if (ctx
->Light
.Model
.TwoSide
)
1337 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHT_TWOSIDE
;
1339 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~(R200_LIGHT_TWOSIDE
);
1340 if (rmesa
->radeon
.TclFallback
) {
1341 r200ChooseRenderState( ctx
);
1342 r200ChooseVertexState( ctx
);
1346 case GL_LIGHT_MODEL_COLOR_CONTROL
:
1347 r200UpdateSpecular(ctx
);
1355 static void r200ShadeModel( GLcontext
*ctx
, GLenum mode
)
1357 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1358 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
1360 s
&= ~(R200_DIFFUSE_SHADE_MASK
|
1361 R200_ALPHA_SHADE_MASK
|
1362 R200_SPECULAR_SHADE_MASK
|
1363 R200_FOG_SHADE_MASK
|
1364 R200_DISC_FOG_SHADE_MASK
);
1368 s
|= (R200_DIFFUSE_SHADE_FLAT
|
1369 R200_ALPHA_SHADE_FLAT
|
1370 R200_SPECULAR_SHADE_FLAT
|
1371 R200_FOG_SHADE_FLAT
|
1372 R200_DISC_FOG_SHADE_FLAT
);
1375 s
|= (R200_DIFFUSE_SHADE_GOURAUD
|
1376 R200_ALPHA_SHADE_GOURAUD
|
1377 R200_SPECULAR_SHADE_GOURAUD
|
1378 R200_FOG_SHADE_GOURAUD
|
1379 R200_DISC_FOG_SHADE_GOURAUD
);
1385 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
1386 R200_STATECHANGE( rmesa
, set
);
1387 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
1392 /* =============================================================
1396 static void r200ClipPlane( GLcontext
*ctx
, GLenum plane
, const GLfloat
*eq
)
1398 GLint p
= (GLint
) plane
- (GLint
) GL_CLIP_PLANE0
;
1399 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1400 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1402 R200_STATECHANGE( rmesa
, ucp
[p
] );
1403 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1404 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1405 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1406 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1409 static void r200UpdateClipPlanes( GLcontext
*ctx
)
1411 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1414 for (p
= 0; p
< ctx
->Const
.MaxClipPlanes
; p
++) {
1415 if (ctx
->Transform
.ClipPlanesEnabled
& (1 << p
)) {
1416 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1418 R200_STATECHANGE( rmesa
, ucp
[p
] );
1419 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1420 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1421 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1422 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1428 /* =============================================================
1433 r200StencilFuncSeparate( GLcontext
*ctx
, GLenum face
, GLenum func
,
1434 GLint ref
, GLuint mask
)
1436 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1437 GLuint refmask
= (((ctx
->Stencil
.Ref
[0] & 0xff) << R200_STENCIL_REF_SHIFT
) |
1438 ((ctx
->Stencil
.ValueMask
[0] & 0xff) << R200_STENCIL_MASK_SHIFT
));
1440 R200_STATECHANGE( rmesa
, ctx
);
1441 R200_STATECHANGE( rmesa
, msk
);
1443 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_STENCIL_TEST_MASK
;
1444 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~(R200_STENCIL_REF_MASK
|
1445 R200_STENCIL_VALUE_MASK
);
1447 switch ( ctx
->Stencil
.Function
[0] ) {
1449 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEVER
;
1452 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LESS
;
1455 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_EQUAL
;
1458 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LEQUAL
;
1461 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GREATER
;
1464 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEQUAL
;
1467 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GEQUAL
;
1470 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_ALWAYS
;
1474 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |= refmask
;
1478 r200StencilMaskSeparate( GLcontext
*ctx
, GLenum face
, GLuint mask
)
1480 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1482 R200_STATECHANGE( rmesa
, msk
);
1483 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~R200_STENCIL_WRITE_MASK
;
1484 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |=
1485 ((ctx
->Stencil
.WriteMask
[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT
);
1489 r200StencilOpSeparate( GLcontext
*ctx
, GLenum face
, GLenum fail
,
1490 GLenum zfail
, GLenum zpass
)
1492 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1494 R200_STATECHANGE( rmesa
, ctx
);
1495 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~(R200_STENCIL_FAIL_MASK
|
1496 R200_STENCIL_ZFAIL_MASK
|
1497 R200_STENCIL_ZPASS_MASK
);
1499 switch ( ctx
->Stencil
.FailFunc
[0] ) {
1501 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_KEEP
;
1504 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_ZERO
;
1507 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_REPLACE
;
1510 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC
;
1513 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC
;
1515 case GL_INCR_WRAP_EXT
:
1516 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC_WRAP
;
1518 case GL_DECR_WRAP_EXT
:
1519 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC_WRAP
;
1522 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INVERT
;
1526 switch ( ctx
->Stencil
.ZFailFunc
[0] ) {
1528 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_KEEP
;
1531 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_ZERO
;
1534 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_REPLACE
;
1537 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC
;
1540 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC
;
1542 case GL_INCR_WRAP_EXT
:
1543 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC_WRAP
;
1545 case GL_DECR_WRAP_EXT
:
1546 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC_WRAP
;
1549 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INVERT
;
1553 switch ( ctx
->Stencil
.ZPassFunc
[0] ) {
1555 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_KEEP
;
1558 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_ZERO
;
1561 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_REPLACE
;
1564 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC
;
1567 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC
;
1569 case GL_INCR_WRAP_EXT
:
1570 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC_WRAP
;
1572 case GL_DECR_WRAP_EXT
:
1573 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC_WRAP
;
1576 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INVERT
;
1581 static void r200ClearStencil( GLcontext
*ctx
, GLint s
)
1583 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1585 rmesa
->radeon
.state
.stencil
.clear
=
1586 ((GLuint
) (ctx
->Stencil
.Clear
& 0xff) |
1587 (0xff << R200_STENCIL_MASK_SHIFT
) |
1588 ((ctx
->Stencil
.WriteMask
[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT
));
1592 /* =============================================================
1593 * Window position and viewport transformation
1597 * To correctly position primitives:
1599 #define SUBPIXEL_X 0.125
1600 #define SUBPIXEL_Y 0.125
1604 * Called when window size or position changes or viewport or depth range
1605 * state is changed. We update the hardware viewport state here.
1607 void r200UpdateWindow( GLcontext
*ctx
)
1609 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1610 __DRIdrawablePrivate
*dPriv
= rmesa
->radeon
.dri
.drawable
;
1611 GLfloat xoffset
= dPriv
? (GLfloat
) dPriv
->x
: 0;
1612 GLfloat yoffset
= dPriv
? (GLfloat
) dPriv
->y
+ dPriv
->h
: 0;
1613 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1614 const GLboolean render_to_fbo
= (ctx
->DrawBuffer
? (ctx
->DrawBuffer
->Name
!= 0) : 0);
1615 const GLfloat depthScale
= 1.0F
/ ctx
->DrawBuffer
->_DepthMaxF
;
1616 GLfloat y_scale
, y_bias
;
1618 if (render_to_fbo
) {
1626 float_ui32_type sx
= { v
[MAT_SX
] };
1627 float_ui32_type tx
= { v
[MAT_TX
] + xoffset
+ SUBPIXEL_X
};
1628 float_ui32_type sy
= { v
[MAT_SY
] * y_scale
};
1629 float_ui32_type ty
= { (v
[MAT_TY
] * y_scale
) + y_bias
+ SUBPIXEL_Y
};
1630 float_ui32_type sz
= { v
[MAT_SZ
] * depthScale
};
1631 float_ui32_type tz
= { v
[MAT_TZ
] * depthScale
};
1633 R200_STATECHANGE( rmesa
, vpt
);
1635 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XSCALE
] = sx
.ui32
;
1636 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = tx
.ui32
;
1637 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YSCALE
] = sy
.ui32
;
1638 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = ty
.ui32
;
1639 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZSCALE
] = sz
.ui32
;
1640 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZOFFSET
] = tz
.ui32
;
1645 static void r200Viewport( GLcontext
*ctx
, GLint x
, GLint y
,
1646 GLsizei width
, GLsizei height
)
1648 /* Don't pipeline viewport changes, conflict with window offset
1649 * setting below. Could apply deltas to rescue pipelined viewport
1650 * values, or keep the originals hanging around.
1652 r200UpdateWindow( ctx
);
1654 radeon_viewport(ctx
, x
, y
, width
, height
);
1657 static void r200DepthRange( GLcontext
*ctx
, GLclampd nearval
,
1660 r200UpdateWindow( ctx
);
1663 void r200UpdateViewportOffset( GLcontext
*ctx
)
1665 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1666 __DRIdrawablePrivate
*dPriv
= rmesa
->radeon
.dri
.drawable
;
1667 GLfloat xoffset
= (GLfloat
)dPriv
->x
;
1668 GLfloat yoffset
= (GLfloat
)dPriv
->y
+ dPriv
->h
;
1669 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1674 tx
.f
= v
[MAT_TX
] + xoffset
+ SUBPIXEL_X
;
1675 ty
.f
= (- v
[MAT_TY
]) + yoffset
+ SUBPIXEL_Y
;
1677 if ( rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] != tx
.ui32
||
1678 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] != ty
.ui32
)
1680 /* Note: this should also modify whatever data the context reset
1683 R200_STATECHANGE( rmesa
, vpt
);
1684 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = tx
.ui32
;
1685 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = ty
.ui32
;
1687 /* update polygon stipple x/y screen offset */
1690 GLuint m
= rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
];
1692 m
&= ~(R200_STIPPLE_X_OFFSET_MASK
|
1693 R200_STIPPLE_Y_OFFSET_MASK
);
1695 /* add magic offsets, then invert */
1696 stx
= 31 - ((rmesa
->radeon
.dri
.drawable
->x
- 1) & R200_STIPPLE_COORD_MASK
);
1697 sty
= 31 - ((rmesa
->radeon
.dri
.drawable
->y
+ rmesa
->radeon
.dri
.drawable
->h
- 1)
1698 & R200_STIPPLE_COORD_MASK
);
1700 m
|= ((stx
<< R200_STIPPLE_X_OFFSET_SHIFT
) |
1701 (sty
<< R200_STIPPLE_Y_OFFSET_SHIFT
));
1703 if ( rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] != m
) {
1704 R200_STATECHANGE( rmesa
, msc
);
1705 rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] = m
;
1710 radeonUpdateScissor( ctx
);
1715 /* =============================================================
1719 static void r200ClearColor( GLcontext
*ctx
, const GLfloat c
[4] )
1721 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1723 CLAMPED_FLOAT_TO_UBYTE(color
[0], c
[0]);
1724 CLAMPED_FLOAT_TO_UBYTE(color
[1], c
[1]);
1725 CLAMPED_FLOAT_TO_UBYTE(color
[2], c
[2]);
1726 CLAMPED_FLOAT_TO_UBYTE(color
[3], c
[3]);
1727 rmesa
->radeon
.state
.color
.clear
= radeonPackColor( rmesa
->radeon
.radeonScreen
->cpp
,
1729 color
[2], color
[3] );
1733 static void r200RenderMode( GLcontext
*ctx
, GLenum mode
)
1735 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1736 FALLBACK( rmesa
, R200_FALLBACK_RENDER_MODE
, (mode
!= GL_RENDER
) );
1740 static GLuint r200_rop_tab
[] = {
1743 R200_ROP_AND_REVERSE
,
1745 R200_ROP_AND_INVERTED
,
1752 R200_ROP_OR_REVERSE
,
1753 R200_ROP_COPY_INVERTED
,
1754 R200_ROP_OR_INVERTED
,
1759 static void r200LogicOpCode( GLcontext
*ctx
, GLenum opcode
)
1761 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1762 GLuint rop
= (GLuint
)opcode
- GL_CLEAR
;
1766 R200_STATECHANGE( rmesa
, msk
);
1767 rmesa
->hw
.msk
.cmd
[MSK_RB3D_ROPCNTL
] = r200_rop_tab
[rop
];
1770 /* =============================================================
1771 * State enable/disable
1774 static void r200Enable( GLcontext
*ctx
, GLenum cap
, GLboolean state
)
1776 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1779 if ( R200_DEBUG
& DEBUG_STATE
)
1780 fprintf( stderr
, "%s( %s = %s )\n", __FUNCTION__
,
1781 _mesa_lookup_enum_by_nr( cap
),
1782 state
? "GL_TRUE" : "GL_FALSE" );
1785 /* Fast track this one...
1793 R200_STATECHANGE( rmesa
, ctx
);
1795 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ALPHA_TEST_ENABLE
;
1797 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ALPHA_TEST_ENABLE
;
1802 case GL_COLOR_LOGIC_OP
:
1803 r200_set_blend_state( ctx
);
1806 case GL_CLIP_PLANE0
:
1807 case GL_CLIP_PLANE1
:
1808 case GL_CLIP_PLANE2
:
1809 case GL_CLIP_PLANE3
:
1810 case GL_CLIP_PLANE4
:
1811 case GL_CLIP_PLANE5
:
1812 p
= cap
-GL_CLIP_PLANE0
;
1813 R200_STATECHANGE( rmesa
, tcl
);
1815 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= (R200_UCP_ENABLE_0
<<p
);
1816 r200ClipPlane( ctx
, cap
, NULL
);
1819 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~(R200_UCP_ENABLE_0
<<p
);
1823 case GL_COLOR_MATERIAL
:
1824 r200ColorMaterial( ctx
, 0, 0 );
1825 r200UpdateMaterial( ctx
);
1829 r200CullFace( ctx
, 0 );
1833 R200_STATECHANGE(rmesa
, ctx
);
1835 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_Z_ENABLE
;
1837 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_Z_ENABLE
;
1842 R200_STATECHANGE(rmesa
, ctx
);
1844 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_DITHER_ENABLE
;
1845 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~rmesa
->radeon
.state
.color
.roundEnable
;
1847 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_DITHER_ENABLE
;
1848 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= rmesa
->radeon
.state
.color
.roundEnable
;
1853 R200_STATECHANGE(rmesa
, ctx
);
1855 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_FOG_ENABLE
;
1856 r200Fogfv( ctx
, GL_FOG_MODE
, NULL
);
1858 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_FOG_ENABLE
;
1859 R200_STATECHANGE(rmesa
, tcl
);
1860 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_TCL_FOG_MASK
;
1862 r200UpdateSpecular( ctx
); /* for PK_SPEC */
1863 if (rmesa
->radeon
.TclFallback
)
1864 r200ChooseVertexState( ctx
);
1865 _mesa_allow_light_in_model( ctx
, !state
);
1876 R200_STATECHANGE(rmesa
, tcl
);
1877 p
= cap
- GL_LIGHT0
;
1879 flag
= (R200_LIGHT_1_ENABLE
|
1880 R200_LIGHT_1_ENABLE_AMBIENT
|
1881 R200_LIGHT_1_ENABLE_SPECULAR
);
1883 flag
= (R200_LIGHT_0_ENABLE
|
1884 R200_LIGHT_0_ENABLE_AMBIENT
|
1885 R200_LIGHT_0_ENABLE_SPECULAR
);
1888 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] |= flag
;
1890 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] &= ~flag
;
1894 update_light_colors( ctx
, p
);
1898 r200UpdateSpecular(ctx
);
1899 /* for reflection map fixup - might set recheck_texgen for all units too */
1900 rmesa
->radeon
.NewGLState
|= _NEW_TEXTURE
;
1903 case GL_LINE_SMOOTH
:
1904 R200_STATECHANGE( rmesa
, ctx
);
1906 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_LINE
;
1908 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_LINE
;
1912 case GL_LINE_STIPPLE
:
1913 R200_STATECHANGE( rmesa
, set
);
1915 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_PATTERN_ENABLE
;
1917 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_PATTERN_ENABLE
;
1922 R200_STATECHANGE( rmesa
, tcl
);
1924 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_NORMALIZE_NORMALS
;
1926 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_NORMALIZE_NORMALS
;
1930 /* Pointsize registers on r200 only work for point sprites, and point smooth
1931 * doesn't work for point sprites (and isn't needed for 1.0 sized aa points).
1932 * In any case, setting pointmin == pointsizemax == 1.0 for aa points
1933 * is enough to satisfy conform.
1935 case GL_POINT_SMOOTH
:
1938 /* These don't really do anything, as we don't use the 3vtx
1942 case GL_POLYGON_OFFSET_POINT
:
1943 R200_STATECHANGE( rmesa
, set
);
1945 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_POINT
;
1947 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_POINT
;
1951 case GL_POLYGON_OFFSET_LINE
:
1952 R200_STATECHANGE( rmesa
, set
);
1954 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_LINE
;
1956 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_LINE
;
1961 case GL_POINT_SPRITE_ARB
:
1962 R200_STATECHANGE( rmesa
, spr
);
1965 for (i
= 0; i
< 6; i
++) {
1966 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |=
1967 ctx
->Point
.CoordReplace
[i
] << (R200_PS_GEN_TEX_0_SHIFT
+ i
);
1970 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] &= ~R200_PS_GEN_TEX_MASK
;
1974 case GL_POLYGON_OFFSET_FILL
:
1975 R200_STATECHANGE( rmesa
, set
);
1977 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_TRI
;
1979 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_TRI
;
1983 case GL_POLYGON_SMOOTH
:
1984 R200_STATECHANGE( rmesa
, ctx
);
1986 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_POLY
;
1988 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_POLY
;
1992 case GL_POLYGON_STIPPLE
:
1993 R200_STATECHANGE(rmesa
, set
);
1995 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_STIPPLE_ENABLE
;
1997 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_STIPPLE_ENABLE
;
2001 case GL_RESCALE_NORMAL_EXT
: {
2002 GLboolean tmp
= ctx
->_NeedEyeCoords
? state
: !state
;
2003 R200_STATECHANGE( rmesa
, tcl
);
2005 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
2007 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
2012 case GL_SCISSOR_TEST
:
2013 radeon_firevertices(&rmesa
->radeon
);
2014 rmesa
->radeon
.state
.scissor
.enabled
= state
;
2015 radeonUpdateScissor( ctx
);
2018 case GL_STENCIL_TEST
:
2020 GLboolean hw_stencil
= GL_FALSE
;
2021 if (ctx
->DrawBuffer
) {
2022 struct radeon_renderbuffer
*rrbStencil
2023 = radeon_get_renderbuffer(ctx
->DrawBuffer
, BUFFER_STENCIL
);
2024 hw_stencil
= (rrbStencil
&& rrbStencil
->bo
);
2028 R200_STATECHANGE( rmesa
, ctx
);
2030 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_STENCIL_ENABLE
;
2032 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_STENCIL_ENABLE
;
2035 FALLBACK( rmesa
, R200_FALLBACK_STENCIL
, state
);
2040 case GL_TEXTURE_GEN_Q
:
2041 case GL_TEXTURE_GEN_R
:
2042 case GL_TEXTURE_GEN_S
:
2043 case GL_TEXTURE_GEN_T
:
2044 /* Picked up in r200UpdateTextureState.
2046 rmesa
->recheck_texgen
[ctx
->Texture
.CurrentUnit
] = GL_TRUE
;
2049 case GL_COLOR_SUM_EXT
:
2050 r200UpdateSpecular ( ctx
);
2053 case GL_VERTEX_PROGRAM_ARB
:
2056 rmesa
->curr_vp_hw
= NULL
;
2057 R200_STATECHANGE( rmesa
, vap
);
2058 rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
] &= ~R200_VAP_PROG_VTX_SHADER_ENABLE
;
2059 /* mark all tcl atoms (tcl vector state got overwritten) dirty
2060 not sure about tcl scalar state - we need at least grd
2061 with vert progs too.
2062 ucp looks like it doesn't get overwritten (may even work
2063 with vp for pos-invariant progs if we're lucky) */
2064 R200_STATECHANGE( rmesa
, mtl
[0] );
2065 R200_STATECHANGE( rmesa
, mtl
[1] );
2066 R200_STATECHANGE( rmesa
, fog
);
2067 R200_STATECHANGE( rmesa
, glt
);
2068 R200_STATECHANGE( rmesa
, eye
);
2069 for (i
= R200_MTX_MV
; i
<= R200_MTX_TEX5
; i
++) {
2070 R200_STATECHANGE( rmesa
, mat
[i
] );
2072 for (i
= 0 ; i
< 8; i
++) {
2073 R200_STATECHANGE( rmesa
, lit
[i
] );
2075 R200_STATECHANGE( rmesa
, tcl
);
2076 for (i
= 0; i
<= ctx
->Const
.MaxClipPlanes
; i
++) {
2077 if (ctx
->Transform
.ClipPlanesEnabled
& (1 << i
)) {
2078 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= (R200_UCP_ENABLE_0
<< i
);
2081 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0 << i);
2084 /* ugly. Need to call everything which might change compsel. */
2085 r200UpdateSpecular( ctx
);
2087 /* shouldn't be necessary, as it's picked up anyway in r200ValidateState (_NEW_PROGRAM),
2088 but without it doom3 locks up at always the same places. Why? */
2089 /* FIXME: This can (and should) be replaced by a call to the TCL_STATE_FLUSH reg before
2090 accessing VAP_SE_VAP_CNTL. Requires drm changes (done). Remove after some time... */
2091 r200UpdateTextureState( ctx
);
2092 /* if we call r200UpdateTextureState we need the code below because we are calling it with
2093 non-current derived enabled values which may revert the state atoms for frag progs even when
2094 they already got disabled... ugh
2095 Should really figure out why we need to call r200UpdateTextureState in the first place */
2097 for (unit
= 0; unit
< R200_MAX_TEXTURE_UNITS
; unit
++) {
2098 R200_STATECHANGE( rmesa
, pix
[unit
] );
2099 R200_STATECHANGE( rmesa
, tex
[unit
] );
2100 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] &=
2101 ~(R200_TXFORMAT_ST_ROUTE_MASK
| R200_TXFORMAT_LOOKUP_DISABLE
);
2102 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] |= unit
<< R200_TXFORMAT_ST_ROUTE_SHIFT
;
2103 /* need to guard this with drmSupportsFragmentShader? Should never get here if
2104 we don't announce ATI_fs, right? */
2105 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXMULTI_CTL
] = 0;
2107 R200_STATECHANGE( rmesa
, cst
);
2108 R200_STATECHANGE( rmesa
, tf
);
2109 rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] = 0;
2113 /* picked up later */
2115 /* call functions which change hw state based on ARB_vp enabled or not. */
2116 r200PointParameter( ctx
, GL_POINT_DISTANCE_ATTENUATION
, NULL
);
2117 r200Fogfv( ctx
, GL_FOG_COORD_SRC
, NULL
);
2120 case GL_VERTEX_PROGRAM_POINT_SIZE_ARB
:
2121 r200PointParameter( ctx
, GL_POINT_DISTANCE_ATTENUATION
, NULL
);
2124 case GL_FRAGMENT_SHADER_ATI
:
2126 /* restore normal tex env colors and make sure tex env combine will get updated
2127 mark env atoms dirty (as their data was overwritten by afs even
2128 if they didn't change) and restore tex coord routing */
2130 for (unit
= 0; unit
< R200_MAX_TEXTURE_UNITS
; unit
++) {
2131 R200_STATECHANGE( rmesa
, pix
[unit
] );
2132 R200_STATECHANGE( rmesa
, tex
[unit
] );
2133 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] &=
2134 ~(R200_TXFORMAT_ST_ROUTE_MASK
| R200_TXFORMAT_LOOKUP_DISABLE
);
2135 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] |= unit
<< R200_TXFORMAT_ST_ROUTE_SHIFT
;
2136 /* need to guard this with drmSupportsFragmentShader? Should never get here if
2137 we don't announce ATI_fs, right? */
2138 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXMULTI_CTL
] = 0;
2140 R200_STATECHANGE( rmesa
, cst
);
2141 R200_STATECHANGE( rmesa
, tf
);
2142 rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] = 0;
2145 /* need to mark this dirty as pix/tf atoms have overwritten the data
2146 even if the data in the atoms didn't change */
2147 R200_STATECHANGE( rmesa
, atf
);
2148 R200_STATECHANGE( rmesa
, afs
[1] );
2149 /* everything else picked up in r200UpdateTextureState hopefully */
2158 void r200LightingSpaceChange( GLcontext
*ctx
)
2160 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2163 if (R200_DEBUG
& DEBUG_STATE
)
2164 fprintf(stderr
, "%s %d BEFORE %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
2165 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
2167 if (ctx
->_NeedEyeCoords
)
2168 tmp
= ctx
->Transform
.RescaleNormals
;
2170 tmp
= !ctx
->Transform
.RescaleNormals
;
2172 R200_STATECHANGE( rmesa
, tcl
);
2174 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
2176 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
2179 if (R200_DEBUG
& DEBUG_STATE
)
2180 fprintf(stderr
, "%s %d AFTER %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
2181 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
2184 /* =============================================================
2185 * Deferred state management - matrices, textures, other?
2191 static void upload_matrix( r200ContextPtr rmesa
, GLfloat
*src
, int idx
)
2193 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
2197 for (i
= 0 ; i
< 4 ; i
++) {
2201 *dest
++ = src
[i
+12];
2204 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
2207 static void upload_matrix_t( r200ContextPtr rmesa
, const GLfloat
*src
, int idx
)
2209 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
2210 memcpy(dest
, src
, 16*sizeof(float));
2211 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
2215 static void update_texturematrix( GLcontext
*ctx
)
2217 r200ContextPtr rmesa
= R200_CONTEXT( ctx
);
2218 GLuint tpc
= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
];
2219 GLuint compsel
= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
];
2222 if (R200_DEBUG
& DEBUG_STATE
)
2223 fprintf(stderr
, "%s before COMPSEL: %x\n", __FUNCTION__
,
2224 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]);
2226 rmesa
->TexMatEnabled
= 0;
2227 rmesa
->TexMatCompSel
= 0;
2229 for (unit
= 0 ; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
2230 if (!ctx
->Texture
.Unit
[unit
]._ReallyEnabled
)
2233 if (ctx
->TextureMatrixStack
[unit
].Top
->type
!= MATRIX_IDENTITY
) {
2234 rmesa
->TexMatEnabled
|= (R200_TEXGEN_TEXMAT_0_ENABLE
|
2235 R200_TEXMAT_0_ENABLE
) << unit
;
2237 rmesa
->TexMatCompSel
|= R200_OUTPUT_TEX_0
<< unit
;
2239 if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2240 /* Need to preconcatenate any active texgen
2241 * obj/eyeplane matrices:
2243 _math_matrix_mul_matrix( &rmesa
->tmpmat
,
2244 ctx
->TextureMatrixStack
[unit
].Top
,
2245 &rmesa
->TexGenMatrix
[unit
] );
2246 upload_matrix( rmesa
, rmesa
->tmpmat
.m
, R200_MTX_TEX0
+unit
);
2249 upload_matrix( rmesa
, ctx
->TextureMatrixStack
[unit
].Top
->m
,
2250 R200_MTX_TEX0
+unit
);
2253 else if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2254 upload_matrix( rmesa
, rmesa
->TexGenMatrix
[unit
].m
,
2255 R200_MTX_TEX0
+unit
);
2259 tpc
= (rmesa
->TexMatEnabled
| rmesa
->TexGenEnabled
);
2260 if (tpc
!= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
]) {
2261 R200_STATECHANGE(rmesa
, tcg
);
2262 rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
] = tpc
;
2265 compsel
&= ~R200_OUTPUT_TEX_MASK
;
2266 compsel
|= rmesa
->TexMatCompSel
| rmesa
->TexGenCompSel
;
2267 if (compsel
!= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]) {
2268 R200_STATECHANGE(rmesa
, vtx
);
2269 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] = compsel
;
2273 static GLboolean
r200ValidateBuffers(GLcontext
*ctx
)
2275 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2276 struct radeon_renderbuffer
*rrb
;
2279 radeon_validate_reset_bos(&rmesa
->radeon
);
2281 rrb
= radeon_get_colorbuffer(&rmesa
->radeon
);
2283 if (rrb
&& rrb
->bo
) {
2284 radeon_validate_bo(&rmesa
->radeon
, rrb
->bo
,
2285 0, RADEON_GEM_DOMAIN_VRAM
);
2289 rrb
= radeon_get_depthbuffer(&rmesa
->radeon
);
2291 if (rrb
&& rrb
->bo
) {
2292 radeon_validate_bo(&rmesa
->radeon
, rrb
->bo
,
2293 0, RADEON_GEM_DOMAIN_VRAM
);
2296 for (i
= 0; i
< ctx
->Const
.MaxTextureImageUnits
; ++i
) {
2299 if (!ctx
->Texture
.Unit
[i
]._ReallyEnabled
)
2302 t
= radeon_tex_obj(ctx
->Texture
.Unit
[i
]._Current
);
2303 if (t
->image_override
&& t
->bo
)
2304 radeon_validate_bo(&rmesa
->radeon
, t
->bo
,
2305 RADEON_GEM_DOMAIN_GTT
| RADEON_GEM_DOMAIN_VRAM
, 0);
2307 radeon_validate_bo(&rmesa
->radeon
, t
->mt
->bo
,
2308 RADEON_GEM_DOMAIN_GTT
| RADEON_GEM_DOMAIN_VRAM
, 0);
2311 return radeon_revalidate_bos(ctx
);
2314 GLboolean
r200ValidateState( GLcontext
*ctx
)
2316 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2317 GLuint new_state
= rmesa
->radeon
.NewGLState
;
2319 if (new_state
& (_NEW_BUFFERS
| _NEW_COLOR
| _NEW_PIXEL
)) {
2320 _mesa_update_framebuffer(ctx
);
2321 /* this updates the DrawBuffer's Width/Height if it's a FBO */
2322 _mesa_update_draw_buffer_bounds(ctx
);
2324 R200_STATECHANGE(rmesa
, ctx
);
2327 if (new_state
& (_NEW_TEXTURE
| _NEW_PROGRAM
)) {
2328 r200UpdateTextureState( ctx
);
2329 new_state
|= rmesa
->radeon
.NewGLState
; /* may add TEXTURE_MATRIX */
2330 r200UpdateLocalViewer( ctx
);
2333 /* we need to do a space check here */
2334 if (!r200ValidateBuffers(ctx
))
2337 /* FIXME: don't really need most of these when vertex progs are enabled */
2339 /* Need an event driven matrix update?
2341 if (new_state
& (_NEW_MODELVIEW
|_NEW_PROJECTION
))
2342 upload_matrix( rmesa
, ctx
->_ModelProjectMatrix
.m
, R200_MTX_MVP
);
2344 /* Need these for lighting (shouldn't upload otherwise)
2346 if (new_state
& (_NEW_MODELVIEW
)) {
2347 upload_matrix( rmesa
, ctx
->ModelviewMatrixStack
.Top
->m
, R200_MTX_MV
);
2348 upload_matrix_t( rmesa
, ctx
->ModelviewMatrixStack
.Top
->inv
, R200_MTX_IMV
);
2351 /* Does this need to be triggered on eg. modelview for
2352 * texgen-derived objplane/eyeplane matrices?
2354 if (new_state
& (_NEW_TEXTURE
|_NEW_TEXTURE_MATRIX
)) {
2355 update_texturematrix( ctx
);
2358 if (new_state
& (_NEW_LIGHT
|_NEW_MODELVIEW
|_MESA_NEW_NEED_EYE_COORDS
)) {
2359 update_light( ctx
);
2362 /* emit all active clip planes if projection matrix changes.
2364 if (new_state
& (_NEW_PROJECTION
)) {
2365 if (ctx
->Transform
.ClipPlanesEnabled
)
2366 r200UpdateClipPlanes( ctx
);
2369 if (new_state
& (_NEW_PROGRAM
|
2370 /* need to test for pretty much anything due to possible parameter bindings */
2371 _NEW_MODELVIEW
|_NEW_PROJECTION
|_NEW_TRANSFORM
|
2372 _NEW_LIGHT
|_NEW_TEXTURE
|_NEW_TEXTURE_MATRIX
|
2373 _NEW_FOG
|_NEW_POINT
|_NEW_TRACK_MATRIX
)) {
2374 if (ctx
->VertexProgram
._Enabled
) {
2375 r200SetupVertexProg( ctx
);
2377 else TCL_FALLBACK(ctx
, R200_TCL_FALLBACK_VERTEX_PROGRAM
, 0);
2380 rmesa
->radeon
.NewGLState
= 0;
2385 static void r200InvalidateState( GLcontext
*ctx
, GLuint new_state
)
2387 _swrast_InvalidateState( ctx
, new_state
);
2388 _swsetup_InvalidateState( ctx
, new_state
);
2389 _vbo_InvalidateState( ctx
, new_state
);
2390 _tnl_InvalidateState( ctx
, new_state
);
2391 _ae_invalidate_state( ctx
, new_state
);
2392 R200_CONTEXT(ctx
)->radeon
.NewGLState
|= new_state
;
2395 /* A hack. The r200 can actually cope just fine with materials
2396 * between begin/ends, so fix this.
2397 * Should map to inputs just like the generic vertex arrays for vertex progs.
2398 * In theory there could still be too many and we'd still need a fallback.
2400 static GLboolean
check_material( GLcontext
*ctx
)
2402 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
2405 for (i
= _TNL_ATTRIB_MAT_FRONT_AMBIENT
;
2406 i
< _TNL_ATTRIB_MAT_BACK_INDEXES
;
2408 if (tnl
->vb
.AttribPtr
[i
] &&
2409 tnl
->vb
.AttribPtr
[i
]->stride
)
2415 static void r200WrapRunPipeline( GLcontext
*ctx
)
2417 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2418 GLboolean has_material
;
2421 fprintf(stderr
, "%s, newstate: %x\n", __FUNCTION__
, rmesa
->radeon
.NewGLState
);
2425 if (rmesa
->radeon
.NewGLState
)
2426 if (!r200ValidateState( ctx
))
2427 FALLBACK(rmesa
, RADEON_FALLBACK_TEXTURE
, GL_TRUE
);
2429 has_material
= !ctx
->VertexProgram
._Enabled
&& ctx
->Light
.Enabled
&& check_material( ctx
);
2432 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_TRUE
);
2435 /* Run the pipeline.
2437 _tnl_run_pipeline( ctx
);
2440 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_FALSE
);
2445 /* Initialize the driver's state functions.
2447 void r200InitStateFuncs( struct dd_function_table
*functions
)
2449 functions
->UpdateState
= r200InvalidateState
;
2450 functions
->LightingSpaceChange
= r200LightingSpaceChange
;
2452 functions
->DrawBuffer
= radeonDrawBuffer
;
2453 functions
->ReadBuffer
= radeonReadBuffer
;
2455 functions
->AlphaFunc
= r200AlphaFunc
;
2456 functions
->BlendColor
= r200BlendColor
;
2457 functions
->BlendEquationSeparate
= r200BlendEquationSeparate
;
2458 functions
->BlendFuncSeparate
= r200BlendFuncSeparate
;
2459 functions
->ClearColor
= r200ClearColor
;
2460 functions
->ClearDepth
= r200ClearDepth
;
2461 functions
->ClearIndex
= NULL
;
2462 functions
->ClearStencil
= r200ClearStencil
;
2463 functions
->ClipPlane
= r200ClipPlane
;
2464 functions
->ColorMask
= r200ColorMask
;
2465 functions
->CullFace
= r200CullFace
;
2466 functions
->DepthFunc
= r200DepthFunc
;
2467 functions
->DepthMask
= r200DepthMask
;
2468 functions
->DepthRange
= r200DepthRange
;
2469 functions
->Enable
= r200Enable
;
2470 functions
->Fogfv
= r200Fogfv
;
2471 functions
->FrontFace
= r200FrontFace
;
2472 functions
->Hint
= NULL
;
2473 functions
->IndexMask
= NULL
;
2474 functions
->LightModelfv
= r200LightModelfv
;
2475 functions
->Lightfv
= r200Lightfv
;
2476 functions
->LineStipple
= r200LineStipple
;
2477 functions
->LineWidth
= r200LineWidth
;
2478 functions
->LogicOpcode
= r200LogicOpCode
;
2479 functions
->PolygonMode
= r200PolygonMode
;
2480 functions
->PolygonOffset
= r200PolygonOffset
;
2481 functions
->PolygonStipple
= r200PolygonStipple
;
2482 functions
->PointParameterfv
= r200PointParameter
;
2483 functions
->PointSize
= r200PointSize
;
2484 functions
->RenderMode
= r200RenderMode
;
2485 functions
->Scissor
= radeonScissor
;
2486 functions
->ShadeModel
= r200ShadeModel
;
2487 functions
->StencilFuncSeparate
= r200StencilFuncSeparate
;
2488 functions
->StencilMaskSeparate
= r200StencilMaskSeparate
;
2489 functions
->StencilOpSeparate
= r200StencilOpSeparate
;
2490 functions
->Viewport
= r200Viewport
;
2494 void r200InitTnlFuncs( GLcontext
*ctx
)
2496 TNL_CONTEXT(ctx
)->Driver
.NotifyMaterialChange
= r200UpdateMaterial
;
2497 TNL_CONTEXT(ctx
)->Driver
.RunPipeline
= r200WrapRunPipeline
;