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
;
527 /* =============================================================
531 static void r200CullFace( GLcontext
*ctx
, GLenum unused
)
533 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
534 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
535 GLuint t
= rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
];
537 s
|= R200_FFACE_SOLID
| R200_BFACE_SOLID
;
538 t
&= ~(R200_CULL_FRONT
| R200_CULL_BACK
);
540 if ( ctx
->Polygon
.CullFlag
) {
541 switch ( ctx
->Polygon
.CullFaceMode
) {
543 s
&= ~R200_FFACE_SOLID
;
544 t
|= R200_CULL_FRONT
;
547 s
&= ~R200_BFACE_SOLID
;
550 case GL_FRONT_AND_BACK
:
551 s
&= ~(R200_FFACE_SOLID
| R200_BFACE_SOLID
);
552 t
|= (R200_CULL_FRONT
| R200_CULL_BACK
);
557 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
558 R200_STATECHANGE(rmesa
, set
);
559 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
562 if ( rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] != t
) {
563 R200_STATECHANGE(rmesa
, tcl
);
564 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] = t
;
568 static void r200FrontFace( GLcontext
*ctx
, GLenum mode
)
570 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
572 R200_STATECHANGE( rmesa
, set
);
573 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_FFACE_CULL_DIR_MASK
;
575 R200_STATECHANGE( rmesa
, tcl
);
576 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_CULL_FRONT_IS_CCW
;
580 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_FFACE_CULL_CW
;
583 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_FFACE_CULL_CCW
;
584 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_CULL_FRONT_IS_CCW
;
589 /* =============================================================
592 static void r200PointSize( GLcontext
*ctx
, GLfloat size
)
594 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
595 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.ptp
.cmd
;
597 R200_STATECHANGE( rmesa
, cst
);
598 R200_STATECHANGE( rmesa
, ptp
);
599 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] &= ~0xffff;
600 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] |= ((GLuint
)(ctx
->Point
.Size
* 16.0));
601 /* this is the size param of the point size calculation (point size reg value
602 is not used when calculation is active). */
603 fcmd
[PTP_VPORT_SCALE_PTSIZE
] = ctx
->Point
.Size
;
606 static void r200PointParameter( GLcontext
*ctx
, GLenum pname
, const GLfloat
*params
)
608 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
609 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.ptp
.cmd
;
612 case GL_POINT_SIZE_MIN
:
613 /* Can clamp both in tcl and setup - just set both (as does fglrx) */
614 R200_STATECHANGE( rmesa
, lin
);
615 R200_STATECHANGE( rmesa
, ptp
);
616 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] &= 0xffff;
617 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] |= (GLuint
)(ctx
->Point
.MinSize
* 16.0) << 16;
618 fcmd
[PTP_CLAMP_MIN
] = ctx
->Point
.MinSize
;
620 case GL_POINT_SIZE_MAX
:
621 R200_STATECHANGE( rmesa
, cst
);
622 R200_STATECHANGE( rmesa
, ptp
);
623 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] &= 0xffff;
624 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] |= (GLuint
)(ctx
->Point
.MaxSize
* 16.0) << 16;
625 fcmd
[PTP_CLAMP_MAX
] = ctx
->Point
.MaxSize
;
627 case GL_POINT_DISTANCE_ATTENUATION
:
628 R200_STATECHANGE( rmesa
, vtx
);
629 R200_STATECHANGE( rmesa
, spr
);
630 R200_STATECHANGE( rmesa
, ptp
);
631 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.ptp
.cmd
;
632 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] &=
633 ~(R200_PS_MULT_MASK
| R200_PS_LIN_ATT_ZERO
| R200_PS_SE_SEL_STATE
);
634 /* can't rely on ctx->Point._Attenuated here and test for NEW_POINT in
635 r200ValidateState looks like overkill */
636 if (ctx
->Point
.Params
[0] != 1.0 ||
637 ctx
->Point
.Params
[1] != 0.0 ||
638 ctx
->Point
.Params
[2] != 0.0 ||
639 (ctx
->VertexProgram
.Enabled
&& ctx
->VertexProgram
.PointSizeEnabled
)) {
640 /* all we care for vp would be the ps_se_sel_state setting */
641 fcmd
[PTP_ATT_CONST_QUAD
] = ctx
->Point
.Params
[2];
642 fcmd
[PTP_ATT_CONST_LIN
] = ctx
->Point
.Params
[1];
643 fcmd
[PTP_ATT_CONST_CON
] = ctx
->Point
.Params
[0];
644 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |= R200_PS_MULT_ATTENCONST
;
645 if (ctx
->Point
.Params
[1] == 0.0)
646 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |= R200_PS_LIN_ATT_ZERO
;
647 /* FIXME: setting this here doesn't look quite ok - we only want to do
648 that if we're actually drawing points probably */
649 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_PT_SIZE
;
650 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |= R200_VTX_POINT_SIZE
;
653 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |=
654 R200_PS_SE_SEL_STATE
| R200_PS_MULT_CONST
;
655 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_PT_SIZE
;
656 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~R200_VTX_POINT_SIZE
;
659 case GL_POINT_FADE_THRESHOLD_SIZE
:
660 /* don't support multisampling, so doesn't matter. */
662 /* can't do these but don't need them.
663 case GL_POINT_SPRITE_R_MODE_NV:
664 case GL_POINT_SPRITE_COORD_ORIGIN: */
666 fprintf(stderr
, "bad pname parameter in r200PointParameter\n");
671 /* =============================================================
674 static void r200LineWidth( GLcontext
*ctx
, GLfloat widthf
)
676 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
678 R200_STATECHANGE( rmesa
, lin
);
679 R200_STATECHANGE( rmesa
, set
);
681 /* Line width is stored in U6.4 format.
682 * Same min/max limits for AA, non-AA lines.
684 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] &= ~0xffff;
685 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] |= (GLuint
)
686 (CLAMP(widthf
, ctx
->Const
.MinLineWidth
, ctx
->Const
.MaxLineWidth
) * 16.0);
688 if ( widthf
> 1.0 ) {
689 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_WIDELINE_ENABLE
;
691 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_WIDELINE_ENABLE
;
695 static void r200LineStipple( GLcontext
*ctx
, GLint factor
, GLushort pattern
)
697 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
699 R200_STATECHANGE( rmesa
, lin
);
700 rmesa
->hw
.lin
.cmd
[LIN_RE_LINE_PATTERN
] =
701 ((((GLuint
)factor
& 0xff) << 16) | ((GLuint
)pattern
));
705 /* =============================================================
708 static void r200ColorMask( GLcontext
*ctx
,
709 GLboolean r
, GLboolean g
,
710 GLboolean b
, GLboolean a
)
712 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
713 GLuint mask
= radeonPackColor( rmesa
->radeon
.radeonScreen
->cpp
,
714 ctx
->Color
.ColorMask
[RCOMP
],
715 ctx
->Color
.ColorMask
[GCOMP
],
716 ctx
->Color
.ColorMask
[BCOMP
],
717 ctx
->Color
.ColorMask
[ACOMP
] );
719 GLuint flag
= rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] & ~R200_PLANE_MASK_ENABLE
;
721 if (!(r
&& g
&& b
&& a
))
722 flag
|= R200_PLANE_MASK_ENABLE
;
724 if ( rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] != flag
) {
725 R200_STATECHANGE( rmesa
, ctx
);
726 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = flag
;
729 if ( rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
] != mask
) {
730 R200_STATECHANGE( rmesa
, msk
);
731 rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
] = mask
;
736 /* =============================================================
740 static void r200PolygonOffset( GLcontext
*ctx
,
741 GLfloat factor
, GLfloat units
)
743 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
744 float_ui32_type constant
= { units
* rmesa
->radeon
.state
.depth
.scale
};
745 float_ui32_type factoru
= { factor
};
750 /* fprintf(stderr, "%s f:%f u:%f\n", __FUNCTION__, factor, constant); */
752 R200_STATECHANGE( rmesa
, zbs
);
753 rmesa
->hw
.zbs
.cmd
[ZBS_SE_ZBIAS_FACTOR
] = factoru
.ui32
;
754 rmesa
->hw
.zbs
.cmd
[ZBS_SE_ZBIAS_CONSTANT
] = constant
.ui32
;
757 static void r200PolygonStipple( GLcontext
*ctx
, const GLubyte
*mask
)
759 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
761 drm_radeon_stipple_t stipple
;
763 /* Must flip pattern upside down.
765 for ( i
= 0 ; i
< 32 ; i
++ ) {
766 rmesa
->state
.stipple
.mask
[31 - i
] = ((GLuint
*) mask
)[i
];
769 /* TODO: push this into cmd mechanism
771 radeon_firevertices(&rmesa
->radeon
);
772 LOCK_HARDWARE( &rmesa
->radeon
);
774 /* FIXME: Use window x,y offsets into stipple RAM.
776 stipple
.mask
= rmesa
->state
.stipple
.mask
;
777 drmCommandWrite( rmesa
->radeon
.dri
.fd
, DRM_RADEON_STIPPLE
,
778 &stipple
, sizeof(stipple
) );
779 UNLOCK_HARDWARE( &rmesa
->radeon
);
782 static void r200PolygonMode( GLcontext
*ctx
, GLenum face
, GLenum mode
)
784 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
785 GLboolean flag
= (ctx
->_TriangleCaps
& DD_TRI_UNFILLED
) != 0;
787 /* Can't generally do unfilled via tcl, but some good special
790 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_UNFILLED
, flag
);
791 if (rmesa
->radeon
.TclFallback
) {
792 r200ChooseRenderState( ctx
);
793 r200ChooseVertexState( ctx
);
798 /* =============================================================
799 * Rendering attributes
801 * We really don't want to recalculate all this every time we bind a
802 * texture. These things shouldn't change all that often, so it makes
803 * sense to break them out of the core texture state update routines.
806 /* Examine lighting and texture state to determine if separate specular
809 static void r200UpdateSpecular( GLcontext
*ctx
)
811 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
812 uint32_t p
= rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
];
814 R200_STATECHANGE( rmesa
, tcl
);
815 R200_STATECHANGE( rmesa
, vtx
);
817 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~(3<<R200_VTX_COLOR_0_SHIFT
);
818 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~(3<<R200_VTX_COLOR_1_SHIFT
);
819 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_COLOR_0
;
820 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_COLOR_1
;
821 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LIGHTING_ENABLE
;
823 p
&= ~R200_SPECULAR_ENABLE
;
825 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_DIFFUSE_SPECULAR_COMBINE
;
828 if (ctx
->Light
.Enabled
&&
829 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
) {
830 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
831 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
) |
832 (R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
833 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_0
;
834 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_1
;
835 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHTING_ENABLE
;
836 p
|= R200_SPECULAR_ENABLE
;
837 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &=
838 ~R200_DIFFUSE_SPECULAR_COMBINE
;
840 else if (ctx
->Light
.Enabled
) {
841 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
842 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
));
843 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_0
;
844 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHTING_ENABLE
;
845 } else if (ctx
->Fog
.ColorSumEnabled
) {
846 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
847 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
) |
848 (R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
849 p
|= R200_SPECULAR_ENABLE
;
851 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
852 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
));
855 if (ctx
->Fog
.Enabled
) {
856 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
857 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
858 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_1
;
861 if ( rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] != p
) {
862 R200_STATECHANGE( rmesa
, ctx
);
863 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] = p
;
866 /* Update vertex/render formats
868 if (rmesa
->radeon
.TclFallback
) {
869 r200ChooseRenderState( ctx
);
870 r200ChooseVertexState( ctx
);
875 /* =============================================================
880 /* Update on colormaterial, material emmissive/ambient,
881 * lightmodel.globalambient
883 static void update_global_ambient( GLcontext
*ctx
)
885 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
886 float *fcmd
= (float *)R200_DB_STATE( glt
);
888 /* Need to do more if both emmissive & ambient are PREMULT:
889 * I believe this is not nessary when using source_material. This condition thus
890 * will never happen currently, and the function has no dependencies on materials now
892 if ((rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
] &
893 ((3 << R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
894 (3 << R200_FRONT_AMBIENT_SOURCE_SHIFT
))) == 0)
896 COPY_3V( &fcmd
[GLT_RED
],
897 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_EMISSION
]);
898 ACC_SCALE_3V( &fcmd
[GLT_RED
],
899 ctx
->Light
.Model
.Ambient
,
900 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_AMBIENT
]);
904 COPY_3V( &fcmd
[GLT_RED
], ctx
->Light
.Model
.Ambient
);
907 R200_DB_STATECHANGE(rmesa
, &rmesa
->hw
.glt
);
910 /* Update on change to
914 static void update_light_colors( GLcontext
*ctx
, GLuint p
)
916 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
918 /* fprintf(stderr, "%s\n", __FUNCTION__); */
921 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
922 float *fcmd
= (float *)R200_DB_STATE( lit
[p
] );
924 COPY_4V( &fcmd
[LIT_AMBIENT_RED
], l
->Ambient
);
925 COPY_4V( &fcmd
[LIT_DIFFUSE_RED
], l
->Diffuse
);
926 COPY_4V( &fcmd
[LIT_SPECULAR_RED
], l
->Specular
);
928 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
932 static void r200ColorMaterial( GLcontext
*ctx
, GLenum face
, GLenum mode
)
934 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
935 GLuint light_model_ctl1
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
];
936 light_model_ctl1
&= ~((0xf << R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
937 (0xf << R200_FRONT_AMBIENT_SOURCE_SHIFT
) |
938 (0xf << R200_FRONT_DIFFUSE_SOURCE_SHIFT
) |
939 (0xf << R200_FRONT_SPECULAR_SOURCE_SHIFT
) |
940 (0xf << R200_BACK_EMISSIVE_SOURCE_SHIFT
) |
941 (0xf << R200_BACK_AMBIENT_SOURCE_SHIFT
) |
942 (0xf << R200_BACK_DIFFUSE_SOURCE_SHIFT
) |
943 (0xf << R200_BACK_SPECULAR_SOURCE_SHIFT
));
945 if (ctx
->Light
.ColorMaterialEnabled
) {
946 GLuint mask
= ctx
->Light
.ColorMaterialBitmask
;
948 if (mask
& MAT_BIT_FRONT_EMISSION
) {
949 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
950 R200_FRONT_EMISSIVE_SOURCE_SHIFT
);
953 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
954 R200_FRONT_EMISSIVE_SOURCE_SHIFT
);
956 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
957 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
958 R200_FRONT_AMBIENT_SOURCE_SHIFT
);
961 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
962 R200_FRONT_AMBIENT_SOURCE_SHIFT
);
964 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
965 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
966 R200_FRONT_DIFFUSE_SOURCE_SHIFT
);
969 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
970 R200_FRONT_DIFFUSE_SOURCE_SHIFT
);
972 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
973 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
974 R200_FRONT_SPECULAR_SOURCE_SHIFT
);
977 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
978 R200_FRONT_SPECULAR_SOURCE_SHIFT
);
981 if (mask
& MAT_BIT_BACK_EMISSION
) {
982 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
983 R200_BACK_EMISSIVE_SOURCE_SHIFT
);
986 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
987 R200_BACK_EMISSIVE_SOURCE_SHIFT
);
989 if (mask
& MAT_BIT_BACK_AMBIENT
) {
990 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
991 R200_BACK_AMBIENT_SOURCE_SHIFT
);
993 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
994 R200_BACK_AMBIENT_SOURCE_SHIFT
);
996 if (mask
& MAT_BIT_BACK_DIFFUSE
) {
997 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
998 R200_BACK_DIFFUSE_SOURCE_SHIFT
);
1000 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
1001 R200_BACK_DIFFUSE_SOURCE_SHIFT
);
1003 if (mask
& MAT_BIT_BACK_SPECULAR
) {
1004 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
1005 R200_BACK_SPECULAR_SOURCE_SHIFT
);
1008 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
1009 R200_BACK_SPECULAR_SOURCE_SHIFT
);
1013 /* Default to SOURCE_MATERIAL:
1016 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
1017 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_AMBIENT_SOURCE_SHIFT
) |
1018 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_DIFFUSE_SOURCE_SHIFT
) |
1019 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_SPECULAR_SOURCE_SHIFT
) |
1020 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_EMISSIVE_SOURCE_SHIFT
) |
1021 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_AMBIENT_SOURCE_SHIFT
) |
1022 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_DIFFUSE_SOURCE_SHIFT
) |
1023 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_SPECULAR_SOURCE_SHIFT
);
1026 if (light_model_ctl1
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
]) {
1027 R200_STATECHANGE( rmesa
, tcl
);
1028 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
] = light_model_ctl1
;
1034 void r200UpdateMaterial( GLcontext
*ctx
)
1036 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1037 GLfloat (*mat
)[4] = ctx
->Light
.Material
.Attrib
;
1038 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( mtl
[0] );
1039 GLfloat
*fcmd2
= (GLfloat
*)R200_DB_STATE( mtl
[1] );
1042 /* Might be possible and faster to update everything unconditionally? */
1043 if (ctx
->Light
.ColorMaterialEnabled
)
1044 mask
&= ~ctx
->Light
.ColorMaterialBitmask
;
1046 if (R200_DEBUG
& DEBUG_STATE
)
1047 fprintf(stderr
, "%s\n", __FUNCTION__
);
1049 if (mask
& MAT_BIT_FRONT_EMISSION
) {
1050 fcmd
[MTL_EMMISSIVE_RED
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][0];
1051 fcmd
[MTL_EMMISSIVE_GREEN
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][1];
1052 fcmd
[MTL_EMMISSIVE_BLUE
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][2];
1053 fcmd
[MTL_EMMISSIVE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][3];
1055 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
1056 fcmd
[MTL_AMBIENT_RED
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][0];
1057 fcmd
[MTL_AMBIENT_GREEN
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][1];
1058 fcmd
[MTL_AMBIENT_BLUE
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][2];
1059 fcmd
[MTL_AMBIENT_ALPHA
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][3];
1061 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
1062 fcmd
[MTL_DIFFUSE_RED
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][0];
1063 fcmd
[MTL_DIFFUSE_GREEN
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][1];
1064 fcmd
[MTL_DIFFUSE_BLUE
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][2];
1065 fcmd
[MTL_DIFFUSE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][3];
1067 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
1068 fcmd
[MTL_SPECULAR_RED
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][0];
1069 fcmd
[MTL_SPECULAR_GREEN
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][1];
1070 fcmd
[MTL_SPECULAR_BLUE
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][2];
1071 fcmd
[MTL_SPECULAR_ALPHA
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][3];
1073 if (mask
& MAT_BIT_FRONT_SHININESS
) {
1074 fcmd
[MTL_SHININESS
] = mat
[MAT_ATTRIB_FRONT_SHININESS
][0];
1077 if (mask
& MAT_BIT_BACK_EMISSION
) {
1078 fcmd2
[MTL_EMMISSIVE_RED
] = mat
[MAT_ATTRIB_BACK_EMISSION
][0];
1079 fcmd2
[MTL_EMMISSIVE_GREEN
] = mat
[MAT_ATTRIB_BACK_EMISSION
][1];
1080 fcmd2
[MTL_EMMISSIVE_BLUE
] = mat
[MAT_ATTRIB_BACK_EMISSION
][2];
1081 fcmd2
[MTL_EMMISSIVE_ALPHA
] = mat
[MAT_ATTRIB_BACK_EMISSION
][3];
1083 if (mask
& MAT_BIT_BACK_AMBIENT
) {
1084 fcmd2
[MTL_AMBIENT_RED
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][0];
1085 fcmd2
[MTL_AMBIENT_GREEN
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][1];
1086 fcmd2
[MTL_AMBIENT_BLUE
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][2];
1087 fcmd2
[MTL_AMBIENT_ALPHA
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][3];
1089 if (mask
& MAT_BIT_BACK_DIFFUSE
) {
1090 fcmd2
[MTL_DIFFUSE_RED
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][0];
1091 fcmd2
[MTL_DIFFUSE_GREEN
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][1];
1092 fcmd2
[MTL_DIFFUSE_BLUE
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][2];
1093 fcmd2
[MTL_DIFFUSE_ALPHA
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][3];
1095 if (mask
& MAT_BIT_BACK_SPECULAR
) {
1096 fcmd2
[MTL_SPECULAR_RED
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][0];
1097 fcmd2
[MTL_SPECULAR_GREEN
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][1];
1098 fcmd2
[MTL_SPECULAR_BLUE
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][2];
1099 fcmd2
[MTL_SPECULAR_ALPHA
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][3];
1101 if (mask
& MAT_BIT_BACK_SHININESS
) {
1102 fcmd2
[MTL_SHININESS
] = mat
[MAT_ATTRIB_BACK_SHININESS
][0];
1105 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mtl
[0] );
1106 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mtl
[1] );
1108 /* currently material changes cannot trigger a global ambient change, I believe this is correct
1109 update_global_ambient( ctx ); */
1114 * _MESA_NEW_NEED_EYE_COORDS
1116 * Uses derived state from mesa:
1121 * _ModelViewInvScale
1125 * which are calculated in light.c and are correct for the current
1126 * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
1127 * and _MESA_NEW_NEED_EYE_COORDS.
1129 static void update_light( GLcontext
*ctx
)
1131 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1133 /* Have to check these, or have an automatic shortcircuit mechanism
1134 * to remove noop statechanges. (Or just do a better job on the
1138 GLuint tmp
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
];
1140 if (ctx
->_NeedEyeCoords
)
1141 tmp
&= ~R200_LIGHT_IN_MODELSPACE
;
1143 tmp
|= R200_LIGHT_IN_MODELSPACE
;
1145 if (tmp
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
])
1147 R200_STATECHANGE( rmesa
, tcl
);
1148 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] = tmp
;
1153 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( eye
);
1154 fcmd
[EYE_X
] = ctx
->_EyeZDir
[0];
1155 fcmd
[EYE_Y
] = ctx
->_EyeZDir
[1];
1156 fcmd
[EYE_Z
] = - ctx
->_EyeZDir
[2];
1157 fcmd
[EYE_RESCALE_FACTOR
] = ctx
->_ModelViewInvScale
;
1158 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.eye
);
1163 if (ctx
->Light
.Enabled
) {
1165 for (p
= 0 ; p
< MAX_LIGHTS
; p
++) {
1166 if (ctx
->Light
.Light
[p
].Enabled
) {
1167 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1168 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( lit
[p
] );
1170 if (l
->EyePosition
[3] == 0.0) {
1171 COPY_3FV( &fcmd
[LIT_POSITION_X
], l
->_VP_inf_norm
);
1172 COPY_3FV( &fcmd
[LIT_DIRECTION_X
], l
->_h_inf_norm
);
1173 fcmd
[LIT_POSITION_W
] = 0;
1174 fcmd
[LIT_DIRECTION_W
] = 0;
1176 COPY_4V( &fcmd
[LIT_POSITION_X
], l
->_Position
);
1177 fcmd
[LIT_DIRECTION_X
] = -l
->_NormDirection
[0];
1178 fcmd
[LIT_DIRECTION_Y
] = -l
->_NormDirection
[1];
1179 fcmd
[LIT_DIRECTION_Z
] = -l
->_NormDirection
[2];
1180 fcmd
[LIT_DIRECTION_W
] = 0;
1183 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
1189 static void r200Lightfv( GLcontext
*ctx
, GLenum light
,
1190 GLenum pname
, const GLfloat
*params
)
1192 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1193 GLint p
= light
- GL_LIGHT0
;
1194 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1195 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.lit
[p
].cmd
;
1202 update_light_colors( ctx
, p
);
1205 case GL_SPOT_DIRECTION
:
1206 /* picked up in update_light */
1210 /* positions picked up in update_light, but can do flag here */
1211 GLuint flag
= (p
&1)? R200_LIGHT_1_IS_LOCAL
: R200_LIGHT_0_IS_LOCAL
;
1212 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1214 R200_STATECHANGE(rmesa
, tcl
);
1215 if (l
->EyePosition
[3] != 0.0F
)
1216 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1218 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1222 case GL_SPOT_EXPONENT
:
1223 R200_STATECHANGE(rmesa
, lit
[p
]);
1224 fcmd
[LIT_SPOT_EXPONENT
] = params
[0];
1227 case GL_SPOT_CUTOFF
: {
1228 GLuint flag
= (p
&1) ? R200_LIGHT_1_IS_SPOT
: R200_LIGHT_0_IS_SPOT
;
1229 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1231 R200_STATECHANGE(rmesa
, lit
[p
]);
1232 fcmd
[LIT_SPOT_CUTOFF
] = l
->_CosCutoff
;
1234 R200_STATECHANGE(rmesa
, tcl
);
1235 if (l
->SpotCutoff
!= 180.0F
)
1236 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1238 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1243 case GL_CONSTANT_ATTENUATION
:
1244 R200_STATECHANGE(rmesa
, lit
[p
]);
1245 fcmd
[LIT_ATTEN_CONST
] = params
[0];
1246 if ( params
[0] == 0.0 )
1247 fcmd
[LIT_ATTEN_CONST_INV
] = FLT_MAX
;
1249 fcmd
[LIT_ATTEN_CONST_INV
] = 1.0 / params
[0];
1251 case GL_LINEAR_ATTENUATION
:
1252 R200_STATECHANGE(rmesa
, lit
[p
]);
1253 fcmd
[LIT_ATTEN_LINEAR
] = params
[0];
1255 case GL_QUADRATIC_ATTENUATION
:
1256 R200_STATECHANGE(rmesa
, lit
[p
]);
1257 fcmd
[LIT_ATTEN_QUADRATIC
] = params
[0];
1263 /* Set RANGE_ATTEN only when needed */
1266 case GL_CONSTANT_ATTENUATION
:
1267 case GL_LINEAR_ATTENUATION
:
1268 case GL_QUADRATIC_ATTENUATION
: {
1269 GLuint
*icmd
= (GLuint
*)R200_DB_STATE( tcl
);
1270 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1271 GLuint atten_flag
= ( p
&1 ) ? R200_LIGHT_1_ENABLE_RANGE_ATTEN
1272 : R200_LIGHT_0_ENABLE_RANGE_ATTEN
;
1273 GLuint atten_const_flag
= ( p
&1 ) ? R200_LIGHT_1_CONSTANT_RANGE_ATTEN
1274 : R200_LIGHT_0_CONSTANT_RANGE_ATTEN
;
1276 if ( l
->EyePosition
[3] == 0.0F
||
1277 ( ( fcmd
[LIT_ATTEN_CONST
] == 0.0 || fcmd
[LIT_ATTEN_CONST
] == 1.0 ) &&
1278 fcmd
[LIT_ATTEN_QUADRATIC
] == 0.0 && fcmd
[LIT_ATTEN_LINEAR
] == 0.0 ) ) {
1279 /* Disable attenuation */
1280 icmd
[idx
] &= ~atten_flag
;
1282 if ( fcmd
[LIT_ATTEN_QUADRATIC
] == 0.0 && fcmd
[LIT_ATTEN_LINEAR
] == 0.0 ) {
1283 /* Enable only constant portion of attenuation calculation */
1284 icmd
[idx
] |= ( atten_flag
| atten_const_flag
);
1286 /* Enable full attenuation calculation */
1287 icmd
[idx
] &= ~atten_const_flag
;
1288 icmd
[idx
] |= atten_flag
;
1292 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.tcl
);
1300 static void r200UpdateLocalViewer ( GLcontext
*ctx
)
1302 /* It looks like for the texgen modes GL_SPHERE_MAP, GL_NORMAL_MAP and
1303 GL_REFLECTION_MAP we need R200_LOCAL_VIEWER set (fglrx does exactly that
1304 for these and only these modes). This means specular highlights may turn out
1305 wrong in some cases when lighting is enabled but GL_LIGHT_MODEL_LOCAL_VIEWER
1306 is not set, though it seems to happen rarely and the effect seems quite
1307 subtle. May need TCL fallback to fix it completely, though I'm not sure
1308 how you'd identify the cases where the specular highlights indeed will
1309 be wrong. Don't know if fglrx does something special in that case.
1311 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1312 R200_STATECHANGE( rmesa
, tcl
);
1313 if (ctx
->Light
.Model
.LocalViewer
||
1314 ctx
->Texture
._GenFlags
& TEXGEN_NEED_NORMALS
)
1315 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LOCAL_VIEWER
;
1317 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LOCAL_VIEWER
;
1320 static void r200LightModelfv( GLcontext
*ctx
, GLenum pname
,
1321 const GLfloat
*param
)
1323 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1326 case GL_LIGHT_MODEL_AMBIENT
:
1327 update_global_ambient( ctx
);
1330 case GL_LIGHT_MODEL_LOCAL_VIEWER
:
1331 r200UpdateLocalViewer( ctx
);
1334 case GL_LIGHT_MODEL_TWO_SIDE
:
1335 R200_STATECHANGE( rmesa
, tcl
);
1336 if (ctx
->Light
.Model
.TwoSide
)
1337 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHT_TWOSIDE
;
1339 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~(R200_LIGHT_TWOSIDE
);
1340 if (rmesa
->radeon
.TclFallback
) {
1341 r200ChooseRenderState( ctx
);
1342 r200ChooseVertexState( ctx
);
1346 case GL_LIGHT_MODEL_COLOR_CONTROL
:
1347 r200UpdateSpecular(ctx
);
1355 static void r200ShadeModel( GLcontext
*ctx
, GLenum mode
)
1357 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1358 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
1360 s
&= ~(R200_DIFFUSE_SHADE_MASK
|
1361 R200_ALPHA_SHADE_MASK
|
1362 R200_SPECULAR_SHADE_MASK
|
1363 R200_FOG_SHADE_MASK
|
1364 R200_DISC_FOG_SHADE_MASK
);
1368 s
|= (R200_DIFFUSE_SHADE_FLAT
|
1369 R200_ALPHA_SHADE_FLAT
|
1370 R200_SPECULAR_SHADE_FLAT
|
1371 R200_FOG_SHADE_FLAT
|
1372 R200_DISC_FOG_SHADE_FLAT
);
1375 s
|= (R200_DIFFUSE_SHADE_GOURAUD
|
1376 R200_ALPHA_SHADE_GOURAUD
|
1377 R200_SPECULAR_SHADE_GOURAUD
|
1378 R200_FOG_SHADE_GOURAUD
|
1379 R200_DISC_FOG_SHADE_GOURAUD
);
1385 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
1386 R200_STATECHANGE( rmesa
, set
);
1387 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
1392 /* =============================================================
1396 static void r200ClipPlane( GLcontext
*ctx
, GLenum plane
, const GLfloat
*eq
)
1398 GLint p
= (GLint
) plane
- (GLint
) GL_CLIP_PLANE0
;
1399 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1400 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1402 R200_STATECHANGE( rmesa
, ucp
[p
] );
1403 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1404 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1405 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1406 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1409 static void r200UpdateClipPlanes( GLcontext
*ctx
)
1411 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1414 for (p
= 0; p
< ctx
->Const
.MaxClipPlanes
; p
++) {
1415 if (ctx
->Transform
.ClipPlanesEnabled
& (1 << p
)) {
1416 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1418 R200_STATECHANGE( rmesa
, ucp
[p
] );
1419 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1420 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1421 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1422 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1428 /* =============================================================
1433 r200StencilFuncSeparate( GLcontext
*ctx
, GLenum face
, GLenum func
,
1434 GLint ref
, GLuint mask
)
1436 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1437 GLuint refmask
= (((ctx
->Stencil
.Ref
[0] & 0xff) << R200_STENCIL_REF_SHIFT
) |
1438 ((ctx
->Stencil
.ValueMask
[0] & 0xff) << R200_STENCIL_MASK_SHIFT
));
1440 R200_STATECHANGE( rmesa
, ctx
);
1441 R200_STATECHANGE( rmesa
, msk
);
1443 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_STENCIL_TEST_MASK
;
1444 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~(R200_STENCIL_REF_MASK
|
1445 R200_STENCIL_VALUE_MASK
);
1447 switch ( ctx
->Stencil
.Function
[0] ) {
1449 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEVER
;
1452 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LESS
;
1455 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_EQUAL
;
1458 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LEQUAL
;
1461 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GREATER
;
1464 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEQUAL
;
1467 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GEQUAL
;
1470 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_ALWAYS
;
1474 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |= refmask
;
1478 r200StencilMaskSeparate( GLcontext
*ctx
, GLenum face
, GLuint mask
)
1480 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1482 R200_STATECHANGE( rmesa
, msk
);
1483 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~R200_STENCIL_WRITE_MASK
;
1484 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |=
1485 ((ctx
->Stencil
.WriteMask
[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT
);
1489 r200StencilOpSeparate( GLcontext
*ctx
, GLenum face
, GLenum fail
,
1490 GLenum zfail
, GLenum zpass
)
1492 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1494 R200_STATECHANGE( rmesa
, ctx
);
1495 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~(R200_STENCIL_FAIL_MASK
|
1496 R200_STENCIL_ZFAIL_MASK
|
1497 R200_STENCIL_ZPASS_MASK
);
1499 switch ( ctx
->Stencil
.FailFunc
[0] ) {
1501 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_KEEP
;
1504 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_ZERO
;
1507 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_REPLACE
;
1510 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC
;
1513 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC
;
1515 case GL_INCR_WRAP_EXT
:
1516 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC_WRAP
;
1518 case GL_DECR_WRAP_EXT
:
1519 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC_WRAP
;
1522 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INVERT
;
1526 switch ( ctx
->Stencil
.ZFailFunc
[0] ) {
1528 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_KEEP
;
1531 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_ZERO
;
1534 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_REPLACE
;
1537 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC
;
1540 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC
;
1542 case GL_INCR_WRAP_EXT
:
1543 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC_WRAP
;
1545 case GL_DECR_WRAP_EXT
:
1546 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC_WRAP
;
1549 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INVERT
;
1553 switch ( ctx
->Stencil
.ZPassFunc
[0] ) {
1555 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_KEEP
;
1558 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_ZERO
;
1561 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_REPLACE
;
1564 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC
;
1567 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC
;
1569 case GL_INCR_WRAP_EXT
:
1570 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC_WRAP
;
1572 case GL_DECR_WRAP_EXT
:
1573 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC_WRAP
;
1576 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INVERT
;
1581 static void r200ClearStencil( GLcontext
*ctx
, GLint s
)
1583 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1585 rmesa
->radeon
.state
.stencil
.clear
=
1586 ((GLuint
) (ctx
->Stencil
.Clear
& 0xff) |
1587 (0xff << R200_STENCIL_MASK_SHIFT
) |
1588 ((ctx
->Stencil
.WriteMask
[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT
));
1592 /* =============================================================
1593 * Window position and viewport transformation
1597 * To correctly position primitives:
1599 #define SUBPIXEL_X 0.125
1600 #define SUBPIXEL_Y 0.125
1604 * Called when window size or position changes or viewport or depth range
1605 * state is changed. We update the hardware viewport state here.
1607 void r200UpdateWindow( GLcontext
*ctx
)
1609 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1610 __DRIdrawablePrivate
*dPriv
= rmesa
->radeon
.dri
.drawable
;
1611 GLfloat xoffset
= dPriv
? (GLfloat
) dPriv
->x
: 0;
1612 GLfloat yoffset
= dPriv
? (GLfloat
) dPriv
->y
+ dPriv
->h
: 0;
1613 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1615 float_ui32_type sx
= { v
[MAT_SX
] };
1616 float_ui32_type tx
= { v
[MAT_TX
] + xoffset
+ SUBPIXEL_X
};
1617 float_ui32_type sy
= { - v
[MAT_SY
] };
1618 float_ui32_type ty
= { (- v
[MAT_TY
]) + yoffset
+ SUBPIXEL_Y
};
1619 float_ui32_type sz
= { v
[MAT_SZ
] * rmesa
->radeon
.state
.depth
.scale
};
1620 float_ui32_type tz
= { v
[MAT_TZ
] * rmesa
->radeon
.state
.depth
.scale
};
1622 radeon_firevertices(&rmesa
->radeon
);
1623 R200_STATECHANGE( rmesa
, vpt
);
1625 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XSCALE
] = sx
.ui32
;
1626 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = tx
.ui32
;
1627 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YSCALE
] = sy
.ui32
;
1628 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = ty
.ui32
;
1629 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZSCALE
] = sz
.ui32
;
1630 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZOFFSET
] = tz
.ui32
;
1635 static void r200Viewport( GLcontext
*ctx
, GLint x
, GLint y
,
1636 GLsizei width
, GLsizei height
)
1638 /* Don't pipeline viewport changes, conflict with window offset
1639 * setting below. Could apply deltas to rescue pipelined viewport
1640 * values, or keep the originals hanging around.
1642 r200UpdateWindow( ctx
);
1645 static void r200DepthRange( GLcontext
*ctx
, GLclampd nearval
,
1648 r200UpdateWindow( ctx
);
1651 void r200UpdateViewportOffset( GLcontext
*ctx
)
1653 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1654 __DRIdrawablePrivate
*dPriv
= rmesa
->radeon
.dri
.drawable
;
1655 GLfloat xoffset
= (GLfloat
)dPriv
->x
;
1656 GLfloat yoffset
= (GLfloat
)dPriv
->y
+ dPriv
->h
;
1657 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1662 tx
.f
= v
[MAT_TX
] + xoffset
+ SUBPIXEL_X
;
1663 ty
.f
= (- v
[MAT_TY
]) + yoffset
+ SUBPIXEL_Y
;
1665 if ( rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] != tx
.ui32
||
1666 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] != ty
.ui32
)
1668 /* Note: this should also modify whatever data the context reset
1671 R200_STATECHANGE( rmesa
, vpt
);
1672 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = tx
.ui32
;
1673 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = ty
.ui32
;
1675 /* update polygon stipple x/y screen offset */
1678 GLuint m
= rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
];
1680 m
&= ~(R200_STIPPLE_X_OFFSET_MASK
|
1681 R200_STIPPLE_Y_OFFSET_MASK
);
1683 /* add magic offsets, then invert */
1684 stx
= 31 - ((rmesa
->radeon
.dri
.drawable
->x
- 1) & R200_STIPPLE_COORD_MASK
);
1685 sty
= 31 - ((rmesa
->radeon
.dri
.drawable
->y
+ rmesa
->radeon
.dri
.drawable
->h
- 1)
1686 & R200_STIPPLE_COORD_MASK
);
1688 m
|= ((stx
<< R200_STIPPLE_X_OFFSET_SHIFT
) |
1689 (sty
<< R200_STIPPLE_Y_OFFSET_SHIFT
));
1691 if ( rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] != m
) {
1692 R200_STATECHANGE( rmesa
, msc
);
1693 rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] = m
;
1698 radeonUpdateScissor( ctx
);
1703 /* =============================================================
1707 static void r200ClearColor( GLcontext
*ctx
, const GLfloat c
[4] )
1709 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1711 CLAMPED_FLOAT_TO_UBYTE(color
[0], c
[0]);
1712 CLAMPED_FLOAT_TO_UBYTE(color
[1], c
[1]);
1713 CLAMPED_FLOAT_TO_UBYTE(color
[2], c
[2]);
1714 CLAMPED_FLOAT_TO_UBYTE(color
[3], c
[3]);
1715 rmesa
->radeon
.state
.color
.clear
= radeonPackColor( rmesa
->radeon
.radeonScreen
->cpp
,
1717 color
[2], color
[3] );
1721 static void r200RenderMode( GLcontext
*ctx
, GLenum mode
)
1723 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1724 FALLBACK( rmesa
, R200_FALLBACK_RENDER_MODE
, (mode
!= GL_RENDER
) );
1728 static GLuint r200_rop_tab
[] = {
1731 R200_ROP_AND_REVERSE
,
1733 R200_ROP_AND_INVERTED
,
1740 R200_ROP_OR_REVERSE
,
1741 R200_ROP_COPY_INVERTED
,
1742 R200_ROP_OR_INVERTED
,
1747 static void r200LogicOpCode( GLcontext
*ctx
, GLenum opcode
)
1749 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1750 GLuint rop
= (GLuint
)opcode
- GL_CLEAR
;
1754 R200_STATECHANGE( rmesa
, msk
);
1755 rmesa
->hw
.msk
.cmd
[MSK_RB3D_ROPCNTL
] = r200_rop_tab
[rop
];
1759 static void r200DrawBuffer( GLcontext
*ctx
, GLenum mode
)
1761 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1763 if (R200_DEBUG
& DEBUG_DRI
)
1764 fprintf(stderr
, "%s %s\n", __FUNCTION__
,
1765 _mesa_lookup_enum_by_nr( mode
));
1767 radeon_firevertices(&rmesa
->radeon
); /* don't pipeline cliprect changes */
1769 if (ctx
->DrawBuffer
->_NumColorDrawBuffers
!= 1) {
1770 /* 0 (GL_NONE) buffers or multiple color drawing buffers */
1771 FALLBACK( rmesa
, R200_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
1775 switch ( ctx
->DrawBuffer
->_ColorDrawBufferIndexes
[0] ) {
1776 case BUFFER_FRONT_LEFT
:
1777 case BUFFER_BACK_LEFT
:
1778 FALLBACK( rmesa
, R200_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
1781 FALLBACK( rmesa
, R200_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
1785 radeonSetCliprects( &rmesa
->radeon
);
1786 radeonUpdatePageFlipping(&rmesa
->radeon
);
1788 /* We'll set the drawing engine's offset/pitch parameters later
1789 * when we update other state.
1794 static void r200ReadBuffer( GLcontext
*ctx
, GLenum mode
)
1796 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
1799 /* =============================================================
1800 * State enable/disable
1803 static void r200Enable( GLcontext
*ctx
, GLenum cap
, GLboolean state
)
1805 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1808 if ( R200_DEBUG
& DEBUG_STATE
)
1809 fprintf( stderr
, "%s( %s = %s )\n", __FUNCTION__
,
1810 _mesa_lookup_enum_by_nr( cap
),
1811 state
? "GL_TRUE" : "GL_FALSE" );
1814 /* Fast track this one...
1822 R200_STATECHANGE( rmesa
, ctx
);
1824 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ALPHA_TEST_ENABLE
;
1826 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ALPHA_TEST_ENABLE
;
1831 case GL_COLOR_LOGIC_OP
:
1832 r200_set_blend_state( ctx
);
1835 case GL_CLIP_PLANE0
:
1836 case GL_CLIP_PLANE1
:
1837 case GL_CLIP_PLANE2
:
1838 case GL_CLIP_PLANE3
:
1839 case GL_CLIP_PLANE4
:
1840 case GL_CLIP_PLANE5
:
1841 p
= cap
-GL_CLIP_PLANE0
;
1842 R200_STATECHANGE( rmesa
, tcl
);
1844 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= (R200_UCP_ENABLE_0
<<p
);
1845 r200ClipPlane( ctx
, cap
, NULL
);
1848 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~(R200_UCP_ENABLE_0
<<p
);
1852 case GL_COLOR_MATERIAL
:
1853 r200ColorMaterial( ctx
, 0, 0 );
1854 r200UpdateMaterial( ctx
);
1858 r200CullFace( ctx
, 0 );
1862 R200_STATECHANGE(rmesa
, ctx
);
1864 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_Z_ENABLE
;
1866 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_Z_ENABLE
;
1871 R200_STATECHANGE(rmesa
, ctx
);
1873 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_DITHER_ENABLE
;
1874 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~rmesa
->radeon
.state
.color
.roundEnable
;
1876 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_DITHER_ENABLE
;
1877 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= rmesa
->radeon
.state
.color
.roundEnable
;
1882 R200_STATECHANGE(rmesa
, ctx
);
1884 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_FOG_ENABLE
;
1885 r200Fogfv( ctx
, GL_FOG_MODE
, NULL
);
1887 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_FOG_ENABLE
;
1888 R200_STATECHANGE(rmesa
, tcl
);
1889 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_TCL_FOG_MASK
;
1891 r200UpdateSpecular( ctx
); /* for PK_SPEC */
1892 if (rmesa
->radeon
.TclFallback
)
1893 r200ChooseVertexState( ctx
);
1894 _mesa_allow_light_in_model( ctx
, !state
);
1905 R200_STATECHANGE(rmesa
, tcl
);
1906 p
= cap
- GL_LIGHT0
;
1908 flag
= (R200_LIGHT_1_ENABLE
|
1909 R200_LIGHT_1_ENABLE_AMBIENT
|
1910 R200_LIGHT_1_ENABLE_SPECULAR
);
1912 flag
= (R200_LIGHT_0_ENABLE
|
1913 R200_LIGHT_0_ENABLE_AMBIENT
|
1914 R200_LIGHT_0_ENABLE_SPECULAR
);
1917 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] |= flag
;
1919 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] &= ~flag
;
1923 update_light_colors( ctx
, p
);
1927 r200UpdateSpecular(ctx
);
1928 /* for reflection map fixup - might set recheck_texgen for all units too */
1929 rmesa
->radeon
.NewGLState
|= _NEW_TEXTURE
;
1932 case GL_LINE_SMOOTH
:
1933 R200_STATECHANGE( rmesa
, ctx
);
1935 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_LINE
;
1937 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_LINE
;
1941 case GL_LINE_STIPPLE
:
1942 R200_STATECHANGE( rmesa
, set
);
1944 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_PATTERN_ENABLE
;
1946 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_PATTERN_ENABLE
;
1951 R200_STATECHANGE( rmesa
, tcl
);
1953 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_NORMALIZE_NORMALS
;
1955 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_NORMALIZE_NORMALS
;
1959 /* Pointsize registers on r200 only work for point sprites, and point smooth
1960 * doesn't work for point sprites (and isn't needed for 1.0 sized aa points).
1961 * In any case, setting pointmin == pointsizemax == 1.0 for aa points
1962 * is enough to satisfy conform.
1964 case GL_POINT_SMOOTH
:
1967 /* These don't really do anything, as we don't use the 3vtx
1971 case GL_POLYGON_OFFSET_POINT
:
1972 R200_STATECHANGE( rmesa
, set
);
1974 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_POINT
;
1976 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_POINT
;
1980 case GL_POLYGON_OFFSET_LINE
:
1981 R200_STATECHANGE( rmesa
, set
);
1983 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_LINE
;
1985 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_LINE
;
1990 case GL_POINT_SPRITE_ARB
:
1991 R200_STATECHANGE( rmesa
, spr
);
1994 for (i
= 0; i
< 6; i
++) {
1995 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |=
1996 ctx
->Point
.CoordReplace
[i
] << (R200_PS_GEN_TEX_0_SHIFT
+ i
);
1999 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] &= ~R200_PS_GEN_TEX_MASK
;
2003 case GL_POLYGON_OFFSET_FILL
:
2004 R200_STATECHANGE( rmesa
, set
);
2006 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_TRI
;
2008 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_TRI
;
2012 case GL_POLYGON_SMOOTH
:
2013 R200_STATECHANGE( rmesa
, ctx
);
2015 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_POLY
;
2017 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_POLY
;
2021 case GL_POLYGON_STIPPLE
:
2022 R200_STATECHANGE(rmesa
, set
);
2024 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_STIPPLE_ENABLE
;
2026 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_STIPPLE_ENABLE
;
2030 case GL_RESCALE_NORMAL_EXT
: {
2031 GLboolean tmp
= ctx
->_NeedEyeCoords
? state
: !state
;
2032 R200_STATECHANGE( rmesa
, tcl
);
2034 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
2036 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
2041 case GL_SCISSOR_TEST
:
2042 radeon_firevertices(&rmesa
->radeon
);
2043 rmesa
->radeon
.state
.scissor
.enabled
= state
;
2044 radeonUpdateScissor( ctx
);
2047 case GL_STENCIL_TEST
:
2048 if ( rmesa
->radeon
.state
.stencil
.hwBuffer
) {
2049 R200_STATECHANGE( rmesa
, ctx
);
2051 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_STENCIL_ENABLE
;
2053 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_STENCIL_ENABLE
;
2056 FALLBACK( rmesa
, R200_FALLBACK_STENCIL
, state
);
2060 case GL_TEXTURE_GEN_Q
:
2061 case GL_TEXTURE_GEN_R
:
2062 case GL_TEXTURE_GEN_S
:
2063 case GL_TEXTURE_GEN_T
:
2064 /* Picked up in r200UpdateTextureState.
2066 rmesa
->recheck_texgen
[ctx
->Texture
.CurrentUnit
] = GL_TRUE
;
2069 case GL_COLOR_SUM_EXT
:
2070 r200UpdateSpecular ( ctx
);
2073 case GL_VERTEX_PROGRAM_ARB
:
2076 rmesa
->curr_vp_hw
= NULL
;
2077 R200_STATECHANGE( rmesa
, vap
);
2078 rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
] &= ~R200_VAP_PROG_VTX_SHADER_ENABLE
;
2079 /* mark all tcl atoms (tcl vector state got overwritten) dirty
2080 not sure about tcl scalar state - we need at least grd
2081 with vert progs too.
2082 ucp looks like it doesn't get overwritten (may even work
2083 with vp for pos-invariant progs if we're lucky) */
2084 R200_STATECHANGE( rmesa
, mtl
[0] );
2085 R200_STATECHANGE( rmesa
, mtl
[1] );
2086 R200_STATECHANGE( rmesa
, fog
);
2087 R200_STATECHANGE( rmesa
, glt
);
2088 R200_STATECHANGE( rmesa
, eye
);
2089 for (i
= R200_MTX_MV
; i
<= R200_MTX_TEX5
; i
++) {
2090 R200_STATECHANGE( rmesa
, mat
[i
] );
2092 for (i
= 0 ; i
< 8; i
++) {
2093 R200_STATECHANGE( rmesa
, lit
[i
] );
2095 R200_STATECHANGE( rmesa
, tcl
);
2096 for (i
= 0; i
<= ctx
->Const
.MaxClipPlanes
; i
++) {
2097 if (ctx
->Transform
.ClipPlanesEnabled
& (1 << i
)) {
2098 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= (R200_UCP_ENABLE_0
<< i
);
2101 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0 << i);
2104 /* ugly. Need to call everything which might change compsel. */
2105 r200UpdateSpecular( ctx
);
2107 /* shouldn't be necessary, as it's picked up anyway in r200ValidateState (_NEW_PROGRAM),
2108 but without it doom3 locks up at always the same places. Why? */
2109 /* FIXME: This can (and should) be replaced by a call to the TCL_STATE_FLUSH reg before
2110 accessing VAP_SE_VAP_CNTL. Requires drm changes (done). Remove after some time... */
2111 r200UpdateTextureState( ctx
);
2112 /* if we call r200UpdateTextureState we need the code below because we are calling it with
2113 non-current derived enabled values which may revert the state atoms for frag progs even when
2114 they already got disabled... ugh
2115 Should really figure out why we need to call r200UpdateTextureState in the first place */
2117 for (unit
= 0; unit
< R200_MAX_TEXTURE_UNITS
; unit
++) {
2118 R200_STATECHANGE( rmesa
, pix
[unit
] );
2119 R200_STATECHANGE( rmesa
, tex
[unit
] );
2120 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] &=
2121 ~(R200_TXFORMAT_ST_ROUTE_MASK
| R200_TXFORMAT_LOOKUP_DISABLE
);
2122 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] |= unit
<< R200_TXFORMAT_ST_ROUTE_SHIFT
;
2123 /* need to guard this with drmSupportsFragmentShader? Should never get here if
2124 we don't announce ATI_fs, right? */
2125 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXMULTI_CTL
] = 0;
2127 R200_STATECHANGE( rmesa
, cst
);
2128 R200_STATECHANGE( rmesa
, tf
);
2129 rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] = 0;
2133 /* picked up later */
2135 /* call functions which change hw state based on ARB_vp enabled or not. */
2136 r200PointParameter( ctx
, GL_POINT_DISTANCE_ATTENUATION
, NULL
);
2137 r200Fogfv( ctx
, GL_FOG_COORD_SRC
, NULL
);
2140 case GL_VERTEX_PROGRAM_POINT_SIZE_ARB
:
2141 r200PointParameter( ctx
, GL_POINT_DISTANCE_ATTENUATION
, NULL
);
2144 case GL_FRAGMENT_SHADER_ATI
:
2146 /* restore normal tex env colors and make sure tex env combine will get updated
2147 mark env atoms dirty (as their data was overwritten by afs even
2148 if they didn't change) and restore tex coord routing */
2150 for (unit
= 0; unit
< R200_MAX_TEXTURE_UNITS
; unit
++) {
2151 R200_STATECHANGE( rmesa
, pix
[unit
] );
2152 R200_STATECHANGE( rmesa
, tex
[unit
] );
2153 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] &=
2154 ~(R200_TXFORMAT_ST_ROUTE_MASK
| R200_TXFORMAT_LOOKUP_DISABLE
);
2155 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] |= unit
<< R200_TXFORMAT_ST_ROUTE_SHIFT
;
2156 /* need to guard this with drmSupportsFragmentShader? Should never get here if
2157 we don't announce ATI_fs, right? */
2158 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXMULTI_CTL
] = 0;
2160 R200_STATECHANGE( rmesa
, cst
);
2161 R200_STATECHANGE( rmesa
, tf
);
2162 rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] = 0;
2165 /* need to mark this dirty as pix/tf atoms have overwritten the data
2166 even if the data in the atoms didn't change */
2167 R200_STATECHANGE( rmesa
, atf
);
2168 R200_STATECHANGE( rmesa
, afs
[1] );
2169 /* everything else picked up in r200UpdateTextureState hopefully */
2178 void r200LightingSpaceChange( GLcontext
*ctx
)
2180 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2183 if (R200_DEBUG
& DEBUG_STATE
)
2184 fprintf(stderr
, "%s %d BEFORE %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
2185 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
2187 if (ctx
->_NeedEyeCoords
)
2188 tmp
= ctx
->Transform
.RescaleNormals
;
2190 tmp
= !ctx
->Transform
.RescaleNormals
;
2192 R200_STATECHANGE( rmesa
, tcl
);
2194 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
2196 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
2199 if (R200_DEBUG
& DEBUG_STATE
)
2200 fprintf(stderr
, "%s %d AFTER %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
2201 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
2204 /* =============================================================
2205 * Deferred state management - matrices, textures, other?
2211 static void upload_matrix( r200ContextPtr rmesa
, GLfloat
*src
, int idx
)
2213 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
2217 for (i
= 0 ; i
< 4 ; i
++) {
2221 *dest
++ = src
[i
+12];
2224 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
2227 static void upload_matrix_t( r200ContextPtr rmesa
, const GLfloat
*src
, int idx
)
2229 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
2230 memcpy(dest
, src
, 16*sizeof(float));
2231 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
2235 static void update_texturematrix( GLcontext
*ctx
)
2237 r200ContextPtr rmesa
= R200_CONTEXT( ctx
);
2238 GLuint tpc
= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
];
2239 GLuint compsel
= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
];
2242 if (R200_DEBUG
& DEBUG_STATE
)
2243 fprintf(stderr
, "%s before COMPSEL: %x\n", __FUNCTION__
,
2244 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]);
2246 rmesa
->TexMatEnabled
= 0;
2247 rmesa
->TexMatCompSel
= 0;
2249 for (unit
= 0 ; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
2250 if (!ctx
->Texture
.Unit
[unit
]._ReallyEnabled
)
2253 if (ctx
->TextureMatrixStack
[unit
].Top
->type
!= MATRIX_IDENTITY
) {
2254 rmesa
->TexMatEnabled
|= (R200_TEXGEN_TEXMAT_0_ENABLE
|
2255 R200_TEXMAT_0_ENABLE
) << unit
;
2257 rmesa
->TexMatCompSel
|= R200_OUTPUT_TEX_0
<< unit
;
2259 if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2260 /* Need to preconcatenate any active texgen
2261 * obj/eyeplane matrices:
2263 _math_matrix_mul_matrix( &rmesa
->tmpmat
,
2264 ctx
->TextureMatrixStack
[unit
].Top
,
2265 &rmesa
->TexGenMatrix
[unit
] );
2266 upload_matrix( rmesa
, rmesa
->tmpmat
.m
, R200_MTX_TEX0
+unit
);
2269 upload_matrix( rmesa
, ctx
->TextureMatrixStack
[unit
].Top
->m
,
2270 R200_MTX_TEX0
+unit
);
2273 else if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2274 upload_matrix( rmesa
, rmesa
->TexGenMatrix
[unit
].m
,
2275 R200_MTX_TEX0
+unit
);
2279 tpc
= (rmesa
->TexMatEnabled
| rmesa
->TexGenEnabled
);
2280 if (tpc
!= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
]) {
2281 R200_STATECHANGE(rmesa
, tcg
);
2282 rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
] = tpc
;
2285 compsel
&= ~R200_OUTPUT_TEX_MASK
;
2286 compsel
|= rmesa
->TexMatCompSel
| rmesa
->TexGenCompSel
;
2287 if (compsel
!= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]) {
2288 R200_STATECHANGE(rmesa
, vtx
);
2289 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] = compsel
;
2296 * Tell the card where to render (offset, pitch).
2297 * Effected by glDrawBuffer, etc
2300 r200UpdateDrawBuffer(GLcontext
*ctx
)
2302 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2303 struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
2304 struct radeon_renderbuffer
*rrb
;
2306 if (fb
->_ColorDrawBufferIndexes
[0] == BUFFER_FRONT_LEFT
) {
2308 rrb
= (void *) fb
->Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
;
2309 } else if (fb
->_ColorDrawBufferIndexes
[0] == BUFFER_BACK_LEFT
) {
2311 rrb
= (void *) fb
->Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
;
2313 /* drawing to multiple buffers, or none */
2320 R200_STATECHANGE( rmesa
, ctx
);
2323 /* Note: we used the (possibly) page-flipped values */
2324 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLOROFFSET
]
2325 = ((rrb
->flippedOffset
+ rmesa
->radeon
.radeonScreen
->fbLocation
)
2326 & R200_COLOROFFSET_MASK
);
2327 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLORPITCH
] = drb
->flippedPitch
;
2328 if (rmesa
->radeon
.sarea
->tiling_enabled
) {
2329 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLORPITCH
] |= R200_COLOR_TILE_ENABLE
;
2334 static GLboolean
r200ValidateBuffers(GLcontext
*ctx
)
2336 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2337 struct radeon_cs_space_check bos
[8];
2338 struct radeon_renderbuffer
*rrb
;
2341 int flushed
= 0, ret
;
2345 rrb
= radeon_get_colorbuffer(&rmesa
->radeon
);
2347 if (rrb
&& rrb
->bo
) {
2348 bos
[num_bo
].bo
= rrb
->bo
;
2349 bos
[num_bo
].read_domains
= 0;
2350 bos
[num_bo
].write_domain
= RADEON_GEM_DOMAIN_VRAM
;
2351 bos
[num_bo
].new_accounted
= 0;
2356 rrb
= radeon_get_depthbuffer(&rmesa
->radeon
);
2358 if (rrb
&& rrb
->bo
) {
2359 bos
[num_bo
].bo
= rrb
->bo
;
2360 bos
[num_bo
].read_domains
= 0;
2361 bos
[num_bo
].write_domain
= RADEON_GEM_DOMAIN_VRAM
;
2362 bos
[num_bo
].new_accounted
= 0;
2366 for (i
= 0; i
< ctx
->Const
.MaxTextureImageUnits
; ++i
) {
2369 if (!ctx
->Texture
.Unit
[i
]._ReallyEnabled
)
2372 t
= radeon_tex_obj(ctx
->Texture
.Unit
[i
]._Current
);
2373 bos
[num_bo
].bo
= t
->mt
->bo
;
2374 bos
[num_bo
].read_domains
= RADEON_GEM_DOMAIN_GTT
| RADEON_GEM_DOMAIN_VRAM
;
2375 bos
[num_bo
].write_domain
= 0;
2376 bos
[num_bo
].new_accounted
= 0;
2380 ret
= radeon_cs_space_check(rmesa
->radeon
.cmdbuf
.cs
, bos
, num_bo
);
2381 if (ret
== RADEON_CS_SPACE_OP_TO_BIG
)
2383 if (ret
== RADEON_CS_SPACE_FLUSH
) {
2393 GLboolean
r200ValidateState( GLcontext
*ctx
)
2395 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2396 GLuint new_state
= rmesa
->radeon
.NewGLState
;
2398 if (new_state
& (_NEW_BUFFERS
| _NEW_COLOR
| _NEW_PIXEL
)) {
2399 r200UpdateDrawBuffer(ctx
);
2402 if (new_state
& (_NEW_TEXTURE
| _NEW_PROGRAM
)) {
2403 r200UpdateTextureState( ctx
);
2404 new_state
|= rmesa
->radeon
.NewGLState
; /* may add TEXTURE_MATRIX */
2405 r200UpdateLocalViewer( ctx
);
2408 /* we need to do a space check here */
2409 if (!r200ValidateBuffers(ctx
))
2412 /* FIXME: don't really need most of these when vertex progs are enabled */
2414 /* Need an event driven matrix update?
2416 if (new_state
& (_NEW_MODELVIEW
|_NEW_PROJECTION
))
2417 upload_matrix( rmesa
, ctx
->_ModelProjectMatrix
.m
, R200_MTX_MVP
);
2419 /* Need these for lighting (shouldn't upload otherwise)
2421 if (new_state
& (_NEW_MODELVIEW
)) {
2422 upload_matrix( rmesa
, ctx
->ModelviewMatrixStack
.Top
->m
, R200_MTX_MV
);
2423 upload_matrix_t( rmesa
, ctx
->ModelviewMatrixStack
.Top
->inv
, R200_MTX_IMV
);
2426 /* Does this need to be triggered on eg. modelview for
2427 * texgen-derived objplane/eyeplane matrices?
2429 if (new_state
& (_NEW_TEXTURE
|_NEW_TEXTURE_MATRIX
)) {
2430 update_texturematrix( ctx
);
2433 if (new_state
& (_NEW_LIGHT
|_NEW_MODELVIEW
|_MESA_NEW_NEED_EYE_COORDS
)) {
2434 update_light( ctx
);
2437 /* emit all active clip planes if projection matrix changes.
2439 if (new_state
& (_NEW_PROJECTION
)) {
2440 if (ctx
->Transform
.ClipPlanesEnabled
)
2441 r200UpdateClipPlanes( ctx
);
2444 if (new_state
& (_NEW_PROGRAM
|
2445 /* need to test for pretty much anything due to possible parameter bindings */
2446 _NEW_MODELVIEW
|_NEW_PROJECTION
|_NEW_TRANSFORM
|
2447 _NEW_LIGHT
|_NEW_TEXTURE
|_NEW_TEXTURE_MATRIX
|
2448 _NEW_FOG
|_NEW_POINT
|_NEW_TRACK_MATRIX
)) {
2449 if (ctx
->VertexProgram
._Enabled
) {
2450 r200SetupVertexProg( ctx
);
2452 else TCL_FALLBACK(ctx
, R200_TCL_FALLBACK_VERTEX_PROGRAM
, 0);
2455 rmesa
->radeon
.NewGLState
= 0;
2460 static void r200InvalidateState( GLcontext
*ctx
, GLuint new_state
)
2462 _swrast_InvalidateState( ctx
, new_state
);
2463 _swsetup_InvalidateState( ctx
, new_state
);
2464 _vbo_InvalidateState( ctx
, new_state
);
2465 _tnl_InvalidateState( ctx
, new_state
);
2466 _ae_invalidate_state( ctx
, new_state
);
2467 R200_CONTEXT(ctx
)->radeon
.NewGLState
|= new_state
;
2470 /* A hack. The r200 can actually cope just fine with materials
2471 * between begin/ends, so fix this.
2472 * Should map to inputs just like the generic vertex arrays for vertex progs.
2473 * In theory there could still be too many and we'd still need a fallback.
2475 static GLboolean
check_material( GLcontext
*ctx
)
2477 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
2480 for (i
= _TNL_ATTRIB_MAT_FRONT_AMBIENT
;
2481 i
< _TNL_ATTRIB_MAT_BACK_INDEXES
;
2483 if (tnl
->vb
.AttribPtr
[i
] &&
2484 tnl
->vb
.AttribPtr
[i
]->stride
)
2490 static void r200WrapRunPipeline( GLcontext
*ctx
)
2492 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2493 GLboolean has_material
;
2496 fprintf(stderr
, "%s, newstate: %x\n", __FUNCTION__
, rmesa
->radeon
.NewGLState
);
2500 if (rmesa
->radeon
.NewGLState
)
2501 if (!r200ValidateState( ctx
))
2502 FALLBACK(rmesa
, RADEON_FALLBACK_TEXTURE
, GL_TRUE
);
2504 has_material
= !ctx
->VertexProgram
._Enabled
&& ctx
->Light
.Enabled
&& check_material( ctx
);
2507 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_TRUE
);
2510 /* Run the pipeline.
2512 _tnl_run_pipeline( ctx
);
2515 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_FALSE
);
2520 /* Initialize the driver's state functions.
2522 void r200InitStateFuncs( struct dd_function_table
*functions
)
2524 functions
->UpdateState
= r200InvalidateState
;
2525 functions
->LightingSpaceChange
= r200LightingSpaceChange
;
2527 functions
->DrawBuffer
= r200DrawBuffer
;
2528 functions
->ReadBuffer
= r200ReadBuffer
;
2530 functions
->AlphaFunc
= r200AlphaFunc
;
2531 functions
->BlendColor
= r200BlendColor
;
2532 functions
->BlendEquationSeparate
= r200BlendEquationSeparate
;
2533 functions
->BlendFuncSeparate
= r200BlendFuncSeparate
;
2534 functions
->ClearColor
= r200ClearColor
;
2535 functions
->ClearDepth
= r200ClearDepth
;
2536 functions
->ClearIndex
= NULL
;
2537 functions
->ClearStencil
= r200ClearStencil
;
2538 functions
->ClipPlane
= r200ClipPlane
;
2539 functions
->ColorMask
= r200ColorMask
;
2540 functions
->CullFace
= r200CullFace
;
2541 functions
->DepthFunc
= r200DepthFunc
;
2542 functions
->DepthMask
= r200DepthMask
;
2543 functions
->DepthRange
= r200DepthRange
;
2544 functions
->Enable
= r200Enable
;
2545 functions
->Fogfv
= r200Fogfv
;
2546 functions
->FrontFace
= r200FrontFace
;
2547 functions
->Hint
= NULL
;
2548 functions
->IndexMask
= NULL
;
2549 functions
->LightModelfv
= r200LightModelfv
;
2550 functions
->Lightfv
= r200Lightfv
;
2551 functions
->LineStipple
= r200LineStipple
;
2552 functions
->LineWidth
= r200LineWidth
;
2553 functions
->LogicOpcode
= r200LogicOpCode
;
2554 functions
->PolygonMode
= r200PolygonMode
;
2555 functions
->PolygonOffset
= r200PolygonOffset
;
2556 functions
->PolygonStipple
= r200PolygonStipple
;
2557 functions
->PointParameterfv
= r200PointParameter
;
2558 functions
->PointSize
= r200PointSize
;
2559 functions
->RenderMode
= r200RenderMode
;
2560 functions
->Scissor
= radeonScissor
;
2561 functions
->ShadeModel
= r200ShadeModel
;
2562 functions
->StencilFuncSeparate
= r200StencilFuncSeparate
;
2563 functions
->StencilMaskSeparate
= r200StencilMaskSeparate
;
2564 functions
->StencilOpSeparate
= r200StencilOpSeparate
;
2565 functions
->Viewport
= r200Viewport
;
2569 void r200InitTnlFuncs( GLcontext
*ctx
)
2571 TNL_CONTEXT(ctx
)->Driver
.NotifyMaterialChange
= r200UpdateMaterial
;
2572 TNL_CONTEXT(ctx
)->Driver
.RunPipeline
= r200WrapRunPipeline
;