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
[RCOMP
],
725 ctx
->Color
.ColorMask
[GCOMP
],
726 ctx
->Color
.ColorMask
[BCOMP
],
727 ctx
->Color
.ColorMask
[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 r200PolygonStipple( GLcontext
*ctx
, const GLubyte
*mask
)
769 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
771 drm_radeon_stipple_t stipple
;
773 /* Must flip pattern upside down.
775 for ( i
= 0 ; i
< 32 ; i
++ ) {
776 rmesa
->state
.stipple
.mask
[31 - i
] = ((GLuint
*) mask
)[i
];
779 /* TODO: push this into cmd mechanism
781 radeon_firevertices(&rmesa
->radeon
);
782 LOCK_HARDWARE( &rmesa
->radeon
);
784 /* FIXME: Use window x,y offsets into stipple RAM.
786 stipple
.mask
= rmesa
->state
.stipple
.mask
;
787 drmCommandWrite( rmesa
->radeon
.dri
.fd
, DRM_RADEON_STIPPLE
,
788 &stipple
, sizeof(stipple
) );
789 UNLOCK_HARDWARE( &rmesa
->radeon
);
792 static void r200PolygonMode( GLcontext
*ctx
, GLenum face
, GLenum mode
)
794 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
795 GLboolean flag
= (ctx
->_TriangleCaps
& DD_TRI_UNFILLED
) != 0;
797 /* Can't generally do unfilled via tcl, but some good special
800 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_UNFILLED
, flag
);
801 if (rmesa
->radeon
.TclFallback
) {
802 r200ChooseRenderState( ctx
);
803 r200ChooseVertexState( ctx
);
808 /* =============================================================
809 * Rendering attributes
811 * We really don't want to recalculate all this every time we bind a
812 * texture. These things shouldn't change all that often, so it makes
813 * sense to break them out of the core texture state update routines.
816 /* Examine lighting and texture state to determine if separate specular
819 static void r200UpdateSpecular( GLcontext
*ctx
)
821 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
822 uint32_t p
= rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
];
824 R200_STATECHANGE( rmesa
, tcl
);
825 R200_STATECHANGE( rmesa
, vtx
);
827 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~(3<<R200_VTX_COLOR_0_SHIFT
);
828 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~(3<<R200_VTX_COLOR_1_SHIFT
);
829 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_COLOR_0
;
830 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_COLOR_1
;
831 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LIGHTING_ENABLE
;
833 p
&= ~R200_SPECULAR_ENABLE
;
835 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_DIFFUSE_SPECULAR_COMBINE
;
838 if (ctx
->Light
.Enabled
&&
839 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
) {
840 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
841 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
) |
842 (R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
843 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_0
;
844 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_1
;
845 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHTING_ENABLE
;
846 p
|= R200_SPECULAR_ENABLE
;
847 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &=
848 ~R200_DIFFUSE_SPECULAR_COMBINE
;
850 else if (ctx
->Light
.Enabled
) {
851 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
852 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
));
853 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_0
;
854 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHTING_ENABLE
;
855 } else if (ctx
->Fog
.ColorSumEnabled
) {
856 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
857 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
) |
858 (R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
859 p
|= R200_SPECULAR_ENABLE
;
861 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
862 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
));
865 if (ctx
->Fog
.Enabled
) {
866 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
867 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
868 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_1
;
871 if ( rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] != p
) {
872 R200_STATECHANGE( rmesa
, ctx
);
873 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] = p
;
876 /* Update vertex/render formats
878 if (rmesa
->radeon
.TclFallback
) {
879 r200ChooseRenderState( ctx
);
880 r200ChooseVertexState( ctx
);
885 /* =============================================================
890 /* Update on colormaterial, material emmissive/ambient,
891 * lightmodel.globalambient
893 static void update_global_ambient( GLcontext
*ctx
)
895 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
896 float *fcmd
= (float *)R200_DB_STATE( glt
);
898 /* Need to do more if both emmissive & ambient are PREMULT:
899 * I believe this is not nessary when using source_material. This condition thus
900 * will never happen currently, and the function has no dependencies on materials now
902 if ((rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
] &
903 ((3 << R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
904 (3 << R200_FRONT_AMBIENT_SOURCE_SHIFT
))) == 0)
906 COPY_3V( &fcmd
[GLT_RED
],
907 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_EMISSION
]);
908 ACC_SCALE_3V( &fcmd
[GLT_RED
],
909 ctx
->Light
.Model
.Ambient
,
910 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_AMBIENT
]);
914 COPY_3V( &fcmd
[GLT_RED
], ctx
->Light
.Model
.Ambient
);
917 R200_DB_STATECHANGE(rmesa
, &rmesa
->hw
.glt
);
920 /* Update on change to
924 static void update_light_colors( GLcontext
*ctx
, GLuint p
)
926 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
928 /* fprintf(stderr, "%s\n", __FUNCTION__); */
931 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
932 float *fcmd
= (float *)R200_DB_STATE( lit
[p
] );
934 COPY_4V( &fcmd
[LIT_AMBIENT_RED
], l
->Ambient
);
935 COPY_4V( &fcmd
[LIT_DIFFUSE_RED
], l
->Diffuse
);
936 COPY_4V( &fcmd
[LIT_SPECULAR_RED
], l
->Specular
);
938 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
942 static void r200ColorMaterial( GLcontext
*ctx
, GLenum face
, GLenum mode
)
944 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
945 GLuint light_model_ctl1
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
];
946 light_model_ctl1
&= ~((0xf << R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
947 (0xf << R200_FRONT_AMBIENT_SOURCE_SHIFT
) |
948 (0xf << R200_FRONT_DIFFUSE_SOURCE_SHIFT
) |
949 (0xf << R200_FRONT_SPECULAR_SOURCE_SHIFT
) |
950 (0xf << R200_BACK_EMISSIVE_SOURCE_SHIFT
) |
951 (0xf << R200_BACK_AMBIENT_SOURCE_SHIFT
) |
952 (0xf << R200_BACK_DIFFUSE_SOURCE_SHIFT
) |
953 (0xf << R200_BACK_SPECULAR_SOURCE_SHIFT
));
955 if (ctx
->Light
.ColorMaterialEnabled
) {
956 GLuint mask
= ctx
->Light
.ColorMaterialBitmask
;
958 if (mask
& MAT_BIT_FRONT_EMISSION
) {
959 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
960 R200_FRONT_EMISSIVE_SOURCE_SHIFT
);
963 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
964 R200_FRONT_EMISSIVE_SOURCE_SHIFT
);
966 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
967 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
968 R200_FRONT_AMBIENT_SOURCE_SHIFT
);
971 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
972 R200_FRONT_AMBIENT_SOURCE_SHIFT
);
974 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
975 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
976 R200_FRONT_DIFFUSE_SOURCE_SHIFT
);
979 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
980 R200_FRONT_DIFFUSE_SOURCE_SHIFT
);
982 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
983 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
984 R200_FRONT_SPECULAR_SOURCE_SHIFT
);
987 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
988 R200_FRONT_SPECULAR_SOURCE_SHIFT
);
991 if (mask
& MAT_BIT_BACK_EMISSION
) {
992 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
993 R200_BACK_EMISSIVE_SOURCE_SHIFT
);
996 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
997 R200_BACK_EMISSIVE_SOURCE_SHIFT
);
999 if (mask
& MAT_BIT_BACK_AMBIENT
) {
1000 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
1001 R200_BACK_AMBIENT_SOURCE_SHIFT
);
1003 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
1004 R200_BACK_AMBIENT_SOURCE_SHIFT
);
1006 if (mask
& MAT_BIT_BACK_DIFFUSE
) {
1007 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
1008 R200_BACK_DIFFUSE_SOURCE_SHIFT
);
1010 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
1011 R200_BACK_DIFFUSE_SOURCE_SHIFT
);
1013 if (mask
& MAT_BIT_BACK_SPECULAR
) {
1014 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
1015 R200_BACK_SPECULAR_SOURCE_SHIFT
);
1018 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
1019 R200_BACK_SPECULAR_SOURCE_SHIFT
);
1023 /* Default to SOURCE_MATERIAL:
1026 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
1027 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_AMBIENT_SOURCE_SHIFT
) |
1028 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_DIFFUSE_SOURCE_SHIFT
) |
1029 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_SPECULAR_SOURCE_SHIFT
) |
1030 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_EMISSIVE_SOURCE_SHIFT
) |
1031 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_AMBIENT_SOURCE_SHIFT
) |
1032 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_DIFFUSE_SOURCE_SHIFT
) |
1033 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_SPECULAR_SOURCE_SHIFT
);
1036 if (light_model_ctl1
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
]) {
1037 R200_STATECHANGE( rmesa
, tcl
);
1038 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
] = light_model_ctl1
;
1044 void r200UpdateMaterial( GLcontext
*ctx
)
1046 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1047 GLfloat (*mat
)[4] = ctx
->Light
.Material
.Attrib
;
1048 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( mtl
[0] );
1049 GLfloat
*fcmd2
= (GLfloat
*)R200_DB_STATE( mtl
[1] );
1052 /* Might be possible and faster to update everything unconditionally? */
1053 if (ctx
->Light
.ColorMaterialEnabled
)
1054 mask
&= ~ctx
->Light
.ColorMaterialBitmask
;
1056 if (R200_DEBUG
& DEBUG_STATE
)
1057 fprintf(stderr
, "%s\n", __FUNCTION__
);
1059 if (mask
& MAT_BIT_FRONT_EMISSION
) {
1060 fcmd
[MTL_EMMISSIVE_RED
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][0];
1061 fcmd
[MTL_EMMISSIVE_GREEN
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][1];
1062 fcmd
[MTL_EMMISSIVE_BLUE
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][2];
1063 fcmd
[MTL_EMMISSIVE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][3];
1065 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
1066 fcmd
[MTL_AMBIENT_RED
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][0];
1067 fcmd
[MTL_AMBIENT_GREEN
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][1];
1068 fcmd
[MTL_AMBIENT_BLUE
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][2];
1069 fcmd
[MTL_AMBIENT_ALPHA
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][3];
1071 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
1072 fcmd
[MTL_DIFFUSE_RED
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][0];
1073 fcmd
[MTL_DIFFUSE_GREEN
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][1];
1074 fcmd
[MTL_DIFFUSE_BLUE
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][2];
1075 fcmd
[MTL_DIFFUSE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][3];
1077 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
1078 fcmd
[MTL_SPECULAR_RED
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][0];
1079 fcmd
[MTL_SPECULAR_GREEN
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][1];
1080 fcmd
[MTL_SPECULAR_BLUE
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][2];
1081 fcmd
[MTL_SPECULAR_ALPHA
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][3];
1083 if (mask
& MAT_BIT_FRONT_SHININESS
) {
1084 fcmd
[MTL_SHININESS
] = mat
[MAT_ATTRIB_FRONT_SHININESS
][0];
1087 if (mask
& MAT_BIT_BACK_EMISSION
) {
1088 fcmd2
[MTL_EMMISSIVE_RED
] = mat
[MAT_ATTRIB_BACK_EMISSION
][0];
1089 fcmd2
[MTL_EMMISSIVE_GREEN
] = mat
[MAT_ATTRIB_BACK_EMISSION
][1];
1090 fcmd2
[MTL_EMMISSIVE_BLUE
] = mat
[MAT_ATTRIB_BACK_EMISSION
][2];
1091 fcmd2
[MTL_EMMISSIVE_ALPHA
] = mat
[MAT_ATTRIB_BACK_EMISSION
][3];
1093 if (mask
& MAT_BIT_BACK_AMBIENT
) {
1094 fcmd2
[MTL_AMBIENT_RED
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][0];
1095 fcmd2
[MTL_AMBIENT_GREEN
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][1];
1096 fcmd2
[MTL_AMBIENT_BLUE
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][2];
1097 fcmd2
[MTL_AMBIENT_ALPHA
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][3];
1099 if (mask
& MAT_BIT_BACK_DIFFUSE
) {
1100 fcmd2
[MTL_DIFFUSE_RED
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][0];
1101 fcmd2
[MTL_DIFFUSE_GREEN
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][1];
1102 fcmd2
[MTL_DIFFUSE_BLUE
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][2];
1103 fcmd2
[MTL_DIFFUSE_ALPHA
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][3];
1105 if (mask
& MAT_BIT_BACK_SPECULAR
) {
1106 fcmd2
[MTL_SPECULAR_RED
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][0];
1107 fcmd2
[MTL_SPECULAR_GREEN
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][1];
1108 fcmd2
[MTL_SPECULAR_BLUE
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][2];
1109 fcmd2
[MTL_SPECULAR_ALPHA
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][3];
1111 if (mask
& MAT_BIT_BACK_SHININESS
) {
1112 fcmd2
[MTL_SHININESS
] = mat
[MAT_ATTRIB_BACK_SHININESS
][0];
1115 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mtl
[0] );
1116 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mtl
[1] );
1118 /* currently material changes cannot trigger a global ambient change, I believe this is correct
1119 update_global_ambient( ctx ); */
1124 * _MESA_NEW_NEED_EYE_COORDS
1126 * Uses derived state from mesa:
1130 * _NormSpotDirection
1131 * _ModelViewInvScale
1135 * which are calculated in light.c and are correct for the current
1136 * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
1137 * and _MESA_NEW_NEED_EYE_COORDS.
1139 static void update_light( GLcontext
*ctx
)
1141 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1143 /* Have to check these, or have an automatic shortcircuit mechanism
1144 * to remove noop statechanges. (Or just do a better job on the
1148 GLuint tmp
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
];
1150 if (ctx
->_NeedEyeCoords
)
1151 tmp
&= ~R200_LIGHT_IN_MODELSPACE
;
1153 tmp
|= R200_LIGHT_IN_MODELSPACE
;
1155 if (tmp
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
])
1157 R200_STATECHANGE( rmesa
, tcl
);
1158 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] = tmp
;
1163 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( eye
);
1164 fcmd
[EYE_X
] = ctx
->_EyeZDir
[0];
1165 fcmd
[EYE_Y
] = ctx
->_EyeZDir
[1];
1166 fcmd
[EYE_Z
] = - ctx
->_EyeZDir
[2];
1167 fcmd
[EYE_RESCALE_FACTOR
] = ctx
->_ModelViewInvScale
;
1168 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.eye
);
1173 if (ctx
->Light
.Enabled
) {
1175 for (p
= 0 ; p
< MAX_LIGHTS
; p
++) {
1176 if (ctx
->Light
.Light
[p
].Enabled
) {
1177 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1178 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( lit
[p
] );
1180 if (l
->EyePosition
[3] == 0.0) {
1181 COPY_3FV( &fcmd
[LIT_POSITION_X
], l
->_VP_inf_norm
);
1182 COPY_3FV( &fcmd
[LIT_DIRECTION_X
], l
->_h_inf_norm
);
1183 fcmd
[LIT_POSITION_W
] = 0;
1184 fcmd
[LIT_DIRECTION_W
] = 0;
1186 COPY_4V( &fcmd
[LIT_POSITION_X
], l
->_Position
);
1187 fcmd
[LIT_DIRECTION_X
] = -l
->_NormSpotDirection
[0];
1188 fcmd
[LIT_DIRECTION_Y
] = -l
->_NormSpotDirection
[1];
1189 fcmd
[LIT_DIRECTION_Z
] = -l
->_NormSpotDirection
[2];
1190 fcmd
[LIT_DIRECTION_W
] = 0;
1193 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
1199 static void r200Lightfv( GLcontext
*ctx
, GLenum light
,
1200 GLenum pname
, const GLfloat
*params
)
1202 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1203 GLint p
= light
- GL_LIGHT0
;
1204 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1205 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.lit
[p
].cmd
;
1212 update_light_colors( ctx
, p
);
1215 case GL_SPOT_DIRECTION
:
1216 /* picked up in update_light */
1220 /* positions picked up in update_light, but can do flag here */
1221 GLuint flag
= (p
&1)? R200_LIGHT_1_IS_LOCAL
: R200_LIGHT_0_IS_LOCAL
;
1222 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1224 R200_STATECHANGE(rmesa
, tcl
);
1225 if (l
->EyePosition
[3] != 0.0F
)
1226 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1228 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1232 case GL_SPOT_EXPONENT
:
1233 R200_STATECHANGE(rmesa
, lit
[p
]);
1234 fcmd
[LIT_SPOT_EXPONENT
] = params
[0];
1237 case GL_SPOT_CUTOFF
: {
1238 GLuint flag
= (p
&1) ? R200_LIGHT_1_IS_SPOT
: R200_LIGHT_0_IS_SPOT
;
1239 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1241 R200_STATECHANGE(rmesa
, lit
[p
]);
1242 fcmd
[LIT_SPOT_CUTOFF
] = l
->_CosCutoff
;
1244 R200_STATECHANGE(rmesa
, tcl
);
1245 if (l
->SpotCutoff
!= 180.0F
)
1246 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1248 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1253 case GL_CONSTANT_ATTENUATION
:
1254 R200_STATECHANGE(rmesa
, lit
[p
]);
1255 fcmd
[LIT_ATTEN_CONST
] = params
[0];
1256 if ( params
[0] == 0.0 )
1257 fcmd
[LIT_ATTEN_CONST_INV
] = FLT_MAX
;
1259 fcmd
[LIT_ATTEN_CONST_INV
] = 1.0 / params
[0];
1261 case GL_LINEAR_ATTENUATION
:
1262 R200_STATECHANGE(rmesa
, lit
[p
]);
1263 fcmd
[LIT_ATTEN_LINEAR
] = params
[0];
1265 case GL_QUADRATIC_ATTENUATION
:
1266 R200_STATECHANGE(rmesa
, lit
[p
]);
1267 fcmd
[LIT_ATTEN_QUADRATIC
] = params
[0];
1273 /* Set RANGE_ATTEN only when needed */
1276 case GL_CONSTANT_ATTENUATION
:
1277 case GL_LINEAR_ATTENUATION
:
1278 case GL_QUADRATIC_ATTENUATION
: {
1279 GLuint
*icmd
= (GLuint
*)R200_DB_STATE( tcl
);
1280 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1281 GLuint atten_flag
= ( p
&1 ) ? R200_LIGHT_1_ENABLE_RANGE_ATTEN
1282 : R200_LIGHT_0_ENABLE_RANGE_ATTEN
;
1283 GLuint atten_const_flag
= ( p
&1 ) ? R200_LIGHT_1_CONSTANT_RANGE_ATTEN
1284 : R200_LIGHT_0_CONSTANT_RANGE_ATTEN
;
1286 if ( l
->EyePosition
[3] == 0.0F
||
1287 ( ( fcmd
[LIT_ATTEN_CONST
] == 0.0 || fcmd
[LIT_ATTEN_CONST
] == 1.0 ) &&
1288 fcmd
[LIT_ATTEN_QUADRATIC
] == 0.0 && fcmd
[LIT_ATTEN_LINEAR
] == 0.0 ) ) {
1289 /* Disable attenuation */
1290 icmd
[idx
] &= ~atten_flag
;
1292 if ( fcmd
[LIT_ATTEN_QUADRATIC
] == 0.0 && fcmd
[LIT_ATTEN_LINEAR
] == 0.0 ) {
1293 /* Enable only constant portion of attenuation calculation */
1294 icmd
[idx
] |= ( atten_flag
| atten_const_flag
);
1296 /* Enable full attenuation calculation */
1297 icmd
[idx
] &= ~atten_const_flag
;
1298 icmd
[idx
] |= atten_flag
;
1302 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.tcl
);
1310 static void r200UpdateLocalViewer ( GLcontext
*ctx
)
1312 /* It looks like for the texgen modes GL_SPHERE_MAP, GL_NORMAL_MAP and
1313 GL_REFLECTION_MAP we need R200_LOCAL_VIEWER set (fglrx does exactly that
1314 for these and only these modes). This means specular highlights may turn out
1315 wrong in some cases when lighting is enabled but GL_LIGHT_MODEL_LOCAL_VIEWER
1316 is not set, though it seems to happen rarely and the effect seems quite
1317 subtle. May need TCL fallback to fix it completely, though I'm not sure
1318 how you'd identify the cases where the specular highlights indeed will
1319 be wrong. Don't know if fglrx does something special in that case.
1321 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1322 R200_STATECHANGE( rmesa
, tcl
);
1323 if (ctx
->Light
.Model
.LocalViewer
||
1324 ctx
->Texture
._GenFlags
& TEXGEN_NEED_NORMALS
)
1325 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LOCAL_VIEWER
;
1327 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LOCAL_VIEWER
;
1330 static void r200LightModelfv( GLcontext
*ctx
, GLenum pname
,
1331 const GLfloat
*param
)
1333 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1336 case GL_LIGHT_MODEL_AMBIENT
:
1337 update_global_ambient( ctx
);
1340 case GL_LIGHT_MODEL_LOCAL_VIEWER
:
1341 r200UpdateLocalViewer( ctx
);
1344 case GL_LIGHT_MODEL_TWO_SIDE
:
1345 R200_STATECHANGE( rmesa
, tcl
);
1346 if (ctx
->Light
.Model
.TwoSide
)
1347 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHT_TWOSIDE
;
1349 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~(R200_LIGHT_TWOSIDE
);
1350 if (rmesa
->radeon
.TclFallback
) {
1351 r200ChooseRenderState( ctx
);
1352 r200ChooseVertexState( ctx
);
1356 case GL_LIGHT_MODEL_COLOR_CONTROL
:
1357 r200UpdateSpecular(ctx
);
1365 static void r200ShadeModel( GLcontext
*ctx
, GLenum mode
)
1367 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1368 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
1370 s
&= ~(R200_DIFFUSE_SHADE_MASK
|
1371 R200_ALPHA_SHADE_MASK
|
1372 R200_SPECULAR_SHADE_MASK
|
1373 R200_FOG_SHADE_MASK
|
1374 R200_DISC_FOG_SHADE_MASK
);
1378 s
|= (R200_DIFFUSE_SHADE_FLAT
|
1379 R200_ALPHA_SHADE_FLAT
|
1380 R200_SPECULAR_SHADE_FLAT
|
1381 R200_FOG_SHADE_FLAT
|
1382 R200_DISC_FOG_SHADE_FLAT
);
1385 s
|= (R200_DIFFUSE_SHADE_GOURAUD
|
1386 R200_ALPHA_SHADE_GOURAUD
|
1387 R200_SPECULAR_SHADE_GOURAUD
|
1388 R200_FOG_SHADE_GOURAUD
|
1389 R200_DISC_FOG_SHADE_GOURAUD
);
1395 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
1396 R200_STATECHANGE( rmesa
, set
);
1397 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
1402 /* =============================================================
1406 static void r200ClipPlane( GLcontext
*ctx
, GLenum plane
, const GLfloat
*eq
)
1408 GLint p
= (GLint
) plane
- (GLint
) GL_CLIP_PLANE0
;
1409 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1410 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1412 R200_STATECHANGE( rmesa
, ucp
[p
] );
1413 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1414 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1415 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1416 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1419 static void r200UpdateClipPlanes( GLcontext
*ctx
)
1421 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1424 for (p
= 0; p
< ctx
->Const
.MaxClipPlanes
; p
++) {
1425 if (ctx
->Transform
.ClipPlanesEnabled
& (1 << p
)) {
1426 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1428 R200_STATECHANGE( rmesa
, ucp
[p
] );
1429 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1430 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1431 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1432 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1438 /* =============================================================
1443 r200StencilFuncSeparate( GLcontext
*ctx
, GLenum face
, GLenum func
,
1444 GLint ref
, GLuint mask
)
1446 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1447 GLuint refmask
= (((ctx
->Stencil
.Ref
[0] & 0xff) << R200_STENCIL_REF_SHIFT
) |
1448 ((ctx
->Stencil
.ValueMask
[0] & 0xff) << R200_STENCIL_MASK_SHIFT
));
1450 R200_STATECHANGE( rmesa
, ctx
);
1451 R200_STATECHANGE( rmesa
, msk
);
1453 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_STENCIL_TEST_MASK
;
1454 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~(R200_STENCIL_REF_MASK
|
1455 R200_STENCIL_VALUE_MASK
);
1457 switch ( ctx
->Stencil
.Function
[0] ) {
1459 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEVER
;
1462 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LESS
;
1465 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_EQUAL
;
1468 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LEQUAL
;
1471 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GREATER
;
1474 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEQUAL
;
1477 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GEQUAL
;
1480 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_ALWAYS
;
1484 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |= refmask
;
1488 r200StencilMaskSeparate( GLcontext
*ctx
, GLenum face
, GLuint mask
)
1490 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1492 R200_STATECHANGE( rmesa
, msk
);
1493 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~R200_STENCIL_WRITE_MASK
;
1494 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |=
1495 ((ctx
->Stencil
.WriteMask
[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT
);
1499 r200StencilOpSeparate( GLcontext
*ctx
, GLenum face
, GLenum fail
,
1500 GLenum zfail
, GLenum zpass
)
1502 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1504 R200_STATECHANGE( rmesa
, ctx
);
1505 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~(R200_STENCIL_FAIL_MASK
|
1506 R200_STENCIL_ZFAIL_MASK
|
1507 R200_STENCIL_ZPASS_MASK
);
1509 switch ( ctx
->Stencil
.FailFunc
[0] ) {
1511 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_KEEP
;
1514 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_ZERO
;
1517 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_REPLACE
;
1520 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC
;
1523 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC
;
1525 case GL_INCR_WRAP_EXT
:
1526 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC_WRAP
;
1528 case GL_DECR_WRAP_EXT
:
1529 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC_WRAP
;
1532 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INVERT
;
1536 switch ( ctx
->Stencil
.ZFailFunc
[0] ) {
1538 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_KEEP
;
1541 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_ZERO
;
1544 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_REPLACE
;
1547 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC
;
1550 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC
;
1552 case GL_INCR_WRAP_EXT
:
1553 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC_WRAP
;
1555 case GL_DECR_WRAP_EXT
:
1556 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC_WRAP
;
1559 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INVERT
;
1563 switch ( ctx
->Stencil
.ZPassFunc
[0] ) {
1565 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_KEEP
;
1568 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_ZERO
;
1571 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_REPLACE
;
1574 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC
;
1577 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC
;
1579 case GL_INCR_WRAP_EXT
:
1580 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC_WRAP
;
1582 case GL_DECR_WRAP_EXT
:
1583 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC_WRAP
;
1586 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INVERT
;
1591 static void r200ClearStencil( GLcontext
*ctx
, GLint s
)
1593 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1595 rmesa
->radeon
.state
.stencil
.clear
=
1596 ((GLuint
) (ctx
->Stencil
.Clear
& 0xff) |
1597 (0xff << R200_STENCIL_MASK_SHIFT
) |
1598 ((ctx
->Stencil
.WriteMask
[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT
));
1602 /* =============================================================
1603 * Window position and viewport transformation
1607 * To correctly position primitives:
1609 #define SUBPIXEL_X 0.125
1610 #define SUBPIXEL_Y 0.125
1614 * Called when window size or position changes or viewport or depth range
1615 * state is changed. We update the hardware viewport state here.
1617 void r200UpdateWindow( GLcontext
*ctx
)
1619 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1620 __DRIdrawablePrivate
*dPriv
= radeon_get_drawable(&rmesa
->radeon
);
1621 GLfloat xoffset
= dPriv
? (GLfloat
) dPriv
->x
: 0;
1622 GLfloat yoffset
= dPriv
? (GLfloat
) dPriv
->y
+ dPriv
->h
: 0;
1623 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1624 const GLboolean render_to_fbo
= (ctx
->DrawBuffer
? (ctx
->DrawBuffer
->Name
!= 0) : 0);
1625 const GLfloat depthScale
= 1.0F
/ ctx
->DrawBuffer
->_DepthMaxF
;
1626 GLfloat y_scale
, y_bias
;
1628 if (render_to_fbo
) {
1636 float_ui32_type sx
= { v
[MAT_SX
] };
1637 float_ui32_type tx
= { v
[MAT_TX
] + xoffset
+ SUBPIXEL_X
};
1638 float_ui32_type sy
= { v
[MAT_SY
] * y_scale
};
1639 float_ui32_type ty
= { (v
[MAT_TY
] * y_scale
) + y_bias
+ SUBPIXEL_Y
};
1640 float_ui32_type sz
= { v
[MAT_SZ
] * depthScale
};
1641 float_ui32_type tz
= { v
[MAT_TZ
] * depthScale
};
1643 R200_STATECHANGE( rmesa
, vpt
);
1645 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XSCALE
] = sx
.ui32
;
1646 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = tx
.ui32
;
1647 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YSCALE
] = sy
.ui32
;
1648 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = ty
.ui32
;
1649 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZSCALE
] = sz
.ui32
;
1650 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZOFFSET
] = tz
.ui32
;
1655 static void r200Viewport( GLcontext
*ctx
, GLint x
, GLint y
,
1656 GLsizei width
, GLsizei height
)
1658 /* Don't pipeline viewport changes, conflict with window offset
1659 * setting below. Could apply deltas to rescue pipelined viewport
1660 * values, or keep the originals hanging around.
1662 r200UpdateWindow( ctx
);
1664 radeon_viewport(ctx
, x
, y
, width
, height
);
1667 static void r200DepthRange( GLcontext
*ctx
, GLclampd nearval
,
1670 r200UpdateWindow( ctx
);
1673 void r200UpdateViewportOffset( GLcontext
*ctx
)
1675 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1676 __DRIdrawablePrivate
*dPriv
= radeon_get_drawable(&rmesa
->radeon
);
1677 GLfloat xoffset
= (GLfloat
)dPriv
->x
;
1678 GLfloat yoffset
= (GLfloat
)dPriv
->y
+ dPriv
->h
;
1679 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1684 tx
.f
= v
[MAT_TX
] + xoffset
+ SUBPIXEL_X
;
1685 ty
.f
= (- v
[MAT_TY
]) + yoffset
+ SUBPIXEL_Y
;
1687 if ( rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] != tx
.ui32
||
1688 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] != ty
.ui32
)
1690 /* Note: this should also modify whatever data the context reset
1693 R200_STATECHANGE( rmesa
, vpt
);
1694 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = tx
.ui32
;
1695 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = ty
.ui32
;
1697 /* update polygon stipple x/y screen offset */
1700 GLuint m
= rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
];
1702 m
&= ~(R200_STIPPLE_X_OFFSET_MASK
|
1703 R200_STIPPLE_Y_OFFSET_MASK
);
1705 /* add magic offsets, then invert */
1706 stx
= 31 - ((dPriv
->x
- 1) & R200_STIPPLE_COORD_MASK
);
1707 sty
= 31 - ((dPriv
->y
+ dPriv
->h
- 1)
1708 & R200_STIPPLE_COORD_MASK
);
1710 m
|= ((stx
<< R200_STIPPLE_X_OFFSET_SHIFT
) |
1711 (sty
<< R200_STIPPLE_Y_OFFSET_SHIFT
));
1713 if ( rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] != m
) {
1714 R200_STATECHANGE( rmesa
, msc
);
1715 rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] = m
;
1720 radeonUpdateScissor( ctx
);
1725 /* =============================================================
1729 static void r200ClearColor( GLcontext
*ctx
, const GLfloat c
[4] )
1731 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1733 struct radeon_renderbuffer
*rrb
;
1735 rrb
= radeon_get_colorbuffer(&rmesa
->radeon
);
1738 CLAMPED_FLOAT_TO_UBYTE(color
[0], c
[0]);
1739 CLAMPED_FLOAT_TO_UBYTE(color
[1], c
[1]);
1740 CLAMPED_FLOAT_TO_UBYTE(color
[2], c
[2]);
1741 CLAMPED_FLOAT_TO_UBYTE(color
[3], c
[3]);
1742 rmesa
->radeon
.state
.color
.clear
= radeonPackColor( rrb
->cpp
,
1744 color
[2], color
[3] );
1748 static void r200RenderMode( GLcontext
*ctx
, GLenum mode
)
1750 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1751 FALLBACK( rmesa
, R200_FALLBACK_RENDER_MODE
, (mode
!= GL_RENDER
) );
1755 static GLuint r200_rop_tab
[] = {
1758 R200_ROP_AND_REVERSE
,
1760 R200_ROP_AND_INVERTED
,
1767 R200_ROP_OR_REVERSE
,
1768 R200_ROP_COPY_INVERTED
,
1769 R200_ROP_OR_INVERTED
,
1774 static void r200LogicOpCode( GLcontext
*ctx
, GLenum opcode
)
1776 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1777 GLuint rop
= (GLuint
)opcode
- GL_CLEAR
;
1781 R200_STATECHANGE( rmesa
, msk
);
1782 rmesa
->hw
.msk
.cmd
[MSK_RB3D_ROPCNTL
] = r200_rop_tab
[rop
];
1785 /* =============================================================
1786 * State enable/disable
1789 static void r200Enable( GLcontext
*ctx
, GLenum cap
, GLboolean state
)
1791 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1794 if ( R200_DEBUG
& DEBUG_STATE
)
1795 fprintf( stderr
, "%s( %s = %s )\n", __FUNCTION__
,
1796 _mesa_lookup_enum_by_nr( cap
),
1797 state
? "GL_TRUE" : "GL_FALSE" );
1800 /* Fast track this one...
1808 R200_STATECHANGE( rmesa
, ctx
);
1810 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ALPHA_TEST_ENABLE
;
1812 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ALPHA_TEST_ENABLE
;
1817 case GL_COLOR_LOGIC_OP
:
1818 r200_set_blend_state( ctx
);
1821 case GL_CLIP_PLANE0
:
1822 case GL_CLIP_PLANE1
:
1823 case GL_CLIP_PLANE2
:
1824 case GL_CLIP_PLANE3
:
1825 case GL_CLIP_PLANE4
:
1826 case GL_CLIP_PLANE5
:
1827 p
= cap
-GL_CLIP_PLANE0
;
1828 R200_STATECHANGE( rmesa
, tcl
);
1830 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= (R200_UCP_ENABLE_0
<<p
);
1831 r200ClipPlane( ctx
, cap
, NULL
);
1834 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~(R200_UCP_ENABLE_0
<<p
);
1838 case GL_COLOR_MATERIAL
:
1839 r200ColorMaterial( ctx
, 0, 0 );
1840 r200UpdateMaterial( ctx
);
1844 r200CullFace( ctx
, 0 );
1848 R200_STATECHANGE(rmesa
, ctx
);
1850 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_Z_ENABLE
;
1852 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_Z_ENABLE
;
1857 R200_STATECHANGE(rmesa
, ctx
);
1859 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_DITHER_ENABLE
;
1860 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~rmesa
->radeon
.state
.color
.roundEnable
;
1862 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_DITHER_ENABLE
;
1863 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= rmesa
->radeon
.state
.color
.roundEnable
;
1868 R200_STATECHANGE(rmesa
, ctx
);
1870 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_FOG_ENABLE
;
1871 r200Fogfv( ctx
, GL_FOG_MODE
, NULL
);
1873 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_FOG_ENABLE
;
1874 R200_STATECHANGE(rmesa
, tcl
);
1875 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_TCL_FOG_MASK
;
1877 r200UpdateSpecular( ctx
); /* for PK_SPEC */
1878 if (rmesa
->radeon
.TclFallback
)
1879 r200ChooseVertexState( ctx
);
1880 _mesa_allow_light_in_model( ctx
, !state
);
1891 R200_STATECHANGE(rmesa
, tcl
);
1892 p
= cap
- GL_LIGHT0
;
1894 flag
= (R200_LIGHT_1_ENABLE
|
1895 R200_LIGHT_1_ENABLE_AMBIENT
|
1896 R200_LIGHT_1_ENABLE_SPECULAR
);
1898 flag
= (R200_LIGHT_0_ENABLE
|
1899 R200_LIGHT_0_ENABLE_AMBIENT
|
1900 R200_LIGHT_0_ENABLE_SPECULAR
);
1903 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] |= flag
;
1905 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] &= ~flag
;
1909 update_light_colors( ctx
, p
);
1913 r200UpdateSpecular(ctx
);
1914 /* for reflection map fixup - might set recheck_texgen for all units too */
1915 rmesa
->radeon
.NewGLState
|= _NEW_TEXTURE
;
1918 case GL_LINE_SMOOTH
:
1919 R200_STATECHANGE( rmesa
, ctx
);
1921 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_LINE
;
1923 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_LINE
;
1927 case GL_LINE_STIPPLE
:
1928 R200_STATECHANGE( rmesa
, set
);
1930 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_PATTERN_ENABLE
;
1932 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_PATTERN_ENABLE
;
1937 R200_STATECHANGE( rmesa
, tcl
);
1939 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_NORMALIZE_NORMALS
;
1941 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_NORMALIZE_NORMALS
;
1945 /* Pointsize registers on r200 only work for point sprites, and point smooth
1946 * doesn't work for point sprites (and isn't needed for 1.0 sized aa points).
1947 * In any case, setting pointmin == pointsizemax == 1.0 for aa points
1948 * is enough to satisfy conform.
1950 case GL_POINT_SMOOTH
:
1953 /* These don't really do anything, as we don't use the 3vtx
1957 case GL_POLYGON_OFFSET_POINT
:
1958 R200_STATECHANGE( rmesa
, set
);
1960 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_POINT
;
1962 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_POINT
;
1966 case GL_POLYGON_OFFSET_LINE
:
1967 R200_STATECHANGE( rmesa
, set
);
1969 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_LINE
;
1971 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_LINE
;
1976 case GL_POINT_SPRITE_ARB
:
1977 R200_STATECHANGE( rmesa
, spr
);
1980 for (i
= 0; i
< 6; i
++) {
1981 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |=
1982 ctx
->Point
.CoordReplace
[i
] << (R200_PS_GEN_TEX_0_SHIFT
+ i
);
1985 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] &= ~R200_PS_GEN_TEX_MASK
;
1989 case GL_POLYGON_OFFSET_FILL
:
1990 R200_STATECHANGE( rmesa
, set
);
1992 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_TRI
;
1994 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_TRI
;
1998 case GL_POLYGON_SMOOTH
:
1999 R200_STATECHANGE( rmesa
, ctx
);
2001 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_POLY
;
2003 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_POLY
;
2007 case GL_POLYGON_STIPPLE
:
2008 R200_STATECHANGE(rmesa
, set
);
2010 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_STIPPLE_ENABLE
;
2012 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_STIPPLE_ENABLE
;
2016 case GL_RESCALE_NORMAL_EXT
: {
2017 GLboolean tmp
= ctx
->_NeedEyeCoords
? state
: !state
;
2018 R200_STATECHANGE( rmesa
, tcl
);
2020 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
2022 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
2027 case GL_SCISSOR_TEST
:
2028 radeon_firevertices(&rmesa
->radeon
);
2029 rmesa
->radeon
.state
.scissor
.enabled
= state
;
2030 radeonUpdateScissor( ctx
);
2033 case GL_STENCIL_TEST
:
2035 GLboolean hw_stencil
= GL_FALSE
;
2036 if (ctx
->DrawBuffer
) {
2037 struct radeon_renderbuffer
*rrbStencil
2038 = radeon_get_renderbuffer(ctx
->DrawBuffer
, BUFFER_STENCIL
);
2039 hw_stencil
= (rrbStencil
&& rrbStencil
->bo
);
2043 R200_STATECHANGE( rmesa
, ctx
);
2045 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_STENCIL_ENABLE
;
2047 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_STENCIL_ENABLE
;
2050 FALLBACK( rmesa
, R200_FALLBACK_STENCIL
, state
);
2055 case GL_TEXTURE_GEN_Q
:
2056 case GL_TEXTURE_GEN_R
:
2057 case GL_TEXTURE_GEN_S
:
2058 case GL_TEXTURE_GEN_T
:
2059 /* Picked up in r200UpdateTextureState.
2061 rmesa
->recheck_texgen
[ctx
->Texture
.CurrentUnit
] = GL_TRUE
;
2064 case GL_COLOR_SUM_EXT
:
2065 r200UpdateSpecular ( ctx
);
2068 case GL_VERTEX_PROGRAM_ARB
:
2071 rmesa
->curr_vp_hw
= NULL
;
2072 R200_STATECHANGE( rmesa
, vap
);
2073 rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
] &= ~R200_VAP_PROG_VTX_SHADER_ENABLE
;
2074 /* mark all tcl atoms (tcl vector state got overwritten) dirty
2075 not sure about tcl scalar state - we need at least grd
2076 with vert progs too.
2077 ucp looks like it doesn't get overwritten (may even work
2078 with vp for pos-invariant progs if we're lucky) */
2079 R200_STATECHANGE( rmesa
, mtl
[0] );
2080 R200_STATECHANGE( rmesa
, mtl
[1] );
2081 R200_STATECHANGE( rmesa
, fog
);
2082 R200_STATECHANGE( rmesa
, glt
);
2083 R200_STATECHANGE( rmesa
, eye
);
2084 for (i
= R200_MTX_MV
; i
<= R200_MTX_TEX5
; i
++) {
2085 R200_STATECHANGE( rmesa
, mat
[i
] );
2087 for (i
= 0 ; i
< 8; i
++) {
2088 R200_STATECHANGE( rmesa
, lit
[i
] );
2090 R200_STATECHANGE( rmesa
, tcl
);
2091 for (i
= 0; i
<= ctx
->Const
.MaxClipPlanes
; i
++) {
2092 if (ctx
->Transform
.ClipPlanesEnabled
& (1 << i
)) {
2093 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= (R200_UCP_ENABLE_0
<< i
);
2096 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0 << i);
2099 /* ugly. Need to call everything which might change compsel. */
2100 r200UpdateSpecular( ctx
);
2102 /* shouldn't be necessary, as it's picked up anyway in r200ValidateState (_NEW_PROGRAM),
2103 but without it doom3 locks up at always the same places. Why? */
2104 /* FIXME: This can (and should) be replaced by a call to the TCL_STATE_FLUSH reg before
2105 accessing VAP_SE_VAP_CNTL. Requires drm changes (done). Remove after some time... */
2106 r200UpdateTextureState( ctx
);
2107 /* if we call r200UpdateTextureState we need the code below because we are calling it with
2108 non-current derived enabled values which may revert the state atoms for frag progs even when
2109 they already got disabled... ugh
2110 Should really figure out why we need to call r200UpdateTextureState in the first place */
2112 for (unit
= 0; unit
< R200_MAX_TEXTURE_UNITS
; unit
++) {
2113 R200_STATECHANGE( rmesa
, pix
[unit
] );
2114 R200_STATECHANGE( rmesa
, tex
[unit
] );
2115 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] &=
2116 ~(R200_TXFORMAT_ST_ROUTE_MASK
| R200_TXFORMAT_LOOKUP_DISABLE
);
2117 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] |= unit
<< R200_TXFORMAT_ST_ROUTE_SHIFT
;
2118 /* need to guard this with drmSupportsFragmentShader? Should never get here if
2119 we don't announce ATI_fs, right? */
2120 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXMULTI_CTL
] = 0;
2122 R200_STATECHANGE( rmesa
, cst
);
2123 R200_STATECHANGE( rmesa
, tf
);
2124 rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] = 0;
2128 /* picked up later */
2130 /* call functions which change hw state based on ARB_vp enabled or not. */
2131 r200PointParameter( ctx
, GL_POINT_DISTANCE_ATTENUATION
, NULL
);
2132 r200Fogfv( ctx
, GL_FOG_COORD_SRC
, NULL
);
2135 case GL_VERTEX_PROGRAM_POINT_SIZE_ARB
:
2136 r200PointParameter( ctx
, GL_POINT_DISTANCE_ATTENUATION
, NULL
);
2139 case GL_FRAGMENT_SHADER_ATI
:
2141 /* restore normal tex env colors and make sure tex env combine will get updated
2142 mark env atoms dirty (as their data was overwritten by afs even
2143 if they didn't change) and restore tex coord routing */
2145 for (unit
= 0; unit
< R200_MAX_TEXTURE_UNITS
; unit
++) {
2146 R200_STATECHANGE( rmesa
, pix
[unit
] );
2147 R200_STATECHANGE( rmesa
, tex
[unit
] );
2148 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] &=
2149 ~(R200_TXFORMAT_ST_ROUTE_MASK
| R200_TXFORMAT_LOOKUP_DISABLE
);
2150 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] |= unit
<< R200_TXFORMAT_ST_ROUTE_SHIFT
;
2151 /* need to guard this with drmSupportsFragmentShader? Should never get here if
2152 we don't announce ATI_fs, right? */
2153 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXMULTI_CTL
] = 0;
2155 R200_STATECHANGE( rmesa
, cst
);
2156 R200_STATECHANGE( rmesa
, tf
);
2157 rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] = 0;
2160 /* need to mark this dirty as pix/tf atoms have overwritten the data
2161 even if the data in the atoms didn't change */
2162 R200_STATECHANGE( rmesa
, atf
);
2163 R200_STATECHANGE( rmesa
, afs
[1] );
2164 /* everything else picked up in r200UpdateTextureState hopefully */
2173 void r200LightingSpaceChange( GLcontext
*ctx
)
2175 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2178 if (R200_DEBUG
& DEBUG_STATE
)
2179 fprintf(stderr
, "%s %d BEFORE %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
2180 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
2182 if (ctx
->_NeedEyeCoords
)
2183 tmp
= ctx
->Transform
.RescaleNormals
;
2185 tmp
= !ctx
->Transform
.RescaleNormals
;
2187 R200_STATECHANGE( rmesa
, tcl
);
2189 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
2191 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
2194 if (R200_DEBUG
& DEBUG_STATE
)
2195 fprintf(stderr
, "%s %d AFTER %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
2196 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
2199 /* =============================================================
2200 * Deferred state management - matrices, textures, other?
2206 static void upload_matrix( r200ContextPtr rmesa
, GLfloat
*src
, int idx
)
2208 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
2212 for (i
= 0 ; i
< 4 ; i
++) {
2216 *dest
++ = src
[i
+12];
2219 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
2222 static void upload_matrix_t( r200ContextPtr rmesa
, const GLfloat
*src
, int idx
)
2224 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
2225 memcpy(dest
, src
, 16*sizeof(float));
2226 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
2230 static void update_texturematrix( GLcontext
*ctx
)
2232 r200ContextPtr rmesa
= R200_CONTEXT( ctx
);
2233 GLuint tpc
= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
];
2234 GLuint compsel
= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
];
2237 if (R200_DEBUG
& DEBUG_STATE
)
2238 fprintf(stderr
, "%s before COMPSEL: %x\n", __FUNCTION__
,
2239 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]);
2241 rmesa
->TexMatEnabled
= 0;
2242 rmesa
->TexMatCompSel
= 0;
2244 for (unit
= 0 ; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
2245 if (!ctx
->Texture
.Unit
[unit
]._ReallyEnabled
)
2248 if (ctx
->TextureMatrixStack
[unit
].Top
->type
!= MATRIX_IDENTITY
) {
2249 rmesa
->TexMatEnabled
|= (R200_TEXGEN_TEXMAT_0_ENABLE
|
2250 R200_TEXMAT_0_ENABLE
) << unit
;
2252 rmesa
->TexMatCompSel
|= R200_OUTPUT_TEX_0
<< unit
;
2254 if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2255 /* Need to preconcatenate any active texgen
2256 * obj/eyeplane matrices:
2258 _math_matrix_mul_matrix( &rmesa
->tmpmat
,
2259 ctx
->TextureMatrixStack
[unit
].Top
,
2260 &rmesa
->TexGenMatrix
[unit
] );
2261 upload_matrix( rmesa
, rmesa
->tmpmat
.m
, R200_MTX_TEX0
+unit
);
2264 upload_matrix( rmesa
, ctx
->TextureMatrixStack
[unit
].Top
->m
,
2265 R200_MTX_TEX0
+unit
);
2268 else if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2269 upload_matrix( rmesa
, rmesa
->TexGenMatrix
[unit
].m
,
2270 R200_MTX_TEX0
+unit
);
2274 tpc
= (rmesa
->TexMatEnabled
| rmesa
->TexGenEnabled
);
2275 if (tpc
!= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
]) {
2276 R200_STATECHANGE(rmesa
, tcg
);
2277 rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
] = tpc
;
2280 compsel
&= ~R200_OUTPUT_TEX_MASK
;
2281 compsel
|= rmesa
->TexMatCompSel
| rmesa
->TexGenCompSel
;
2282 if (compsel
!= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]) {
2283 R200_STATECHANGE(rmesa
, vtx
);
2284 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] = compsel
;
2288 static GLboolean
r200ValidateBuffers(GLcontext
*ctx
)
2290 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2291 struct radeon_renderbuffer
*rrb
;
2292 struct radeon_dma_bo
*dma_bo
;
2295 if (RADEON_DEBUG
& DEBUG_IOCTL
)
2296 fprintf(stderr
, "%s\n", __FUNCTION__
);
2297 radeon_cs_space_reset_bos(rmesa
->radeon
.cmdbuf
.cs
);
2299 rrb
= radeon_get_colorbuffer(&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
);
2307 rrb
= radeon_get_depthbuffer(&rmesa
->radeon
);
2309 if (rrb
&& rrb
->bo
) {
2310 radeon_cs_space_add_persistent_bo(rmesa
->radeon
.cmdbuf
.cs
, rrb
->bo
,
2311 0, RADEON_GEM_DOMAIN_VRAM
);
2314 for (i
= 0; i
< ctx
->Const
.MaxTextureImageUnits
; ++i
) {
2317 if (!ctx
->Texture
.Unit
[i
]._ReallyEnabled
)
2320 t
= radeon_tex_obj(ctx
->Texture
.Unit
[i
]._Current
);
2321 if (t
->image_override
&& t
->bo
)
2322 radeon_cs_space_add_persistent_bo(rmesa
->radeon
.cmdbuf
.cs
, t
->bo
,
2323 RADEON_GEM_DOMAIN_GTT
| RADEON_GEM_DOMAIN_VRAM
, 0);
2325 radeon_cs_space_add_persistent_bo(rmesa
->radeon
.cmdbuf
.cs
, t
->mt
->bo
,
2326 RADEON_GEM_DOMAIN_GTT
| RADEON_GEM_DOMAIN_VRAM
, 0);
2329 dma_bo
= first_elem(&rmesa
->radeon
.dma
.reserved
);
2331 ret
= radeon_cs_space_check_with_bo(rmesa
->radeon
.cmdbuf
.cs
, dma_bo
->bo
, RADEON_GEM_DOMAIN_GTT
, 0);
2338 GLboolean
r200ValidateState( GLcontext
*ctx
)
2340 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2341 GLuint new_state
= rmesa
->radeon
.NewGLState
;
2343 if (new_state
& _NEW_BUFFERS
) {
2344 _mesa_update_framebuffer(ctx
);
2345 /* this updates the DrawBuffer's Width/Height if it's a FBO */
2346 _mesa_update_draw_buffer_bounds(ctx
);
2348 R200_STATECHANGE(rmesa
, ctx
);
2351 if (new_state
& (_NEW_TEXTURE
| _NEW_PROGRAM
| _NEW_PROGRAM_CONSTANTS
)) {
2352 r200UpdateTextureState( ctx
);
2353 new_state
|= rmesa
->radeon
.NewGLState
; /* may add TEXTURE_MATRIX */
2354 r200UpdateLocalViewer( ctx
);
2357 /* we need to do a space check here */
2358 if (!r200ValidateBuffers(ctx
))
2361 /* FIXME: don't really need most of these when vertex progs are enabled */
2363 /* Need an event driven matrix update?
2365 if (new_state
& (_NEW_MODELVIEW
|_NEW_PROJECTION
))
2366 upload_matrix( rmesa
, ctx
->_ModelProjectMatrix
.m
, R200_MTX_MVP
);
2368 /* Need these for lighting (shouldn't upload otherwise)
2370 if (new_state
& (_NEW_MODELVIEW
)) {
2371 upload_matrix( rmesa
, ctx
->ModelviewMatrixStack
.Top
->m
, R200_MTX_MV
);
2372 upload_matrix_t( rmesa
, ctx
->ModelviewMatrixStack
.Top
->inv
, R200_MTX_IMV
);
2375 /* Does this need to be triggered on eg. modelview for
2376 * texgen-derived objplane/eyeplane matrices?
2378 if (new_state
& (_NEW_TEXTURE
|_NEW_TEXTURE_MATRIX
)) {
2379 update_texturematrix( ctx
);
2382 if (new_state
& (_NEW_LIGHT
|_NEW_MODELVIEW
|_MESA_NEW_NEED_EYE_COORDS
)) {
2383 update_light( ctx
);
2386 /* emit all active clip planes if projection matrix changes.
2388 if (new_state
& (_NEW_PROJECTION
)) {
2389 if (ctx
->Transform
.ClipPlanesEnabled
)
2390 r200UpdateClipPlanes( ctx
);
2393 if (new_state
& (_NEW_PROGRAM
|
2394 _NEW_PROGRAM_CONSTANTS
|
2395 /* need to test for pretty much anything due to possible parameter bindings */
2396 _NEW_MODELVIEW
|_NEW_PROJECTION
|_NEW_TRANSFORM
|
2397 _NEW_LIGHT
|_NEW_TEXTURE
|_NEW_TEXTURE_MATRIX
|
2398 _NEW_FOG
|_NEW_POINT
|_NEW_TRACK_MATRIX
)) {
2399 if (ctx
->VertexProgram
._Enabled
) {
2400 r200SetupVertexProg( ctx
);
2402 else TCL_FALLBACK(ctx
, R200_TCL_FALLBACK_VERTEX_PROGRAM
, 0);
2405 rmesa
->radeon
.NewGLState
= 0;
2410 static void r200InvalidateState( GLcontext
*ctx
, GLuint new_state
)
2412 _swrast_InvalidateState( ctx
, new_state
);
2413 _swsetup_InvalidateState( ctx
, new_state
);
2414 _vbo_InvalidateState( ctx
, new_state
);
2415 _tnl_InvalidateState( ctx
, new_state
);
2416 _ae_invalidate_state( ctx
, new_state
);
2417 R200_CONTEXT(ctx
)->radeon
.NewGLState
|= new_state
;
2420 /* A hack. The r200 can actually cope just fine with materials
2421 * between begin/ends, so fix this.
2422 * Should map to inputs just like the generic vertex arrays for vertex progs.
2423 * In theory there could still be too many and we'd still need a fallback.
2425 static GLboolean
check_material( GLcontext
*ctx
)
2427 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
2430 for (i
= _TNL_ATTRIB_MAT_FRONT_AMBIENT
;
2431 i
< _TNL_ATTRIB_MAT_BACK_INDEXES
;
2433 if (tnl
->vb
.AttribPtr
[i
] &&
2434 tnl
->vb
.AttribPtr
[i
]->stride
)
2440 static void r200WrapRunPipeline( GLcontext
*ctx
)
2442 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2443 GLboolean has_material
;
2446 fprintf(stderr
, "%s, newstate: %x\n", __FUNCTION__
, rmesa
->radeon
.NewGLState
);
2450 if (rmesa
->radeon
.NewGLState
)
2451 if (!r200ValidateState( ctx
))
2452 FALLBACK(rmesa
, RADEON_FALLBACK_TEXTURE
, GL_TRUE
);
2454 has_material
= !ctx
->VertexProgram
._Enabled
&& ctx
->Light
.Enabled
&& check_material( ctx
);
2457 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_TRUE
);
2460 /* Run the pipeline.
2462 _tnl_run_pipeline( ctx
);
2465 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_FALSE
);
2470 /* Initialize the driver's state functions.
2472 void r200InitStateFuncs( struct dd_function_table
*functions
)
2474 functions
->UpdateState
= r200InvalidateState
;
2475 functions
->LightingSpaceChange
= r200LightingSpaceChange
;
2477 functions
->DrawBuffer
= radeonDrawBuffer
;
2478 functions
->ReadBuffer
= radeonReadBuffer
;
2480 functions
->AlphaFunc
= r200AlphaFunc
;
2481 functions
->BlendColor
= r200BlendColor
;
2482 functions
->BlendEquationSeparate
= r200BlendEquationSeparate
;
2483 functions
->BlendFuncSeparate
= r200BlendFuncSeparate
;
2484 functions
->ClearColor
= r200ClearColor
;
2485 functions
->ClearDepth
= r200ClearDepth
;
2486 functions
->ClearIndex
= NULL
;
2487 functions
->ClearStencil
= r200ClearStencil
;
2488 functions
->ClipPlane
= r200ClipPlane
;
2489 functions
->ColorMask
= r200ColorMask
;
2490 functions
->CullFace
= r200CullFace
;
2491 functions
->DepthFunc
= r200DepthFunc
;
2492 functions
->DepthMask
= r200DepthMask
;
2493 functions
->DepthRange
= r200DepthRange
;
2494 functions
->Enable
= r200Enable
;
2495 functions
->Fogfv
= r200Fogfv
;
2496 functions
->FrontFace
= r200FrontFace
;
2497 functions
->Hint
= NULL
;
2498 functions
->IndexMask
= NULL
;
2499 functions
->LightModelfv
= r200LightModelfv
;
2500 functions
->Lightfv
= r200Lightfv
;
2501 functions
->LineStipple
= r200LineStipple
;
2502 functions
->LineWidth
= r200LineWidth
;
2503 functions
->LogicOpcode
= r200LogicOpCode
;
2504 functions
->PolygonMode
= r200PolygonMode
;
2505 functions
->PolygonOffset
= r200PolygonOffset
;
2506 functions
->PolygonStipple
= r200PolygonStipple
;
2507 functions
->PointParameterfv
= r200PointParameter
;
2508 functions
->PointSize
= r200PointSize
;
2509 functions
->RenderMode
= r200RenderMode
;
2510 functions
->Scissor
= radeonScissor
;
2511 functions
->ShadeModel
= r200ShadeModel
;
2512 functions
->StencilFuncSeparate
= r200StencilFuncSeparate
;
2513 functions
->StencilMaskSeparate
= r200StencilMaskSeparate
;
2514 functions
->StencilOpSeparate
= r200StencilOpSeparate
;
2515 functions
->Viewport
= r200Viewport
;
2519 void r200InitTnlFuncs( GLcontext
*ctx
)
2521 TNL_CONTEXT(ctx
)->Driver
.NotifyMaterialChange
= r200UpdateMaterial
;
2522 TNL_CONTEXT(ctx
)->Driver
.RunPipeline
= r200WrapRunPipeline
;