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_buffer.h"
51 #include "radeon_cs.h"
52 #include "radeon_mipmap_tree.h"
53 #include "r200_context.h"
54 #include "r200_ioctl.h"
55 #include "r200_state.h"
58 #include "r200_swtcl.h"
59 #include "r200_vertprog.h"
61 #include "drirenderbuffer.h"
64 /* =============================================================
68 static void r200AlphaFunc( GLcontext
*ctx
, GLenum func
, GLfloat ref
)
70 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
71 int pp_misc
= rmesa
->hw
.ctx
.cmd
[CTX_PP_MISC
];
74 CLAMPED_FLOAT_TO_UBYTE(refByte
, ref
);
76 R200_STATECHANGE( rmesa
, ctx
);
78 pp_misc
&= ~(R200_ALPHA_TEST_OP_MASK
| R200_REF_ALPHA_MASK
);
79 pp_misc
|= (refByte
& R200_REF_ALPHA_MASK
);
83 pp_misc
|= R200_ALPHA_TEST_FAIL
;
86 pp_misc
|= R200_ALPHA_TEST_LESS
;
89 pp_misc
|= R200_ALPHA_TEST_EQUAL
;
92 pp_misc
|= R200_ALPHA_TEST_LEQUAL
;
95 pp_misc
|= R200_ALPHA_TEST_GREATER
;
98 pp_misc
|= R200_ALPHA_TEST_NEQUAL
;
101 pp_misc
|= R200_ALPHA_TEST_GEQUAL
;
104 pp_misc
|= R200_ALPHA_TEST_PASS
;
108 rmesa
->hw
.ctx
.cmd
[CTX_PP_MISC
] = pp_misc
;
111 static void r200BlendColor( GLcontext
*ctx
, const GLfloat cf
[4] )
114 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
115 R200_STATECHANGE( rmesa
, ctx
);
116 CLAMPED_FLOAT_TO_UBYTE(color
[0], cf
[0]);
117 CLAMPED_FLOAT_TO_UBYTE(color
[1], cf
[1]);
118 CLAMPED_FLOAT_TO_UBYTE(color
[2], cf
[2]);
119 CLAMPED_FLOAT_TO_UBYTE(color
[3], cf
[3]);
120 if (rmesa
->radeon
.radeonScreen
->drmSupportsBlendColor
)
121 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCOLOR
] = radeonPackColor( 4, color
[0], color
[1], color
[2], color
[3] );
125 * Calculate the hardware blend factor setting. This same function is used
126 * for source and destination of both alpha and RGB.
129 * The hardware register value for the specified blend factor. This value
130 * will need to be shifted into the correct position for either source or
131 * destination factor.
134 * Since the two cases where source and destination are handled differently
135 * are essentially error cases, they should never happen. Determine if these
136 * cases can be removed.
138 static int blend_factor( GLenum factor
, GLboolean is_src
)
144 func
= R200_BLEND_GL_ZERO
;
147 func
= R200_BLEND_GL_ONE
;
150 func
= R200_BLEND_GL_DST_COLOR
;
152 case GL_ONE_MINUS_DST_COLOR
:
153 func
= R200_BLEND_GL_ONE_MINUS_DST_COLOR
;
156 func
= R200_BLEND_GL_SRC_COLOR
;
158 case GL_ONE_MINUS_SRC_COLOR
:
159 func
= R200_BLEND_GL_ONE_MINUS_SRC_COLOR
;
162 func
= R200_BLEND_GL_SRC_ALPHA
;
164 case GL_ONE_MINUS_SRC_ALPHA
:
165 func
= R200_BLEND_GL_ONE_MINUS_SRC_ALPHA
;
168 func
= R200_BLEND_GL_DST_ALPHA
;
170 case GL_ONE_MINUS_DST_ALPHA
:
171 func
= R200_BLEND_GL_ONE_MINUS_DST_ALPHA
;
173 case GL_SRC_ALPHA_SATURATE
:
174 func
= (is_src
) ? R200_BLEND_GL_SRC_ALPHA_SATURATE
: R200_BLEND_GL_ZERO
;
176 case GL_CONSTANT_COLOR
:
177 func
= R200_BLEND_GL_CONST_COLOR
;
179 case GL_ONE_MINUS_CONSTANT_COLOR
:
180 func
= R200_BLEND_GL_ONE_MINUS_CONST_COLOR
;
182 case GL_CONSTANT_ALPHA
:
183 func
= R200_BLEND_GL_CONST_ALPHA
;
185 case GL_ONE_MINUS_CONSTANT_ALPHA
:
186 func
= R200_BLEND_GL_ONE_MINUS_CONST_ALPHA
;
189 func
= (is_src
) ? R200_BLEND_GL_ONE
: R200_BLEND_GL_ZERO
;
195 * Sets both the blend equation and the blend function.
196 * This is done in a single
197 * function because some blend equations (i.e., \c GL_MIN and \c GL_MAX)
198 * change the interpretation of the blend function.
199 * Also, make sure that blend function and blend equation are set to their default
200 * value if color blending is not enabled, since at least blend equations GL_MIN
201 * and GL_FUNC_REVERSE_SUBTRACT will cause wrong results otherwise for
204 static void r200_set_blend_state( GLcontext
* ctx
)
206 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
207 GLuint cntl
= rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &
208 ~(R200_ROP_ENABLE
| R200_ALPHA_BLEND_ENABLE
| R200_SEPARATE_ALPHA_ENABLE
);
210 int func
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
211 (R200_BLEND_GL_ZERO
<< R200_DST_BLEND_SHIFT
);
212 int eqn
= R200_COMB_FCN_ADD_CLAMP
;
213 int funcA
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
214 (R200_BLEND_GL_ZERO
<< R200_DST_BLEND_SHIFT
);
215 int eqnA
= R200_COMB_FCN_ADD_CLAMP
;
217 R200_STATECHANGE( rmesa
, ctx
);
219 if (rmesa
->radeon
.radeonScreen
->drmSupportsBlendColor
) {
220 if (ctx
->Color
.ColorLogicOpEnabled
) {
221 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
| R200_ROP_ENABLE
;
222 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ABLENDCNTL
] = eqn
| func
;
223 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CBLENDCNTL
] = eqn
| func
;
225 } else if (ctx
->Color
.BlendEnabled
) {
226 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
| R200_ALPHA_BLEND_ENABLE
| R200_SEPARATE_ALPHA_ENABLE
;
229 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
;
230 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ABLENDCNTL
] = eqn
| func
;
231 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CBLENDCNTL
] = eqn
| func
;
236 if (ctx
->Color
.ColorLogicOpEnabled
) {
237 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
| R200_ROP_ENABLE
;
238 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] = eqn
| func
;
240 } else if (ctx
->Color
.BlendEnabled
) {
241 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
| R200_ALPHA_BLEND_ENABLE
;
244 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
;
245 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] = eqn
| func
;
250 func
= (blend_factor( ctx
->Color
.BlendSrcRGB
, GL_TRUE
) << R200_SRC_BLEND_SHIFT
) |
251 (blend_factor( ctx
->Color
.BlendDstRGB
, GL_FALSE
) << R200_DST_BLEND_SHIFT
);
253 switch(ctx
->Color
.BlendEquationRGB
) {
255 eqn
= R200_COMB_FCN_ADD_CLAMP
;
258 case GL_FUNC_SUBTRACT
:
259 eqn
= R200_COMB_FCN_SUB_CLAMP
;
262 case GL_FUNC_REVERSE_SUBTRACT
:
263 eqn
= R200_COMB_FCN_RSUB_CLAMP
;
267 eqn
= R200_COMB_FCN_MIN
;
268 func
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
269 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
273 eqn
= R200_COMB_FCN_MAX
;
274 func
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
275 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
279 fprintf( stderr
, "[%s:%u] Invalid RGB blend equation (0x%04x).\n",
280 __FUNCTION__
, __LINE__
, ctx
->Color
.BlendEquationRGB
);
284 if (!rmesa
->radeon
.radeonScreen
->drmSupportsBlendColor
) {
285 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] = eqn
| func
;
289 funcA
= (blend_factor( ctx
->Color
.BlendSrcA
, GL_TRUE
) << R200_SRC_BLEND_SHIFT
) |
290 (blend_factor( ctx
->Color
.BlendDstA
, GL_FALSE
) << R200_DST_BLEND_SHIFT
);
292 switch(ctx
->Color
.BlendEquationA
) {
294 eqnA
= R200_COMB_FCN_ADD_CLAMP
;
297 case GL_FUNC_SUBTRACT
:
298 eqnA
= R200_COMB_FCN_SUB_CLAMP
;
301 case GL_FUNC_REVERSE_SUBTRACT
:
302 eqnA
= R200_COMB_FCN_RSUB_CLAMP
;
306 eqnA
= R200_COMB_FCN_MIN
;
307 funcA
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
308 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
312 eqnA
= R200_COMB_FCN_MAX
;
313 funcA
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
314 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
318 fprintf( stderr
, "[%s:%u] Invalid A blend equation (0x%04x).\n",
319 __FUNCTION__
, __LINE__
, ctx
->Color
.BlendEquationA
);
323 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ABLENDCNTL
] = eqnA
| funcA
;
324 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CBLENDCNTL
] = eqn
| func
;
328 static void r200BlendEquationSeparate( GLcontext
*ctx
,
329 GLenum modeRGB
, GLenum modeA
)
331 r200_set_blend_state( ctx
);
334 static void r200BlendFuncSeparate( GLcontext
*ctx
,
335 GLenum sfactorRGB
, GLenum dfactorRGB
,
336 GLenum sfactorA
, GLenum dfactorA
)
338 r200_set_blend_state( ctx
);
342 /* =============================================================
346 static void r200DepthFunc( GLcontext
*ctx
, GLenum func
)
348 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
350 R200_STATECHANGE( rmesa
, ctx
);
351 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_Z_TEST_MASK
;
353 switch ( ctx
->Depth
.Func
) {
355 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_NEVER
;
358 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_LESS
;
361 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_EQUAL
;
364 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_LEQUAL
;
367 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_GREATER
;
370 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_NEQUAL
;
373 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_GEQUAL
;
376 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_ALWAYS
;
381 static void r200ClearDepth( GLcontext
*ctx
, GLclampd d
)
383 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
384 GLuint format
= (rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &
385 R200_DEPTH_FORMAT_MASK
);
388 case R200_DEPTH_FORMAT_16BIT_INT_Z
:
389 rmesa
->radeon
.state
.depth
.clear
= d
* 0x0000ffff;
391 case R200_DEPTH_FORMAT_24BIT_INT_Z
:
392 rmesa
->radeon
.state
.depth
.clear
= d
* 0x00ffffff;
397 static void r200DepthMask( GLcontext
*ctx
, GLboolean flag
)
399 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
400 R200_STATECHANGE( rmesa
, ctx
);
402 if ( ctx
->Depth
.Mask
) {
403 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_WRITE_ENABLE
;
405 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_Z_WRITE_ENABLE
;
410 /* =============================================================
415 static void r200Fogfv( GLcontext
*ctx
, GLenum pname
, const GLfloat
*param
)
417 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
418 union { int i
; float f
; } c
, d
;
422 c
.i
= rmesa
->hw
.fog
.cmd
[FOG_C
];
423 d
.i
= rmesa
->hw
.fog
.cmd
[FOG_D
];
427 if (!ctx
->Fog
.Enabled
)
429 R200_STATECHANGE(rmesa
, tcl
);
430 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_TCL_FOG_MASK
;
431 switch (ctx
->Fog
.Mode
) {
433 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_LINEAR
;
434 if (ctx
->Fog
.Start
== ctx
->Fog
.End
) {
439 c
.f
= ctx
->Fog
.End
/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
440 d
.f
= -1.0/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
444 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_EXP
;
446 d
.f
= -ctx
->Fog
.Density
;
449 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_EXP2
;
451 d
.f
= -(ctx
->Fog
.Density
* ctx
->Fog
.Density
);
458 switch (ctx
->Fog
.Mode
) {
461 d
.f
= -ctx
->Fog
.Density
;
465 d
.f
= -(ctx
->Fog
.Density
* ctx
->Fog
.Density
);
473 if (ctx
->Fog
.Mode
== GL_LINEAR
) {
474 if (ctx
->Fog
.Start
== ctx
->Fog
.End
) {
478 c
.f
= ctx
->Fog
.End
/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
479 d
.f
= -1.0/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
484 R200_STATECHANGE( rmesa
, ctx
);
485 UNCLAMPED_FLOAT_TO_RGB_CHAN( col
, ctx
->Fog
.Color
);
486 i
= radeonPackColor( 4, col
[0], col
[1], col
[2], 0 );
487 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] &= ~R200_FOG_COLOR_MASK
;
488 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] |= i
;
490 case GL_FOG_COORD_SRC
: {
491 GLuint out_0
= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
];
492 GLuint fog
= rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
];
494 fog
&= ~R200_FOG_USE_MASK
;
495 if ( ctx
->Fog
.FogCoordinateSource
== GL_FOG_COORD
|| ctx
->VertexProgram
.Enabled
) {
496 fog
|= R200_FOG_USE_VTX_FOG
;
497 out_0
|= R200_VTX_DISCRETE_FOG
;
500 fog
|= R200_FOG_USE_SPEC_ALPHA
;
501 out_0
&= ~R200_VTX_DISCRETE_FOG
;
504 if ( fog
!= rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] ) {
505 R200_STATECHANGE( rmesa
, ctx
);
506 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] = fog
;
509 if (out_0
!= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
]) {
510 R200_STATECHANGE( rmesa
, vtx
);
511 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] = out_0
;
520 if (c
.i
!= rmesa
->hw
.fog
.cmd
[FOG_C
] || d
.i
!= rmesa
->hw
.fog
.cmd
[FOG_D
]) {
521 R200_STATECHANGE( rmesa
, fog
);
522 rmesa
->hw
.fog
.cmd
[FOG_C
] = c
.i
;
523 rmesa
->hw
.fog
.cmd
[FOG_D
] = d
.i
;
528 /* =============================================================
533 static void r200Scissor( GLcontext
*ctx
,
534 GLint x
, GLint y
, GLsizei w
, GLsizei h
)
536 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
538 if ( ctx
->Scissor
.Enabled
) {
539 R200_FIREVERTICES( rmesa
); /* don't pipeline cliprect changes */
540 radeonUpdateScissor( ctx
);
546 /* =============================================================
550 static void r200CullFace( GLcontext
*ctx
, GLenum unused
)
552 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
553 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
554 GLuint t
= rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
];
556 s
|= R200_FFACE_SOLID
| R200_BFACE_SOLID
;
557 t
&= ~(R200_CULL_FRONT
| R200_CULL_BACK
);
559 if ( ctx
->Polygon
.CullFlag
) {
560 switch ( ctx
->Polygon
.CullFaceMode
) {
562 s
&= ~R200_FFACE_SOLID
;
563 t
|= R200_CULL_FRONT
;
566 s
&= ~R200_BFACE_SOLID
;
569 case GL_FRONT_AND_BACK
:
570 s
&= ~(R200_FFACE_SOLID
| R200_BFACE_SOLID
);
571 t
|= (R200_CULL_FRONT
| R200_CULL_BACK
);
576 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
577 R200_STATECHANGE(rmesa
, set
);
578 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
581 if ( rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] != t
) {
582 R200_STATECHANGE(rmesa
, tcl
);
583 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] = t
;
587 static void r200FrontFace( GLcontext
*ctx
, GLenum mode
)
589 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
591 R200_STATECHANGE( rmesa
, set
);
592 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_FFACE_CULL_DIR_MASK
;
594 R200_STATECHANGE( rmesa
, tcl
);
595 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_CULL_FRONT_IS_CCW
;
599 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_FFACE_CULL_CW
;
602 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_FFACE_CULL_CCW
;
603 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_CULL_FRONT_IS_CCW
;
608 /* =============================================================
611 static void r200PointSize( GLcontext
*ctx
, GLfloat size
)
613 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
614 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.ptp
.cmd
;
616 R200_STATECHANGE( rmesa
, cst
);
617 R200_STATECHANGE( rmesa
, ptp
);
618 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] &= ~0xffff;
619 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] |= ((GLuint
)(ctx
->Point
.Size
* 16.0));
620 /* this is the size param of the point size calculation (point size reg value
621 is not used when calculation is active). */
622 fcmd
[PTP_VPORT_SCALE_PTSIZE
] = ctx
->Point
.Size
;
625 static void r200PointParameter( GLcontext
*ctx
, GLenum pname
, const GLfloat
*params
)
627 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
628 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.ptp
.cmd
;
631 case GL_POINT_SIZE_MIN
:
632 /* Can clamp both in tcl and setup - just set both (as does fglrx) */
633 R200_STATECHANGE( rmesa
, lin
);
634 R200_STATECHANGE( rmesa
, ptp
);
635 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] &= 0xffff;
636 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] |= (GLuint
)(ctx
->Point
.MinSize
* 16.0) << 16;
637 fcmd
[PTP_CLAMP_MIN
] = ctx
->Point
.MinSize
;
639 case GL_POINT_SIZE_MAX
:
640 R200_STATECHANGE( rmesa
, cst
);
641 R200_STATECHANGE( rmesa
, ptp
);
642 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] &= 0xffff;
643 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] |= (GLuint
)(ctx
->Point
.MaxSize
* 16.0) << 16;
644 fcmd
[PTP_CLAMP_MAX
] = ctx
->Point
.MaxSize
;
646 case GL_POINT_DISTANCE_ATTENUATION
:
647 R200_STATECHANGE( rmesa
, vtx
);
648 R200_STATECHANGE( rmesa
, spr
);
649 R200_STATECHANGE( rmesa
, ptp
);
650 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.ptp
.cmd
;
651 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] &=
652 ~(R200_PS_MULT_MASK
| R200_PS_LIN_ATT_ZERO
| R200_PS_SE_SEL_STATE
);
653 /* can't rely on ctx->Point._Attenuated here and test for NEW_POINT in
654 r200ValidateState looks like overkill */
655 if (ctx
->Point
.Params
[0] != 1.0 ||
656 ctx
->Point
.Params
[1] != 0.0 ||
657 ctx
->Point
.Params
[2] != 0.0 ||
658 (ctx
->VertexProgram
.Enabled
&& ctx
->VertexProgram
.PointSizeEnabled
)) {
659 /* all we care for vp would be the ps_se_sel_state setting */
660 fcmd
[PTP_ATT_CONST_QUAD
] = ctx
->Point
.Params
[2];
661 fcmd
[PTP_ATT_CONST_LIN
] = ctx
->Point
.Params
[1];
662 fcmd
[PTP_ATT_CONST_CON
] = ctx
->Point
.Params
[0];
663 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |= R200_PS_MULT_ATTENCONST
;
664 if (ctx
->Point
.Params
[1] == 0.0)
665 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |= R200_PS_LIN_ATT_ZERO
;
666 /* FIXME: setting this here doesn't look quite ok - we only want to do
667 that if we're actually drawing points probably */
668 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_PT_SIZE
;
669 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |= R200_VTX_POINT_SIZE
;
672 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |=
673 R200_PS_SE_SEL_STATE
| R200_PS_MULT_CONST
;
674 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_PT_SIZE
;
675 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~R200_VTX_POINT_SIZE
;
678 case GL_POINT_FADE_THRESHOLD_SIZE
:
679 /* don't support multisampling, so doesn't matter. */
681 /* can't do these but don't need them.
682 case GL_POINT_SPRITE_R_MODE_NV:
683 case GL_POINT_SPRITE_COORD_ORIGIN: */
685 fprintf(stderr
, "bad pname parameter in r200PointParameter\n");
690 /* =============================================================
693 static void r200LineWidth( GLcontext
*ctx
, GLfloat widthf
)
695 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
697 R200_STATECHANGE( rmesa
, lin
);
698 R200_STATECHANGE( rmesa
, set
);
700 /* Line width is stored in U6.4 format.
701 * Same min/max limits for AA, non-AA lines.
703 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] &= ~0xffff;
704 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] |= (GLuint
)
705 (CLAMP(widthf
, ctx
->Const
.MinLineWidth
, ctx
->Const
.MaxLineWidth
) * 16.0);
707 if ( widthf
> 1.0 ) {
708 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_WIDELINE_ENABLE
;
710 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_WIDELINE_ENABLE
;
714 static void r200LineStipple( GLcontext
*ctx
, GLint factor
, GLushort pattern
)
716 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
718 R200_STATECHANGE( rmesa
, lin
);
719 rmesa
->hw
.lin
.cmd
[LIN_RE_LINE_PATTERN
] =
720 ((((GLuint
)factor
& 0xff) << 16) | ((GLuint
)pattern
));
724 /* =============================================================
727 static void r200ColorMask( GLcontext
*ctx
,
728 GLboolean r
, GLboolean g
,
729 GLboolean b
, GLboolean a
)
731 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
732 GLuint mask
= radeonPackColor( rmesa
->radeon
.radeonScreen
->cpp
,
733 ctx
->Color
.ColorMask
[RCOMP
],
734 ctx
->Color
.ColorMask
[GCOMP
],
735 ctx
->Color
.ColorMask
[BCOMP
],
736 ctx
->Color
.ColorMask
[ACOMP
] );
738 GLuint flag
= rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] & ~R200_PLANE_MASK_ENABLE
;
740 if (!(r
&& g
&& b
&& a
))
741 flag
|= R200_PLANE_MASK_ENABLE
;
743 if ( rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] != flag
) {
744 R200_STATECHANGE( rmesa
, ctx
);
745 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = flag
;
748 if ( rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
] != mask
) {
749 R200_STATECHANGE( rmesa
, msk
);
750 rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
] = mask
;
755 /* =============================================================
759 static void r200PolygonOffset( GLcontext
*ctx
,
760 GLfloat factor
, GLfloat units
)
762 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
763 float_ui32_type constant
= { units
* rmesa
->radeon
.state
.depth
.scale
};
764 float_ui32_type factoru
= { factor
};
769 /* fprintf(stderr, "%s f:%f u:%f\n", __FUNCTION__, factor, constant); */
771 R200_STATECHANGE( rmesa
, zbs
);
772 rmesa
->hw
.zbs
.cmd
[ZBS_SE_ZBIAS_FACTOR
] = factoru
.ui32
;
773 rmesa
->hw
.zbs
.cmd
[ZBS_SE_ZBIAS_CONSTANT
] = constant
.ui32
;
776 static void r200PolygonStipple( GLcontext
*ctx
, const GLubyte
*mask
)
778 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
780 drm_radeon_stipple_t stipple
;
782 /* Must flip pattern upside down.
784 for ( i
= 0 ; i
< 32 ; i
++ ) {
785 rmesa
->state
.stipple
.mask
[31 - i
] = ((GLuint
*) mask
)[i
];
788 /* TODO: push this into cmd mechanism
790 R200_FIREVERTICES( rmesa
);
791 LOCK_HARDWARE( &rmesa
->radeon
);
793 /* FIXME: Use window x,y offsets into stipple RAM.
795 stipple
.mask
= rmesa
->state
.stipple
.mask
;
796 drmCommandWrite( rmesa
->radeon
.dri
.fd
, DRM_RADEON_STIPPLE
,
797 &stipple
, sizeof(stipple
) );
798 UNLOCK_HARDWARE( &rmesa
->radeon
);
801 static void r200PolygonMode( GLcontext
*ctx
, GLenum face
, GLenum mode
)
803 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
804 GLboolean flag
= (ctx
->_TriangleCaps
& DD_TRI_UNFILLED
) != 0;
806 /* Can't generally do unfilled via tcl, but some good special
809 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_UNFILLED
, flag
);
810 if (rmesa
->radeon
.TclFallback
) {
811 r200ChooseRenderState( ctx
);
812 r200ChooseVertexState( ctx
);
817 /* =============================================================
818 * Rendering attributes
820 * We really don't want to recalculate all this every time we bind a
821 * texture. These things shouldn't change all that often, so it makes
822 * sense to break them out of the core texture state update routines.
825 /* Examine lighting and texture state to determine if separate specular
828 static void r200UpdateSpecular( GLcontext
*ctx
)
830 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
831 uint32_t p
= rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
];
833 R200_STATECHANGE( rmesa
, tcl
);
834 R200_STATECHANGE( rmesa
, vtx
);
836 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~(3<<R200_VTX_COLOR_0_SHIFT
);
837 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~(3<<R200_VTX_COLOR_1_SHIFT
);
838 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_COLOR_0
;
839 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_COLOR_1
;
840 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LIGHTING_ENABLE
;
842 p
&= ~R200_SPECULAR_ENABLE
;
844 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_DIFFUSE_SPECULAR_COMBINE
;
847 if (ctx
->Light
.Enabled
&&
848 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
) {
849 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
850 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
) |
851 (R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
852 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_0
;
853 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_1
;
854 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHTING_ENABLE
;
855 p
|= R200_SPECULAR_ENABLE
;
856 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &=
857 ~R200_DIFFUSE_SPECULAR_COMBINE
;
859 else if (ctx
->Light
.Enabled
) {
860 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
861 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
));
862 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_0
;
863 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHTING_ENABLE
;
864 } else if (ctx
->Fog
.ColorSumEnabled
) {
865 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
866 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
) |
867 (R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
868 p
|= R200_SPECULAR_ENABLE
;
870 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
871 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
));
874 if (ctx
->Fog
.Enabled
) {
875 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
876 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
877 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_1
;
880 if ( rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] != p
) {
881 R200_STATECHANGE( rmesa
, ctx
);
882 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] = p
;
885 /* Update vertex/render formats
887 if (rmesa
->radeon
.TclFallback
) {
888 r200ChooseRenderState( ctx
);
889 r200ChooseVertexState( ctx
);
894 /* =============================================================
899 /* Update on colormaterial, material emmissive/ambient,
900 * lightmodel.globalambient
902 static void update_global_ambient( GLcontext
*ctx
)
904 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
905 float *fcmd
= (float *)R200_DB_STATE( glt
);
907 /* Need to do more if both emmissive & ambient are PREMULT:
908 * I believe this is not nessary when using source_material. This condition thus
909 * will never happen currently, and the function has no dependencies on materials now
911 if ((rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
] &
912 ((3 << R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
913 (3 << R200_FRONT_AMBIENT_SOURCE_SHIFT
))) == 0)
915 COPY_3V( &fcmd
[GLT_RED
],
916 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_EMISSION
]);
917 ACC_SCALE_3V( &fcmd
[GLT_RED
],
918 ctx
->Light
.Model
.Ambient
,
919 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_AMBIENT
]);
923 COPY_3V( &fcmd
[GLT_RED
], ctx
->Light
.Model
.Ambient
);
926 R200_DB_STATECHANGE(rmesa
, &rmesa
->hw
.glt
);
929 /* Update on change to
933 static void update_light_colors( GLcontext
*ctx
, GLuint p
)
935 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
937 /* fprintf(stderr, "%s\n", __FUNCTION__); */
940 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
941 float *fcmd
= (float *)R200_DB_STATE( lit
[p
] );
943 COPY_4V( &fcmd
[LIT_AMBIENT_RED
], l
->Ambient
);
944 COPY_4V( &fcmd
[LIT_DIFFUSE_RED
], l
->Diffuse
);
945 COPY_4V( &fcmd
[LIT_SPECULAR_RED
], l
->Specular
);
947 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
951 static void r200ColorMaterial( GLcontext
*ctx
, GLenum face
, GLenum mode
)
953 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
954 GLuint light_model_ctl1
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
];
955 light_model_ctl1
&= ~((0xf << R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
956 (0xf << R200_FRONT_AMBIENT_SOURCE_SHIFT
) |
957 (0xf << R200_FRONT_DIFFUSE_SOURCE_SHIFT
) |
958 (0xf << R200_FRONT_SPECULAR_SOURCE_SHIFT
) |
959 (0xf << R200_BACK_EMISSIVE_SOURCE_SHIFT
) |
960 (0xf << R200_BACK_AMBIENT_SOURCE_SHIFT
) |
961 (0xf << R200_BACK_DIFFUSE_SOURCE_SHIFT
) |
962 (0xf << R200_BACK_SPECULAR_SOURCE_SHIFT
));
964 if (ctx
->Light
.ColorMaterialEnabled
) {
965 GLuint mask
= ctx
->Light
.ColorMaterialBitmask
;
967 if (mask
& MAT_BIT_FRONT_EMISSION
) {
968 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
969 R200_FRONT_EMISSIVE_SOURCE_SHIFT
);
972 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
973 R200_FRONT_EMISSIVE_SOURCE_SHIFT
);
975 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
976 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
977 R200_FRONT_AMBIENT_SOURCE_SHIFT
);
980 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
981 R200_FRONT_AMBIENT_SOURCE_SHIFT
);
983 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
984 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
985 R200_FRONT_DIFFUSE_SOURCE_SHIFT
);
988 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
989 R200_FRONT_DIFFUSE_SOURCE_SHIFT
);
991 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
992 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
993 R200_FRONT_SPECULAR_SOURCE_SHIFT
);
996 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
997 R200_FRONT_SPECULAR_SOURCE_SHIFT
);
1000 if (mask
& MAT_BIT_BACK_EMISSION
) {
1001 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
1002 R200_BACK_EMISSIVE_SOURCE_SHIFT
);
1005 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
1006 R200_BACK_EMISSIVE_SOURCE_SHIFT
);
1008 if (mask
& MAT_BIT_BACK_AMBIENT
) {
1009 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
1010 R200_BACK_AMBIENT_SOURCE_SHIFT
);
1012 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
1013 R200_BACK_AMBIENT_SOURCE_SHIFT
);
1015 if (mask
& MAT_BIT_BACK_DIFFUSE
) {
1016 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
1017 R200_BACK_DIFFUSE_SOURCE_SHIFT
);
1019 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
1020 R200_BACK_DIFFUSE_SOURCE_SHIFT
);
1022 if (mask
& MAT_BIT_BACK_SPECULAR
) {
1023 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
1024 R200_BACK_SPECULAR_SOURCE_SHIFT
);
1027 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
1028 R200_BACK_SPECULAR_SOURCE_SHIFT
);
1032 /* Default to SOURCE_MATERIAL:
1035 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
1036 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_AMBIENT_SOURCE_SHIFT
) |
1037 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_DIFFUSE_SOURCE_SHIFT
) |
1038 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_SPECULAR_SOURCE_SHIFT
) |
1039 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_EMISSIVE_SOURCE_SHIFT
) |
1040 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_AMBIENT_SOURCE_SHIFT
) |
1041 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_DIFFUSE_SOURCE_SHIFT
) |
1042 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_SPECULAR_SOURCE_SHIFT
);
1045 if (light_model_ctl1
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
]) {
1046 R200_STATECHANGE( rmesa
, tcl
);
1047 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
] = light_model_ctl1
;
1053 void r200UpdateMaterial( GLcontext
*ctx
)
1055 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1056 GLfloat (*mat
)[4] = ctx
->Light
.Material
.Attrib
;
1057 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( mtl
[0] );
1058 GLfloat
*fcmd2
= (GLfloat
*)R200_DB_STATE( mtl
[1] );
1061 /* Might be possible and faster to update everything unconditionally? */
1062 if (ctx
->Light
.ColorMaterialEnabled
)
1063 mask
&= ~ctx
->Light
.ColorMaterialBitmask
;
1065 if (R200_DEBUG
& DEBUG_STATE
)
1066 fprintf(stderr
, "%s\n", __FUNCTION__
);
1068 if (mask
& MAT_BIT_FRONT_EMISSION
) {
1069 fcmd
[MTL_EMMISSIVE_RED
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][0];
1070 fcmd
[MTL_EMMISSIVE_GREEN
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][1];
1071 fcmd
[MTL_EMMISSIVE_BLUE
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][2];
1072 fcmd
[MTL_EMMISSIVE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][3];
1074 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
1075 fcmd
[MTL_AMBIENT_RED
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][0];
1076 fcmd
[MTL_AMBIENT_GREEN
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][1];
1077 fcmd
[MTL_AMBIENT_BLUE
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][2];
1078 fcmd
[MTL_AMBIENT_ALPHA
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][3];
1080 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
1081 fcmd
[MTL_DIFFUSE_RED
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][0];
1082 fcmd
[MTL_DIFFUSE_GREEN
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][1];
1083 fcmd
[MTL_DIFFUSE_BLUE
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][2];
1084 fcmd
[MTL_DIFFUSE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][3];
1086 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
1087 fcmd
[MTL_SPECULAR_RED
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][0];
1088 fcmd
[MTL_SPECULAR_GREEN
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][1];
1089 fcmd
[MTL_SPECULAR_BLUE
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][2];
1090 fcmd
[MTL_SPECULAR_ALPHA
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][3];
1092 if (mask
& MAT_BIT_FRONT_SHININESS
) {
1093 fcmd
[MTL_SHININESS
] = mat
[MAT_ATTRIB_FRONT_SHININESS
][0];
1096 if (mask
& MAT_BIT_BACK_EMISSION
) {
1097 fcmd2
[MTL_EMMISSIVE_RED
] = mat
[MAT_ATTRIB_BACK_EMISSION
][0];
1098 fcmd2
[MTL_EMMISSIVE_GREEN
] = mat
[MAT_ATTRIB_BACK_EMISSION
][1];
1099 fcmd2
[MTL_EMMISSIVE_BLUE
] = mat
[MAT_ATTRIB_BACK_EMISSION
][2];
1100 fcmd2
[MTL_EMMISSIVE_ALPHA
] = mat
[MAT_ATTRIB_BACK_EMISSION
][3];
1102 if (mask
& MAT_BIT_BACK_AMBIENT
) {
1103 fcmd2
[MTL_AMBIENT_RED
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][0];
1104 fcmd2
[MTL_AMBIENT_GREEN
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][1];
1105 fcmd2
[MTL_AMBIENT_BLUE
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][2];
1106 fcmd2
[MTL_AMBIENT_ALPHA
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][3];
1108 if (mask
& MAT_BIT_BACK_DIFFUSE
) {
1109 fcmd2
[MTL_DIFFUSE_RED
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][0];
1110 fcmd2
[MTL_DIFFUSE_GREEN
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][1];
1111 fcmd2
[MTL_DIFFUSE_BLUE
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][2];
1112 fcmd2
[MTL_DIFFUSE_ALPHA
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][3];
1114 if (mask
& MAT_BIT_BACK_SPECULAR
) {
1115 fcmd2
[MTL_SPECULAR_RED
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][0];
1116 fcmd2
[MTL_SPECULAR_GREEN
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][1];
1117 fcmd2
[MTL_SPECULAR_BLUE
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][2];
1118 fcmd2
[MTL_SPECULAR_ALPHA
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][3];
1120 if (mask
& MAT_BIT_BACK_SHININESS
) {
1121 fcmd2
[MTL_SHININESS
] = mat
[MAT_ATTRIB_BACK_SHININESS
][0];
1124 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mtl
[0] );
1125 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mtl
[1] );
1127 /* currently material changes cannot trigger a global ambient change, I believe this is correct
1128 update_global_ambient( ctx ); */
1133 * _MESA_NEW_NEED_EYE_COORDS
1135 * Uses derived state from mesa:
1140 * _ModelViewInvScale
1144 * which are calculated in light.c and are correct for the current
1145 * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
1146 * and _MESA_NEW_NEED_EYE_COORDS.
1148 static void update_light( GLcontext
*ctx
)
1150 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1152 /* Have to check these, or have an automatic shortcircuit mechanism
1153 * to remove noop statechanges. (Or just do a better job on the
1157 GLuint tmp
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
];
1159 if (ctx
->_NeedEyeCoords
)
1160 tmp
&= ~R200_LIGHT_IN_MODELSPACE
;
1162 tmp
|= R200_LIGHT_IN_MODELSPACE
;
1164 if (tmp
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
])
1166 R200_STATECHANGE( rmesa
, tcl
);
1167 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] = tmp
;
1172 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( eye
);
1173 fcmd
[EYE_X
] = ctx
->_EyeZDir
[0];
1174 fcmd
[EYE_Y
] = ctx
->_EyeZDir
[1];
1175 fcmd
[EYE_Z
] = - ctx
->_EyeZDir
[2];
1176 fcmd
[EYE_RESCALE_FACTOR
] = ctx
->_ModelViewInvScale
;
1177 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.eye
);
1182 if (ctx
->Light
.Enabled
) {
1184 for (p
= 0 ; p
< MAX_LIGHTS
; p
++) {
1185 if (ctx
->Light
.Light
[p
].Enabled
) {
1186 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1187 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( lit
[p
] );
1189 if (l
->EyePosition
[3] == 0.0) {
1190 COPY_3FV( &fcmd
[LIT_POSITION_X
], l
->_VP_inf_norm
);
1191 COPY_3FV( &fcmd
[LIT_DIRECTION_X
], l
->_h_inf_norm
);
1192 fcmd
[LIT_POSITION_W
] = 0;
1193 fcmd
[LIT_DIRECTION_W
] = 0;
1195 COPY_4V( &fcmd
[LIT_POSITION_X
], l
->_Position
);
1196 fcmd
[LIT_DIRECTION_X
] = -l
->_NormDirection
[0];
1197 fcmd
[LIT_DIRECTION_Y
] = -l
->_NormDirection
[1];
1198 fcmd
[LIT_DIRECTION_Z
] = -l
->_NormDirection
[2];
1199 fcmd
[LIT_DIRECTION_W
] = 0;
1202 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
1208 static void r200Lightfv( GLcontext
*ctx
, GLenum light
,
1209 GLenum pname
, const GLfloat
*params
)
1211 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1212 GLint p
= light
- GL_LIGHT0
;
1213 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1214 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.lit
[p
].cmd
;
1221 update_light_colors( ctx
, p
);
1224 case GL_SPOT_DIRECTION
:
1225 /* picked up in update_light */
1229 /* positions picked up in update_light, but can do flag here */
1230 GLuint flag
= (p
&1)? R200_LIGHT_1_IS_LOCAL
: R200_LIGHT_0_IS_LOCAL
;
1231 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1233 R200_STATECHANGE(rmesa
, tcl
);
1234 if (l
->EyePosition
[3] != 0.0F
)
1235 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1237 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1241 case GL_SPOT_EXPONENT
:
1242 R200_STATECHANGE(rmesa
, lit
[p
]);
1243 fcmd
[LIT_SPOT_EXPONENT
] = params
[0];
1246 case GL_SPOT_CUTOFF
: {
1247 GLuint flag
= (p
&1) ? R200_LIGHT_1_IS_SPOT
: R200_LIGHT_0_IS_SPOT
;
1248 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1250 R200_STATECHANGE(rmesa
, lit
[p
]);
1251 fcmd
[LIT_SPOT_CUTOFF
] = l
->_CosCutoff
;
1253 R200_STATECHANGE(rmesa
, tcl
);
1254 if (l
->SpotCutoff
!= 180.0F
)
1255 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1257 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1262 case GL_CONSTANT_ATTENUATION
:
1263 R200_STATECHANGE(rmesa
, lit
[p
]);
1264 fcmd
[LIT_ATTEN_CONST
] = params
[0];
1265 if ( params
[0] == 0.0 )
1266 fcmd
[LIT_ATTEN_CONST_INV
] = FLT_MAX
;
1268 fcmd
[LIT_ATTEN_CONST_INV
] = 1.0 / params
[0];
1270 case GL_LINEAR_ATTENUATION
:
1271 R200_STATECHANGE(rmesa
, lit
[p
]);
1272 fcmd
[LIT_ATTEN_LINEAR
] = params
[0];
1274 case GL_QUADRATIC_ATTENUATION
:
1275 R200_STATECHANGE(rmesa
, lit
[p
]);
1276 fcmd
[LIT_ATTEN_QUADRATIC
] = params
[0];
1282 /* Set RANGE_ATTEN only when needed */
1285 case GL_CONSTANT_ATTENUATION
:
1286 case GL_LINEAR_ATTENUATION
:
1287 case GL_QUADRATIC_ATTENUATION
: {
1288 GLuint
*icmd
= (GLuint
*)R200_DB_STATE( tcl
);
1289 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1290 GLuint atten_flag
= ( p
&1 ) ? R200_LIGHT_1_ENABLE_RANGE_ATTEN
1291 : R200_LIGHT_0_ENABLE_RANGE_ATTEN
;
1292 GLuint atten_const_flag
= ( p
&1 ) ? R200_LIGHT_1_CONSTANT_RANGE_ATTEN
1293 : R200_LIGHT_0_CONSTANT_RANGE_ATTEN
;
1295 if ( l
->EyePosition
[3] == 0.0F
||
1296 ( ( fcmd
[LIT_ATTEN_CONST
] == 0.0 || fcmd
[LIT_ATTEN_CONST
] == 1.0 ) &&
1297 fcmd
[LIT_ATTEN_QUADRATIC
] == 0.0 && fcmd
[LIT_ATTEN_LINEAR
] == 0.0 ) ) {
1298 /* Disable attenuation */
1299 icmd
[idx
] &= ~atten_flag
;
1301 if ( fcmd
[LIT_ATTEN_QUADRATIC
] == 0.0 && fcmd
[LIT_ATTEN_LINEAR
] == 0.0 ) {
1302 /* Enable only constant portion of attenuation calculation */
1303 icmd
[idx
] |= ( atten_flag
| atten_const_flag
);
1305 /* Enable full attenuation calculation */
1306 icmd
[idx
] &= ~atten_const_flag
;
1307 icmd
[idx
] |= atten_flag
;
1311 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.tcl
);
1319 static void r200UpdateLocalViewer ( GLcontext
*ctx
)
1321 /* It looks like for the texgen modes GL_SPHERE_MAP, GL_NORMAL_MAP and
1322 GL_REFLECTION_MAP we need R200_LOCAL_VIEWER set (fglrx does exactly that
1323 for these and only these modes). This means specular highlights may turn out
1324 wrong in some cases when lighting is enabled but GL_LIGHT_MODEL_LOCAL_VIEWER
1325 is not set, though it seems to happen rarely and the effect seems quite
1326 subtle. May need TCL fallback to fix it completely, though I'm not sure
1327 how you'd identify the cases where the specular highlights indeed will
1328 be wrong. Don't know if fglrx does something special in that case.
1330 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1331 R200_STATECHANGE( rmesa
, tcl
);
1332 if (ctx
->Light
.Model
.LocalViewer
||
1333 ctx
->Texture
._GenFlags
& TEXGEN_NEED_NORMALS
)
1334 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LOCAL_VIEWER
;
1336 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LOCAL_VIEWER
;
1339 static void r200LightModelfv( GLcontext
*ctx
, GLenum pname
,
1340 const GLfloat
*param
)
1342 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1345 case GL_LIGHT_MODEL_AMBIENT
:
1346 update_global_ambient( ctx
);
1349 case GL_LIGHT_MODEL_LOCAL_VIEWER
:
1350 r200UpdateLocalViewer( ctx
);
1353 case GL_LIGHT_MODEL_TWO_SIDE
:
1354 R200_STATECHANGE( rmesa
, tcl
);
1355 if (ctx
->Light
.Model
.TwoSide
)
1356 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHT_TWOSIDE
;
1358 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~(R200_LIGHT_TWOSIDE
);
1359 if (rmesa
->radeon
.TclFallback
) {
1360 r200ChooseRenderState( ctx
);
1361 r200ChooseVertexState( ctx
);
1365 case GL_LIGHT_MODEL_COLOR_CONTROL
:
1366 r200UpdateSpecular(ctx
);
1374 static void r200ShadeModel( GLcontext
*ctx
, GLenum mode
)
1376 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1377 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
1379 s
&= ~(R200_DIFFUSE_SHADE_MASK
|
1380 R200_ALPHA_SHADE_MASK
|
1381 R200_SPECULAR_SHADE_MASK
|
1382 R200_FOG_SHADE_MASK
|
1383 R200_DISC_FOG_SHADE_MASK
);
1387 s
|= (R200_DIFFUSE_SHADE_FLAT
|
1388 R200_ALPHA_SHADE_FLAT
|
1389 R200_SPECULAR_SHADE_FLAT
|
1390 R200_FOG_SHADE_FLAT
|
1391 R200_DISC_FOG_SHADE_FLAT
);
1394 s
|= (R200_DIFFUSE_SHADE_GOURAUD
|
1395 R200_ALPHA_SHADE_GOURAUD
|
1396 R200_SPECULAR_SHADE_GOURAUD
|
1397 R200_FOG_SHADE_GOURAUD
|
1398 R200_DISC_FOG_SHADE_GOURAUD
);
1404 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
1405 R200_STATECHANGE( rmesa
, set
);
1406 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
1411 /* =============================================================
1415 static void r200ClipPlane( GLcontext
*ctx
, GLenum plane
, const GLfloat
*eq
)
1417 GLint p
= (GLint
) plane
- (GLint
) GL_CLIP_PLANE0
;
1418 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1419 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1421 R200_STATECHANGE( rmesa
, ucp
[p
] );
1422 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1423 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1424 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1425 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1428 static void r200UpdateClipPlanes( GLcontext
*ctx
)
1430 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1433 for (p
= 0; p
< ctx
->Const
.MaxClipPlanes
; p
++) {
1434 if (ctx
->Transform
.ClipPlanesEnabled
& (1 << p
)) {
1435 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1437 R200_STATECHANGE( rmesa
, ucp
[p
] );
1438 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1439 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1440 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1441 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1447 /* =============================================================
1452 r200StencilFuncSeparate( GLcontext
*ctx
, GLenum face
, GLenum func
,
1453 GLint ref
, GLuint mask
)
1455 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1456 GLuint refmask
= (((ctx
->Stencil
.Ref
[0] & 0xff) << R200_STENCIL_REF_SHIFT
) |
1457 ((ctx
->Stencil
.ValueMask
[0] & 0xff) << R200_STENCIL_MASK_SHIFT
));
1459 R200_STATECHANGE( rmesa
, ctx
);
1460 R200_STATECHANGE( rmesa
, msk
);
1462 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_STENCIL_TEST_MASK
;
1463 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~(R200_STENCIL_REF_MASK
|
1464 R200_STENCIL_VALUE_MASK
);
1466 switch ( ctx
->Stencil
.Function
[0] ) {
1468 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEVER
;
1471 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LESS
;
1474 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_EQUAL
;
1477 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LEQUAL
;
1480 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GREATER
;
1483 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEQUAL
;
1486 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GEQUAL
;
1489 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_ALWAYS
;
1493 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |= refmask
;
1497 r200StencilMaskSeparate( GLcontext
*ctx
, GLenum face
, GLuint mask
)
1499 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1501 R200_STATECHANGE( rmesa
, msk
);
1502 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~R200_STENCIL_WRITE_MASK
;
1503 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |=
1504 ((ctx
->Stencil
.WriteMask
[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT
);
1508 r200StencilOpSeparate( GLcontext
*ctx
, GLenum face
, GLenum fail
,
1509 GLenum zfail
, GLenum zpass
)
1511 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1513 R200_STATECHANGE( rmesa
, ctx
);
1514 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~(R200_STENCIL_FAIL_MASK
|
1515 R200_STENCIL_ZFAIL_MASK
|
1516 R200_STENCIL_ZPASS_MASK
);
1518 switch ( ctx
->Stencil
.FailFunc
[0] ) {
1520 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_KEEP
;
1523 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_ZERO
;
1526 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_REPLACE
;
1529 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC
;
1532 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC
;
1534 case GL_INCR_WRAP_EXT
:
1535 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC_WRAP
;
1537 case GL_DECR_WRAP_EXT
:
1538 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC_WRAP
;
1541 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INVERT
;
1545 switch ( ctx
->Stencil
.ZFailFunc
[0] ) {
1547 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_KEEP
;
1550 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_ZERO
;
1553 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_REPLACE
;
1556 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC
;
1559 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC
;
1561 case GL_INCR_WRAP_EXT
:
1562 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC_WRAP
;
1564 case GL_DECR_WRAP_EXT
:
1565 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC_WRAP
;
1568 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INVERT
;
1572 switch ( ctx
->Stencil
.ZPassFunc
[0] ) {
1574 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_KEEP
;
1577 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_ZERO
;
1580 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_REPLACE
;
1583 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC
;
1586 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC
;
1588 case GL_INCR_WRAP_EXT
:
1589 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC_WRAP
;
1591 case GL_DECR_WRAP_EXT
:
1592 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC_WRAP
;
1595 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INVERT
;
1600 static void r200ClearStencil( GLcontext
*ctx
, GLint s
)
1602 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1604 rmesa
->radeon
.state
.stencil
.clear
=
1605 ((GLuint
) (ctx
->Stencil
.Clear
& 0xff) |
1606 (0xff << R200_STENCIL_MASK_SHIFT
) |
1607 ((ctx
->Stencil
.WriteMask
[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT
));
1611 /* =============================================================
1612 * Window position and viewport transformation
1616 * To correctly position primitives:
1618 #define SUBPIXEL_X 0.125
1619 #define SUBPIXEL_Y 0.125
1623 * Called when window size or position changes or viewport or depth range
1624 * state is changed. We update the hardware viewport state here.
1626 void r200UpdateWindow( GLcontext
*ctx
)
1628 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1629 __DRIdrawablePrivate
*dPriv
= rmesa
->radeon
.dri
.drawable
;
1630 GLfloat xoffset
= dPriv
? (GLfloat
) dPriv
->x
: 0;
1631 GLfloat yoffset
= dPriv
? (GLfloat
) dPriv
->y
+ dPriv
->h
: 0;
1632 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1634 float_ui32_type sx
= { v
[MAT_SX
] };
1635 float_ui32_type tx
= { v
[MAT_TX
] + xoffset
+ SUBPIXEL_X
};
1636 float_ui32_type sy
= { - v
[MAT_SY
] };
1637 float_ui32_type ty
= { (- v
[MAT_TY
]) + yoffset
+ SUBPIXEL_Y
};
1638 float_ui32_type sz
= { v
[MAT_SZ
] * rmesa
->radeon
.state
.depth
.scale
};
1639 float_ui32_type tz
= { v
[MAT_TZ
] * rmesa
->radeon
.state
.depth
.scale
};
1641 R200_FIREVERTICES( rmesa
);
1642 R200_STATECHANGE( rmesa
, vpt
);
1644 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XSCALE
] = sx
.ui32
;
1645 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = tx
.ui32
;
1646 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YSCALE
] = sy
.ui32
;
1647 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = ty
.ui32
;
1648 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZSCALE
] = sz
.ui32
;
1649 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZOFFSET
] = tz
.ui32
;
1654 static void r200Viewport( GLcontext
*ctx
, GLint x
, GLint y
,
1655 GLsizei width
, GLsizei height
)
1657 /* Don't pipeline viewport changes, conflict with window offset
1658 * setting below. Could apply deltas to rescue pipelined viewport
1659 * values, or keep the originals hanging around.
1661 r200UpdateWindow( ctx
);
1664 static void r200DepthRange( GLcontext
*ctx
, GLclampd nearval
,
1667 r200UpdateWindow( ctx
);
1670 void r200UpdateViewportOffset( GLcontext
*ctx
)
1672 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1673 __DRIdrawablePrivate
*dPriv
= rmesa
->radeon
.dri
.drawable
;
1674 GLfloat xoffset
= (GLfloat
)dPriv
->x
;
1675 GLfloat yoffset
= (GLfloat
)dPriv
->y
+ dPriv
->h
;
1676 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1681 tx
.f
= v
[MAT_TX
] + xoffset
+ SUBPIXEL_X
;
1682 ty
.f
= (- v
[MAT_TY
]) + yoffset
+ SUBPIXEL_Y
;
1684 if ( rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] != tx
.ui32
||
1685 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] != ty
.ui32
)
1687 /* Note: this should also modify whatever data the context reset
1690 R200_STATECHANGE( rmesa
, vpt
);
1691 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = tx
.ui32
;
1692 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = ty
.ui32
;
1694 /* update polygon stipple x/y screen offset */
1697 GLuint m
= rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
];
1699 m
&= ~(R200_STIPPLE_X_OFFSET_MASK
|
1700 R200_STIPPLE_Y_OFFSET_MASK
);
1702 /* add magic offsets, then invert */
1703 stx
= 31 - ((rmesa
->radeon
.dri
.drawable
->x
- 1) & R200_STIPPLE_COORD_MASK
);
1704 sty
= 31 - ((rmesa
->radeon
.dri
.drawable
->y
+ rmesa
->radeon
.dri
.drawable
->h
- 1)
1705 & R200_STIPPLE_COORD_MASK
);
1707 m
|= ((stx
<< R200_STIPPLE_X_OFFSET_SHIFT
) |
1708 (sty
<< R200_STIPPLE_Y_OFFSET_SHIFT
));
1710 if ( rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] != m
) {
1711 R200_STATECHANGE( rmesa
, msc
);
1712 rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] = m
;
1717 radeonUpdateScissor( ctx
);
1722 /* =============================================================
1726 static void r200ClearColor( GLcontext
*ctx
, const GLfloat c
[4] )
1728 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1730 CLAMPED_FLOAT_TO_UBYTE(color
[0], c
[0]);
1731 CLAMPED_FLOAT_TO_UBYTE(color
[1], c
[1]);
1732 CLAMPED_FLOAT_TO_UBYTE(color
[2], c
[2]);
1733 CLAMPED_FLOAT_TO_UBYTE(color
[3], c
[3]);
1734 rmesa
->radeon
.state
.color
.clear
= radeonPackColor( rmesa
->radeon
.radeonScreen
->cpp
,
1736 color
[2], color
[3] );
1740 static void r200RenderMode( GLcontext
*ctx
, GLenum mode
)
1742 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1743 FALLBACK( rmesa
, R200_FALLBACK_RENDER_MODE
, (mode
!= GL_RENDER
) );
1747 static GLuint r200_rop_tab
[] = {
1750 R200_ROP_AND_REVERSE
,
1752 R200_ROP_AND_INVERTED
,
1759 R200_ROP_OR_REVERSE
,
1760 R200_ROP_COPY_INVERTED
,
1761 R200_ROP_OR_INVERTED
,
1766 static void r200LogicOpCode( GLcontext
*ctx
, GLenum opcode
)
1768 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1769 GLuint rop
= (GLuint
)opcode
- GL_CLEAR
;
1773 R200_STATECHANGE( rmesa
, msk
);
1774 rmesa
->hw
.msk
.cmd
[MSK_RB3D_ROPCNTL
] = r200_rop_tab
[rop
];
1778 static void r200DrawBuffer( GLcontext
*ctx
, GLenum mode
)
1780 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1782 if (R200_DEBUG
& DEBUG_DRI
)
1783 fprintf(stderr
, "%s %s\n", __FUNCTION__
,
1784 _mesa_lookup_enum_by_nr( mode
));
1786 R200_FIREVERTICES(rmesa
); /* don't pipeline cliprect changes */
1788 if (ctx
->DrawBuffer
->_NumColorDrawBuffers
!= 1) {
1789 /* 0 (GL_NONE) buffers or multiple color drawing buffers */
1790 FALLBACK( rmesa
, R200_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
1794 switch ( ctx
->DrawBuffer
->_ColorDrawBufferIndexes
[0] ) {
1795 case BUFFER_FRONT_LEFT
:
1796 case BUFFER_BACK_LEFT
:
1797 FALLBACK( rmesa
, R200_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
1800 FALLBACK( rmesa
, R200_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
1804 radeonSetCliprects( &rmesa
->radeon
);
1806 /* We'll set the drawing engine's offset/pitch parameters later
1807 * when we update other state.
1812 static void r200ReadBuffer( GLcontext
*ctx
, GLenum mode
)
1814 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
1817 /* =============================================================
1818 * State enable/disable
1821 static void r200Enable( GLcontext
*ctx
, GLenum cap
, GLboolean state
)
1823 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1826 if ( R200_DEBUG
& DEBUG_STATE
)
1827 fprintf( stderr
, "%s( %s = %s )\n", __FUNCTION__
,
1828 _mesa_lookup_enum_by_nr( cap
),
1829 state
? "GL_TRUE" : "GL_FALSE" );
1832 /* Fast track this one...
1840 R200_STATECHANGE( rmesa
, ctx
);
1842 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ALPHA_TEST_ENABLE
;
1844 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ALPHA_TEST_ENABLE
;
1849 case GL_COLOR_LOGIC_OP
:
1850 r200_set_blend_state( ctx
);
1853 case GL_CLIP_PLANE0
:
1854 case GL_CLIP_PLANE1
:
1855 case GL_CLIP_PLANE2
:
1856 case GL_CLIP_PLANE3
:
1857 case GL_CLIP_PLANE4
:
1858 case GL_CLIP_PLANE5
:
1859 p
= cap
-GL_CLIP_PLANE0
;
1860 R200_STATECHANGE( rmesa
, tcl
);
1862 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= (R200_UCP_ENABLE_0
<<p
);
1863 r200ClipPlane( ctx
, cap
, NULL
);
1866 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~(R200_UCP_ENABLE_0
<<p
);
1870 case GL_COLOR_MATERIAL
:
1871 r200ColorMaterial( ctx
, 0, 0 );
1872 r200UpdateMaterial( ctx
);
1876 r200CullFace( ctx
, 0 );
1880 R200_STATECHANGE(rmesa
, ctx
);
1882 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_Z_ENABLE
;
1884 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_Z_ENABLE
;
1889 R200_STATECHANGE(rmesa
, ctx
);
1891 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_DITHER_ENABLE
;
1892 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~rmesa
->radeon
.state
.color
.roundEnable
;
1894 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_DITHER_ENABLE
;
1895 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= rmesa
->radeon
.state
.color
.roundEnable
;
1900 R200_STATECHANGE(rmesa
, ctx
);
1902 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_FOG_ENABLE
;
1903 r200Fogfv( ctx
, GL_FOG_MODE
, NULL
);
1905 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_FOG_ENABLE
;
1906 R200_STATECHANGE(rmesa
, tcl
);
1907 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_TCL_FOG_MASK
;
1909 r200UpdateSpecular( ctx
); /* for PK_SPEC */
1910 if (rmesa
->radeon
.TclFallback
)
1911 r200ChooseVertexState( ctx
);
1912 _mesa_allow_light_in_model( ctx
, !state
);
1923 R200_STATECHANGE(rmesa
, tcl
);
1924 p
= cap
- GL_LIGHT0
;
1926 flag
= (R200_LIGHT_1_ENABLE
|
1927 R200_LIGHT_1_ENABLE_AMBIENT
|
1928 R200_LIGHT_1_ENABLE_SPECULAR
);
1930 flag
= (R200_LIGHT_0_ENABLE
|
1931 R200_LIGHT_0_ENABLE_AMBIENT
|
1932 R200_LIGHT_0_ENABLE_SPECULAR
);
1935 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] |= flag
;
1937 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] &= ~flag
;
1941 update_light_colors( ctx
, p
);
1945 r200UpdateSpecular(ctx
);
1946 /* for reflection map fixup - might set recheck_texgen for all units too */
1947 rmesa
->radeon
.NewGLState
|= _NEW_TEXTURE
;
1950 case GL_LINE_SMOOTH
:
1951 R200_STATECHANGE( rmesa
, ctx
);
1953 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_LINE
;
1955 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_LINE
;
1959 case GL_LINE_STIPPLE
:
1960 R200_STATECHANGE( rmesa
, set
);
1962 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_PATTERN_ENABLE
;
1964 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_PATTERN_ENABLE
;
1969 R200_STATECHANGE( rmesa
, tcl
);
1971 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_NORMALIZE_NORMALS
;
1973 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_NORMALIZE_NORMALS
;
1977 /* Pointsize registers on r200 only work for point sprites, and point smooth
1978 * doesn't work for point sprites (and isn't needed for 1.0 sized aa points).
1979 * In any case, setting pointmin == pointsizemax == 1.0 for aa points
1980 * is enough to satisfy conform.
1982 case GL_POINT_SMOOTH
:
1985 /* These don't really do anything, as we don't use the 3vtx
1989 case GL_POLYGON_OFFSET_POINT
:
1990 R200_STATECHANGE( rmesa
, set
);
1992 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_POINT
;
1994 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_POINT
;
1998 case GL_POLYGON_OFFSET_LINE
:
1999 R200_STATECHANGE( rmesa
, set
);
2001 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_LINE
;
2003 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_LINE
;
2008 case GL_POINT_SPRITE_ARB
:
2009 R200_STATECHANGE( rmesa
, spr
);
2012 for (i
= 0; i
< 6; i
++) {
2013 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |=
2014 ctx
->Point
.CoordReplace
[i
] << (R200_PS_GEN_TEX_0_SHIFT
+ i
);
2017 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] &= ~R200_PS_GEN_TEX_MASK
;
2021 case GL_POLYGON_OFFSET_FILL
:
2022 R200_STATECHANGE( rmesa
, set
);
2024 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_TRI
;
2026 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_TRI
;
2030 case GL_POLYGON_SMOOTH
:
2031 R200_STATECHANGE( rmesa
, ctx
);
2033 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_POLY
;
2035 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_POLY
;
2039 case GL_POLYGON_STIPPLE
:
2040 R200_STATECHANGE(rmesa
, set
);
2042 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_STIPPLE_ENABLE
;
2044 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_STIPPLE_ENABLE
;
2048 case GL_RESCALE_NORMAL_EXT
: {
2049 GLboolean tmp
= ctx
->_NeedEyeCoords
? state
: !state
;
2050 R200_STATECHANGE( rmesa
, tcl
);
2052 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
2054 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
2059 case GL_SCISSOR_TEST
:
2060 R200_FIREVERTICES( rmesa
);
2061 rmesa
->radeon
.state
.scissor
.enabled
= state
;
2062 radeonUpdateScissor( ctx
);
2065 case GL_STENCIL_TEST
:
2066 if ( rmesa
->radeon
.state
.stencil
.hwBuffer
) {
2067 R200_STATECHANGE( rmesa
, ctx
);
2069 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_STENCIL_ENABLE
;
2071 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_STENCIL_ENABLE
;
2074 FALLBACK( rmesa
, R200_FALLBACK_STENCIL
, state
);
2078 case GL_TEXTURE_GEN_Q
:
2079 case GL_TEXTURE_GEN_R
:
2080 case GL_TEXTURE_GEN_S
:
2081 case GL_TEXTURE_GEN_T
:
2082 /* Picked up in r200UpdateTextureState.
2084 rmesa
->recheck_texgen
[ctx
->Texture
.CurrentUnit
] = GL_TRUE
;
2087 case GL_COLOR_SUM_EXT
:
2088 r200UpdateSpecular ( ctx
);
2091 case GL_VERTEX_PROGRAM_ARB
:
2094 rmesa
->curr_vp_hw
= NULL
;
2095 R200_STATECHANGE( rmesa
, vap
);
2096 rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
] &= ~R200_VAP_PROG_VTX_SHADER_ENABLE
;
2097 /* mark all tcl atoms (tcl vector state got overwritten) dirty
2098 not sure about tcl scalar state - we need at least grd
2099 with vert progs too.
2100 ucp looks like it doesn't get overwritten (may even work
2101 with vp for pos-invariant progs if we're lucky) */
2102 R200_STATECHANGE( rmesa
, mtl
[0] );
2103 R200_STATECHANGE( rmesa
, mtl
[1] );
2104 R200_STATECHANGE( rmesa
, fog
);
2105 R200_STATECHANGE( rmesa
, glt
);
2106 R200_STATECHANGE( rmesa
, eye
);
2107 for (i
= R200_MTX_MV
; i
<= R200_MTX_TEX5
; i
++) {
2108 R200_STATECHANGE( rmesa
, mat
[i
] );
2110 for (i
= 0 ; i
< 8; i
++) {
2111 R200_STATECHANGE( rmesa
, lit
[i
] );
2113 R200_STATECHANGE( rmesa
, tcl
);
2114 for (i
= 0; i
<= ctx
->Const
.MaxClipPlanes
; i
++) {
2115 if (ctx
->Transform
.ClipPlanesEnabled
& (1 << i
)) {
2116 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= (R200_UCP_ENABLE_0
<< i
);
2119 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0 << i);
2122 /* ugly. Need to call everything which might change compsel. */
2123 r200UpdateSpecular( ctx
);
2125 /* shouldn't be necessary, as it's picked up anyway in r200ValidateState (_NEW_PROGRAM),
2126 but without it doom3 locks up at always the same places. Why? */
2127 /* FIXME: This can (and should) be replaced by a call to the TCL_STATE_FLUSH reg before
2128 accessing VAP_SE_VAP_CNTL. Requires drm changes (done). Remove after some time... */
2129 r200UpdateTextureState( ctx
);
2130 /* if we call r200UpdateTextureState we need the code below because we are calling it with
2131 non-current derived enabled values which may revert the state atoms for frag progs even when
2132 they already got disabled... ugh
2133 Should really figure out why we need to call r200UpdateTextureState in the first place */
2135 for (unit
= 0; unit
< R200_MAX_TEXTURE_UNITS
; unit
++) {
2136 R200_STATECHANGE( rmesa
, pix
[unit
] );
2137 R200_STATECHANGE( rmesa
, tex
[unit
] );
2138 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] &=
2139 ~(R200_TXFORMAT_ST_ROUTE_MASK
| R200_TXFORMAT_LOOKUP_DISABLE
);
2140 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] |= unit
<< R200_TXFORMAT_ST_ROUTE_SHIFT
;
2141 /* need to guard this with drmSupportsFragmentShader? Should never get here if
2142 we don't announce ATI_fs, right? */
2143 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXMULTI_CTL
] = 0;
2145 R200_STATECHANGE( rmesa
, cst
);
2146 R200_STATECHANGE( rmesa
, tf
);
2147 rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] = 0;
2151 /* picked up later */
2153 /* call functions which change hw state based on ARB_vp enabled or not. */
2154 r200PointParameter( ctx
, GL_POINT_DISTANCE_ATTENUATION
, NULL
);
2155 r200Fogfv( ctx
, GL_FOG_COORD_SRC
, NULL
);
2158 case GL_VERTEX_PROGRAM_POINT_SIZE_ARB
:
2159 r200PointParameter( ctx
, GL_POINT_DISTANCE_ATTENUATION
, NULL
);
2162 case GL_FRAGMENT_SHADER_ATI
:
2164 /* restore normal tex env colors and make sure tex env combine will get updated
2165 mark env atoms dirty (as their data was overwritten by afs even
2166 if they didn't change) and restore tex coord routing */
2168 for (unit
= 0; unit
< R200_MAX_TEXTURE_UNITS
; unit
++) {
2169 R200_STATECHANGE( rmesa
, pix
[unit
] );
2170 R200_STATECHANGE( rmesa
, tex
[unit
] );
2171 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] &=
2172 ~(R200_TXFORMAT_ST_ROUTE_MASK
| R200_TXFORMAT_LOOKUP_DISABLE
);
2173 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] |= unit
<< R200_TXFORMAT_ST_ROUTE_SHIFT
;
2174 /* need to guard this with drmSupportsFragmentShader? Should never get here if
2175 we don't announce ATI_fs, right? */
2176 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXMULTI_CTL
] = 0;
2178 R200_STATECHANGE( rmesa
, cst
);
2179 R200_STATECHANGE( rmesa
, tf
);
2180 rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] = 0;
2183 /* need to mark this dirty as pix/tf atoms have overwritten the data
2184 even if the data in the atoms didn't change */
2185 R200_STATECHANGE( rmesa
, atf
);
2186 R200_STATECHANGE( rmesa
, afs
[1] );
2187 /* everything else picked up in r200UpdateTextureState hopefully */
2196 void r200LightingSpaceChange( GLcontext
*ctx
)
2198 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2201 if (R200_DEBUG
& DEBUG_STATE
)
2202 fprintf(stderr
, "%s %d BEFORE %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
2203 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
2205 if (ctx
->_NeedEyeCoords
)
2206 tmp
= ctx
->Transform
.RescaleNormals
;
2208 tmp
= !ctx
->Transform
.RescaleNormals
;
2210 R200_STATECHANGE( rmesa
, tcl
);
2212 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
2214 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
2217 if (R200_DEBUG
& DEBUG_STATE
)
2218 fprintf(stderr
, "%s %d AFTER %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
2219 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
2222 /* =============================================================
2223 * Deferred state management - matrices, textures, other?
2229 static void upload_matrix( r200ContextPtr rmesa
, GLfloat
*src
, int idx
)
2231 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
2235 for (i
= 0 ; i
< 4 ; i
++) {
2239 *dest
++ = src
[i
+12];
2242 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
2245 static void upload_matrix_t( r200ContextPtr rmesa
, const GLfloat
*src
, int idx
)
2247 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
2248 memcpy(dest
, src
, 16*sizeof(float));
2249 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
2253 static void update_texturematrix( GLcontext
*ctx
)
2255 r200ContextPtr rmesa
= R200_CONTEXT( ctx
);
2256 GLuint tpc
= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
];
2257 GLuint compsel
= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
];
2260 if (R200_DEBUG
& DEBUG_STATE
)
2261 fprintf(stderr
, "%s before COMPSEL: %x\n", __FUNCTION__
,
2262 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]);
2264 rmesa
->TexMatEnabled
= 0;
2265 rmesa
->TexMatCompSel
= 0;
2267 for (unit
= 0 ; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
2268 if (!ctx
->Texture
.Unit
[unit
]._ReallyEnabled
)
2271 if (ctx
->TextureMatrixStack
[unit
].Top
->type
!= MATRIX_IDENTITY
) {
2272 rmesa
->TexMatEnabled
|= (R200_TEXGEN_TEXMAT_0_ENABLE
|
2273 R200_TEXMAT_0_ENABLE
) << unit
;
2275 rmesa
->TexMatCompSel
|= R200_OUTPUT_TEX_0
<< unit
;
2277 if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2278 /* Need to preconcatenate any active texgen
2279 * obj/eyeplane matrices:
2281 _math_matrix_mul_matrix( &rmesa
->tmpmat
,
2282 ctx
->TextureMatrixStack
[unit
].Top
,
2283 &rmesa
->TexGenMatrix
[unit
] );
2284 upload_matrix( rmesa
, rmesa
->tmpmat
.m
, R200_MTX_TEX0
+unit
);
2287 upload_matrix( rmesa
, ctx
->TextureMatrixStack
[unit
].Top
->m
,
2288 R200_MTX_TEX0
+unit
);
2291 else if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2292 upload_matrix( rmesa
, rmesa
->TexGenMatrix
[unit
].m
,
2293 R200_MTX_TEX0
+unit
);
2297 tpc
= (rmesa
->TexMatEnabled
| rmesa
->TexGenEnabled
);
2298 if (tpc
!= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
]) {
2299 R200_STATECHANGE(rmesa
, tcg
);
2300 rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
] = tpc
;
2303 compsel
&= ~R200_OUTPUT_TEX_MASK
;
2304 compsel
|= rmesa
->TexMatCompSel
| rmesa
->TexGenCompSel
;
2305 if (compsel
!= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]) {
2306 R200_STATECHANGE(rmesa
, vtx
);
2307 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] = compsel
;
2314 * Tell the card where to render (offset, pitch).
2315 * Effected by glDrawBuffer, etc
2318 r200UpdateDrawBuffer(GLcontext
*ctx
)
2320 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2321 struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
2322 struct radeon_renderbuffer
*rrb
;
2324 if (fb
->_ColorDrawBufferIndexes
[0] == BUFFER_FRONT_LEFT
) {
2326 rrb
= (void *) fb
->Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
;
2327 } else if (fb
->_ColorDrawBufferIndexes
[0] == BUFFER_BACK_LEFT
) {
2329 rrb
= (void *) fb
->Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
;
2331 /* drawing to multiple buffers, or none */
2338 R200_STATECHANGE( rmesa
, ctx
);
2341 /* Note: we used the (possibly) page-flipped values */
2342 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLOROFFSET
]
2343 = ((rrb
->flippedOffset
+ rmesa
->radeon
.radeonScreen
->fbLocation
)
2344 & R200_COLOROFFSET_MASK
);
2345 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLORPITCH
] = drb
->flippedPitch
;
2346 if (rmesa
->radeon
.sarea
->tiling_enabled
) {
2347 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLORPITCH
] |= R200_COLOR_TILE_ENABLE
;
2352 static GLboolean
r200ValidateBuffers(GLcontext
*ctx
)
2354 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2355 struct radeon_cs_space_check bos
[8];
2356 struct radeon_renderbuffer
*rrb
;
2359 int flushed
= 0, ret
;
2363 rrb
= radeon_get_colorbuffer(&rmesa
->radeon
);
2365 if (rrb
&& rrb
->bo
) {
2366 bos
[num_bo
].bo
= rrb
->bo
;
2367 bos
[num_bo
].read_domains
= 0;
2368 bos
[num_bo
].write_domain
= RADEON_GEM_DOMAIN_VRAM
;
2369 bos
[num_bo
].new_accounted
= 0;
2374 rrb
= radeon_get_depthbuffer(&rmesa
->radeon
);
2376 if (rrb
&& rrb
->bo
) {
2377 bos
[num_bo
].bo
= rrb
->bo
;
2378 bos
[num_bo
].read_domains
= 0;
2379 bos
[num_bo
].write_domain
= RADEON_GEM_DOMAIN_VRAM
;
2380 bos
[num_bo
].new_accounted
= 0;
2384 for (i
= 0; i
< ctx
->Const
.MaxTextureImageUnits
; ++i
) {
2387 if (!ctx
->Texture
.Unit
[i
]._ReallyEnabled
)
2390 t
= radeon_tex_obj(ctx
->Texture
.Unit
[i
]._Current
);
2391 bos
[num_bo
].bo
= t
->mt
->bo
;
2392 bos
[num_bo
].read_domains
= RADEON_GEM_DOMAIN_GTT
| RADEON_GEM_DOMAIN_VRAM
;
2393 bos
[num_bo
].write_domain
= 0;
2394 bos
[num_bo
].new_accounted
= 0;
2398 ret
= radeon_cs_space_check(rmesa
->radeon
.cmdbuf
.cs
, bos
, num_bo
);
2399 if (ret
== RADEON_CS_SPACE_OP_TO_BIG
)
2401 if (ret
== RADEON_CS_SPACE_FLUSH
) {
2411 GLboolean
r200ValidateState( GLcontext
*ctx
)
2413 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2414 GLuint new_state
= rmesa
->radeon
.NewGLState
;
2416 if (new_state
& (_NEW_BUFFERS
| _NEW_COLOR
| _NEW_PIXEL
)) {
2417 r200UpdateDrawBuffer(ctx
);
2420 if (new_state
& (_NEW_TEXTURE
| _NEW_PROGRAM
)) {
2421 r200UpdateTextureState( ctx
);
2422 new_state
|= rmesa
->radeon
.NewGLState
; /* may add TEXTURE_MATRIX */
2423 r200UpdateLocalViewer( ctx
);
2426 /* we need to do a space check here */
2427 if (!r200ValidateBuffers(ctx
))
2430 /* FIXME: don't really need most of these when vertex progs are enabled */
2432 /* Need an event driven matrix update?
2434 if (new_state
& (_NEW_MODELVIEW
|_NEW_PROJECTION
))
2435 upload_matrix( rmesa
, ctx
->_ModelProjectMatrix
.m
, R200_MTX_MVP
);
2437 /* Need these for lighting (shouldn't upload otherwise)
2439 if (new_state
& (_NEW_MODELVIEW
)) {
2440 upload_matrix( rmesa
, ctx
->ModelviewMatrixStack
.Top
->m
, R200_MTX_MV
);
2441 upload_matrix_t( rmesa
, ctx
->ModelviewMatrixStack
.Top
->inv
, R200_MTX_IMV
);
2444 /* Does this need to be triggered on eg. modelview for
2445 * texgen-derived objplane/eyeplane matrices?
2447 if (new_state
& (_NEW_TEXTURE
|_NEW_TEXTURE_MATRIX
)) {
2448 update_texturematrix( ctx
);
2451 if (new_state
& (_NEW_LIGHT
|_NEW_MODELVIEW
|_MESA_NEW_NEED_EYE_COORDS
)) {
2452 update_light( ctx
);
2455 /* emit all active clip planes if projection matrix changes.
2457 if (new_state
& (_NEW_PROJECTION
)) {
2458 if (ctx
->Transform
.ClipPlanesEnabled
)
2459 r200UpdateClipPlanes( ctx
);
2462 if (new_state
& (_NEW_PROGRAM
|
2463 /* need to test for pretty much anything due to possible parameter bindings */
2464 _NEW_MODELVIEW
|_NEW_PROJECTION
|_NEW_TRANSFORM
|
2465 _NEW_LIGHT
|_NEW_TEXTURE
|_NEW_TEXTURE_MATRIX
|
2466 _NEW_FOG
|_NEW_POINT
|_NEW_TRACK_MATRIX
)) {
2467 if (ctx
->VertexProgram
._Enabled
) {
2468 r200SetupVertexProg( ctx
);
2470 else TCL_FALLBACK(ctx
, R200_TCL_FALLBACK_VERTEX_PROGRAM
, 0);
2473 rmesa
->radeon
.NewGLState
= 0;
2478 static void r200InvalidateState( GLcontext
*ctx
, GLuint new_state
)
2480 _swrast_InvalidateState( ctx
, new_state
);
2481 _swsetup_InvalidateState( ctx
, new_state
);
2482 _vbo_InvalidateState( ctx
, new_state
);
2483 _tnl_InvalidateState( ctx
, new_state
);
2484 _ae_invalidate_state( ctx
, new_state
);
2485 R200_CONTEXT(ctx
)->radeon
.NewGLState
|= new_state
;
2488 /* A hack. The r200 can actually cope just fine with materials
2489 * between begin/ends, so fix this.
2490 * Should map to inputs just like the generic vertex arrays for vertex progs.
2491 * In theory there could still be too many and we'd still need a fallback.
2493 static GLboolean
check_material( GLcontext
*ctx
)
2495 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
2498 for (i
= _TNL_ATTRIB_MAT_FRONT_AMBIENT
;
2499 i
< _TNL_ATTRIB_MAT_BACK_INDEXES
;
2501 if (tnl
->vb
.AttribPtr
[i
] &&
2502 tnl
->vb
.AttribPtr
[i
]->stride
)
2508 static void r200WrapRunPipeline( GLcontext
*ctx
)
2510 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2511 GLboolean has_material
;
2514 fprintf(stderr
, "%s, newstate: %x\n", __FUNCTION__
, rmesa
->radeon
.NewGLState
);
2518 if (rmesa
->radeon
.NewGLState
)
2519 if (!r200ValidateState( ctx
))
2520 FALLBACK(rmesa
, RADEON_FALLBACK_TEXTURE
, GL_TRUE
);
2522 has_material
= !ctx
->VertexProgram
._Enabled
&& ctx
->Light
.Enabled
&& check_material( ctx
);
2525 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_TRUE
);
2528 /* Run the pipeline.
2530 _tnl_run_pipeline( ctx
);
2533 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_FALSE
);
2538 /* Initialize the driver's state functions.
2540 void r200InitStateFuncs( struct dd_function_table
*functions
)
2542 functions
->UpdateState
= r200InvalidateState
;
2543 functions
->LightingSpaceChange
= r200LightingSpaceChange
;
2545 functions
->DrawBuffer
= r200DrawBuffer
;
2546 functions
->ReadBuffer
= r200ReadBuffer
;
2548 functions
->AlphaFunc
= r200AlphaFunc
;
2549 functions
->BlendColor
= r200BlendColor
;
2550 functions
->BlendEquationSeparate
= r200BlendEquationSeparate
;
2551 functions
->BlendFuncSeparate
= r200BlendFuncSeparate
;
2552 functions
->ClearColor
= r200ClearColor
;
2553 functions
->ClearDepth
= r200ClearDepth
;
2554 functions
->ClearIndex
= NULL
;
2555 functions
->ClearStencil
= r200ClearStencil
;
2556 functions
->ClipPlane
= r200ClipPlane
;
2557 functions
->ColorMask
= r200ColorMask
;
2558 functions
->CullFace
= r200CullFace
;
2559 functions
->DepthFunc
= r200DepthFunc
;
2560 functions
->DepthMask
= r200DepthMask
;
2561 functions
->DepthRange
= r200DepthRange
;
2562 functions
->Enable
= r200Enable
;
2563 functions
->Fogfv
= r200Fogfv
;
2564 functions
->FrontFace
= r200FrontFace
;
2565 functions
->Hint
= NULL
;
2566 functions
->IndexMask
= NULL
;
2567 functions
->LightModelfv
= r200LightModelfv
;
2568 functions
->Lightfv
= r200Lightfv
;
2569 functions
->LineStipple
= r200LineStipple
;
2570 functions
->LineWidth
= r200LineWidth
;
2571 functions
->LogicOpcode
= r200LogicOpCode
;
2572 functions
->PolygonMode
= r200PolygonMode
;
2573 functions
->PolygonOffset
= r200PolygonOffset
;
2574 functions
->PolygonStipple
= r200PolygonStipple
;
2575 functions
->PointParameterfv
= r200PointParameter
;
2576 functions
->PointSize
= r200PointSize
;
2577 functions
->RenderMode
= r200RenderMode
;
2578 functions
->Scissor
= r200Scissor
;
2579 functions
->ShadeModel
= r200ShadeModel
;
2580 functions
->StencilFuncSeparate
= r200StencilFuncSeparate
;
2581 functions
->StencilMaskSeparate
= r200StencilMaskSeparate
;
2582 functions
->StencilOpSeparate
= r200StencilOpSeparate
;
2583 functions
->Viewport
= r200Viewport
;
2587 void r200InitTnlFuncs( GLcontext
*ctx
)
2589 TNL_CONTEXT(ctx
)->Driver
.NotifyMaterialChange
= r200UpdateMaterial
;
2590 TNL_CONTEXT(ctx
)->Driver
.RunPipeline
= r200WrapRunPipeline
;