1 /**************************************************************************
3 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
5 The Weather Channel (TM) funded Tungsten Graphics to develop the
6 initial release of the Radeon 8500 driver under the XFree86 license.
7 This notice must be preserved.
9 Permission is hereby granted, free of charge, to any person obtaining
10 a copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sublicense, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial
19 portions of the Software.
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
25 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 **************************************************************************/
33 * Keith Whitwell <keith@tungstengraphics.com>
36 #include "main/glheader.h"
37 #include "main/imports.h"
38 #include "main/api_arrayelt.h"
39 #include "main/enums.h"
40 #include "main/colormac.h"
41 #include "main/light.h"
42 #include "main/framebuffer.h"
44 #include "swrast/swrast.h"
47 #include "tnl/t_pipeline.h"
48 #include "swrast_setup/swrast_setup.h"
50 #include "radeon_common.h"
51 #include "radeon_mipmap_tree.h"
52 #include "r200_context.h"
53 #include "r200_ioctl.h"
54 #include "r200_state.h"
57 #include "r200_swtcl.h"
58 #include "r200_vertprog.h"
60 #include "drirenderbuffer.h"
63 /* =============================================================
67 static void r200AlphaFunc( GLcontext
*ctx
, GLenum func
, GLfloat ref
)
69 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
70 int pp_misc
= rmesa
->hw
.ctx
.cmd
[CTX_PP_MISC
];
73 CLAMPED_FLOAT_TO_UBYTE(refByte
, ref
);
75 R200_STATECHANGE( rmesa
, ctx
);
77 pp_misc
&= ~(R200_ALPHA_TEST_OP_MASK
| R200_REF_ALPHA_MASK
);
78 pp_misc
|= (refByte
& R200_REF_ALPHA_MASK
);
82 pp_misc
|= R200_ALPHA_TEST_FAIL
;
85 pp_misc
|= R200_ALPHA_TEST_LESS
;
88 pp_misc
|= R200_ALPHA_TEST_EQUAL
;
91 pp_misc
|= R200_ALPHA_TEST_LEQUAL
;
94 pp_misc
|= R200_ALPHA_TEST_GREATER
;
97 pp_misc
|= R200_ALPHA_TEST_NEQUAL
;
100 pp_misc
|= R200_ALPHA_TEST_GEQUAL
;
103 pp_misc
|= R200_ALPHA_TEST_PASS
;
107 rmesa
->hw
.ctx
.cmd
[CTX_PP_MISC
] = pp_misc
;
110 static void r200BlendColor( GLcontext
*ctx
, const GLfloat cf
[4] )
113 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
114 R200_STATECHANGE( rmesa
, ctx
);
115 CLAMPED_FLOAT_TO_UBYTE(color
[0], cf
[0]);
116 CLAMPED_FLOAT_TO_UBYTE(color
[1], cf
[1]);
117 CLAMPED_FLOAT_TO_UBYTE(color
[2], cf
[2]);
118 CLAMPED_FLOAT_TO_UBYTE(color
[3], cf
[3]);
119 if (rmesa
->radeon
.radeonScreen
->drmSupportsBlendColor
)
120 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCOLOR
] = radeonPackColor( 4, color
[0], color
[1], color
[2], color
[3] );
124 * Calculate the hardware blend factor setting. This same function is used
125 * for source and destination of both alpha and RGB.
128 * The hardware register value for the specified blend factor. This value
129 * will need to be shifted into the correct position for either source or
130 * destination factor.
133 * Since the two cases where source and destination are handled differently
134 * are essentially error cases, they should never happen. Determine if these
135 * cases can be removed.
137 static int blend_factor( GLenum factor
, GLboolean is_src
)
143 func
= R200_BLEND_GL_ZERO
;
146 func
= R200_BLEND_GL_ONE
;
149 func
= R200_BLEND_GL_DST_COLOR
;
151 case GL_ONE_MINUS_DST_COLOR
:
152 func
= R200_BLEND_GL_ONE_MINUS_DST_COLOR
;
155 func
= R200_BLEND_GL_SRC_COLOR
;
157 case GL_ONE_MINUS_SRC_COLOR
:
158 func
= R200_BLEND_GL_ONE_MINUS_SRC_COLOR
;
161 func
= R200_BLEND_GL_SRC_ALPHA
;
163 case GL_ONE_MINUS_SRC_ALPHA
:
164 func
= R200_BLEND_GL_ONE_MINUS_SRC_ALPHA
;
167 func
= R200_BLEND_GL_DST_ALPHA
;
169 case GL_ONE_MINUS_DST_ALPHA
:
170 func
= R200_BLEND_GL_ONE_MINUS_DST_ALPHA
;
172 case GL_SRC_ALPHA_SATURATE
:
173 func
= (is_src
) ? R200_BLEND_GL_SRC_ALPHA_SATURATE
: R200_BLEND_GL_ZERO
;
175 case GL_CONSTANT_COLOR
:
176 func
= R200_BLEND_GL_CONST_COLOR
;
178 case GL_ONE_MINUS_CONSTANT_COLOR
:
179 func
= R200_BLEND_GL_ONE_MINUS_CONST_COLOR
;
181 case GL_CONSTANT_ALPHA
:
182 func
= R200_BLEND_GL_CONST_ALPHA
;
184 case GL_ONE_MINUS_CONSTANT_ALPHA
:
185 func
= R200_BLEND_GL_ONE_MINUS_CONST_ALPHA
;
188 func
= (is_src
) ? R200_BLEND_GL_ONE
: R200_BLEND_GL_ZERO
;
194 * Sets both the blend equation and the blend function.
195 * This is done in a single
196 * function because some blend equations (i.e., \c GL_MIN and \c GL_MAX)
197 * change the interpretation of the blend function.
198 * Also, make sure that blend function and blend equation are set to their default
199 * value if color blending is not enabled, since at least blend equations GL_MIN
200 * and GL_FUNC_REVERSE_SUBTRACT will cause wrong results otherwise for
203 static void r200_set_blend_state( GLcontext
* ctx
)
205 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
206 GLuint cntl
= rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &
207 ~(R200_ROP_ENABLE
| R200_ALPHA_BLEND_ENABLE
| R200_SEPARATE_ALPHA_ENABLE
);
209 int func
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
210 (R200_BLEND_GL_ZERO
<< R200_DST_BLEND_SHIFT
);
211 int eqn
= R200_COMB_FCN_ADD_CLAMP
;
212 int funcA
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
213 (R200_BLEND_GL_ZERO
<< R200_DST_BLEND_SHIFT
);
214 int eqnA
= R200_COMB_FCN_ADD_CLAMP
;
216 R200_STATECHANGE( rmesa
, ctx
);
218 if (rmesa
->radeon
.radeonScreen
->drmSupportsBlendColor
) {
219 if (ctx
->Color
.ColorLogicOpEnabled
) {
220 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
| R200_ROP_ENABLE
;
221 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ABLENDCNTL
] = eqn
| func
;
222 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CBLENDCNTL
] = eqn
| func
;
224 } else if (ctx
->Color
.BlendEnabled
) {
225 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
| R200_ALPHA_BLEND_ENABLE
| R200_SEPARATE_ALPHA_ENABLE
;
228 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
;
229 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ABLENDCNTL
] = eqn
| func
;
230 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CBLENDCNTL
] = eqn
| func
;
235 if (ctx
->Color
.ColorLogicOpEnabled
) {
236 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
| R200_ROP_ENABLE
;
237 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] = eqn
| func
;
239 } else if (ctx
->Color
.BlendEnabled
) {
240 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
| R200_ALPHA_BLEND_ENABLE
;
243 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
;
244 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] = eqn
| func
;
249 func
= (blend_factor( ctx
->Color
.BlendSrcRGB
, GL_TRUE
) << R200_SRC_BLEND_SHIFT
) |
250 (blend_factor( ctx
->Color
.BlendDstRGB
, GL_FALSE
) << R200_DST_BLEND_SHIFT
);
252 switch(ctx
->Color
.BlendEquationRGB
) {
254 eqn
= R200_COMB_FCN_ADD_CLAMP
;
257 case GL_FUNC_SUBTRACT
:
258 eqn
= R200_COMB_FCN_SUB_CLAMP
;
261 case GL_FUNC_REVERSE_SUBTRACT
:
262 eqn
= R200_COMB_FCN_RSUB_CLAMP
;
266 eqn
= R200_COMB_FCN_MIN
;
267 func
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
268 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
272 eqn
= R200_COMB_FCN_MAX
;
273 func
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
274 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
278 fprintf( stderr
, "[%s:%u] Invalid RGB blend equation (0x%04x).\n",
279 __FUNCTION__
, __LINE__
, ctx
->Color
.BlendEquationRGB
);
283 if (!rmesa
->radeon
.radeonScreen
->drmSupportsBlendColor
) {
284 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] = eqn
| func
;
288 funcA
= (blend_factor( ctx
->Color
.BlendSrcA
, GL_TRUE
) << R200_SRC_BLEND_SHIFT
) |
289 (blend_factor( ctx
->Color
.BlendDstA
, GL_FALSE
) << R200_DST_BLEND_SHIFT
);
291 switch(ctx
->Color
.BlendEquationA
) {
293 eqnA
= R200_COMB_FCN_ADD_CLAMP
;
296 case GL_FUNC_SUBTRACT
:
297 eqnA
= R200_COMB_FCN_SUB_CLAMP
;
300 case GL_FUNC_REVERSE_SUBTRACT
:
301 eqnA
= R200_COMB_FCN_RSUB_CLAMP
;
305 eqnA
= R200_COMB_FCN_MIN
;
306 funcA
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
307 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
311 eqnA
= R200_COMB_FCN_MAX
;
312 funcA
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
313 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
317 fprintf( stderr
, "[%s:%u] Invalid A blend equation (0x%04x).\n",
318 __FUNCTION__
, __LINE__
, ctx
->Color
.BlendEquationA
);
322 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ABLENDCNTL
] = eqnA
| funcA
;
323 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CBLENDCNTL
] = eqn
| func
;
327 static void r200BlendEquationSeparate( GLcontext
*ctx
,
328 GLenum modeRGB
, GLenum modeA
)
330 r200_set_blend_state( ctx
);
333 static void r200BlendFuncSeparate( GLcontext
*ctx
,
334 GLenum sfactorRGB
, GLenum dfactorRGB
,
335 GLenum sfactorA
, GLenum dfactorA
)
337 r200_set_blend_state( ctx
);
341 /* =============================================================
345 static void r200DepthFunc( GLcontext
*ctx
, GLenum func
)
347 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
349 R200_STATECHANGE( rmesa
, ctx
);
350 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_Z_TEST_MASK
;
352 switch ( ctx
->Depth
.Func
) {
354 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_NEVER
;
357 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_LESS
;
360 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_EQUAL
;
363 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_LEQUAL
;
366 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_GREATER
;
369 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_NEQUAL
;
372 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_GEQUAL
;
375 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_ALWAYS
;
380 static void r200ClearDepth( GLcontext
*ctx
, GLclampd d
)
382 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
383 GLuint format
= (rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &
384 R200_DEPTH_FORMAT_MASK
);
387 case R200_DEPTH_FORMAT_16BIT_INT_Z
:
388 rmesa
->radeon
.state
.depth
.clear
= d
* 0x0000ffff;
390 case R200_DEPTH_FORMAT_24BIT_INT_Z
:
391 rmesa
->radeon
.state
.depth
.clear
= d
* 0x00ffffff;
396 static void r200DepthMask( GLcontext
*ctx
, GLboolean flag
)
398 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
399 R200_STATECHANGE( rmesa
, ctx
);
401 if ( ctx
->Depth
.Mask
) {
402 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_WRITE_ENABLE
;
404 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_Z_WRITE_ENABLE
;
409 /* =============================================================
414 static void r200Fogfv( GLcontext
*ctx
, GLenum pname
, const GLfloat
*param
)
416 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
417 union { int i
; float f
; } c
, d
;
421 c
.i
= rmesa
->hw
.fog
.cmd
[FOG_C
];
422 d
.i
= rmesa
->hw
.fog
.cmd
[FOG_D
];
426 if (!ctx
->Fog
.Enabled
)
428 R200_STATECHANGE(rmesa
, tcl
);
429 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_TCL_FOG_MASK
;
430 switch (ctx
->Fog
.Mode
) {
432 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_LINEAR
;
433 if (ctx
->Fog
.Start
== ctx
->Fog
.End
) {
438 c
.f
= ctx
->Fog
.End
/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
439 d
.f
= -1.0/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
443 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_EXP
;
445 d
.f
= -ctx
->Fog
.Density
;
448 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_EXP2
;
450 d
.f
= -(ctx
->Fog
.Density
* ctx
->Fog
.Density
);
457 switch (ctx
->Fog
.Mode
) {
460 d
.f
= -ctx
->Fog
.Density
;
464 d
.f
= -(ctx
->Fog
.Density
* ctx
->Fog
.Density
);
472 if (ctx
->Fog
.Mode
== GL_LINEAR
) {
473 if (ctx
->Fog
.Start
== ctx
->Fog
.End
) {
477 c
.f
= ctx
->Fog
.End
/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
478 d
.f
= -1.0/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
483 R200_STATECHANGE( rmesa
, ctx
);
484 UNCLAMPED_FLOAT_TO_RGB_CHAN( col
, ctx
->Fog
.Color
);
485 i
= radeonPackColor( 4, col
[0], col
[1], col
[2], 0 );
486 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] &= ~R200_FOG_COLOR_MASK
;
487 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] |= i
;
489 case GL_FOG_COORD_SRC
: {
490 GLuint out_0
= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
];
491 GLuint fog
= rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
];
493 fog
&= ~R200_FOG_USE_MASK
;
494 if ( ctx
->Fog
.FogCoordinateSource
== GL_FOG_COORD
|| ctx
->VertexProgram
.Enabled
) {
495 fog
|= R200_FOG_USE_VTX_FOG
;
496 out_0
|= R200_VTX_DISCRETE_FOG
;
499 fog
|= R200_FOG_USE_SPEC_ALPHA
;
500 out_0
&= ~R200_VTX_DISCRETE_FOG
;
503 if ( fog
!= rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] ) {
504 R200_STATECHANGE( rmesa
, ctx
);
505 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] = fog
;
508 if (out_0
!= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
]) {
509 R200_STATECHANGE( rmesa
, vtx
);
510 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] = out_0
;
519 if (c
.i
!= rmesa
->hw
.fog
.cmd
[FOG_C
] || d
.i
!= rmesa
->hw
.fog
.cmd
[FOG_D
]) {
520 R200_STATECHANGE( rmesa
, fog
);
521 rmesa
->hw
.fog
.cmd
[FOG_C
] = c
.i
;
522 rmesa
->hw
.fog
.cmd
[FOG_D
] = d
.i
;
526 /* =============================================================
530 static void r200CullFace( GLcontext
*ctx
, GLenum unused
)
532 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
533 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
534 GLuint t
= rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
];
536 s
|= R200_FFACE_SOLID
| R200_BFACE_SOLID
;
537 t
&= ~(R200_CULL_FRONT
| R200_CULL_BACK
);
539 if ( ctx
->Polygon
.CullFlag
) {
540 switch ( ctx
->Polygon
.CullFaceMode
) {
542 s
&= ~R200_FFACE_SOLID
;
543 t
|= R200_CULL_FRONT
;
546 s
&= ~R200_BFACE_SOLID
;
549 case GL_FRONT_AND_BACK
:
550 s
&= ~(R200_FFACE_SOLID
| R200_BFACE_SOLID
);
551 t
|= (R200_CULL_FRONT
| R200_CULL_BACK
);
556 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
557 R200_STATECHANGE(rmesa
, set
);
558 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
561 if ( rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] != t
) {
562 R200_STATECHANGE(rmesa
, tcl
);
563 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] = t
;
567 static void r200FrontFace( GLcontext
*ctx
, GLenum mode
)
569 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
571 R200_STATECHANGE( rmesa
, set
);
572 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_FFACE_CULL_DIR_MASK
;
574 R200_STATECHANGE( rmesa
, tcl
);
575 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_CULL_FRONT_IS_CCW
;
579 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_FFACE_CULL_CW
;
582 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_FFACE_CULL_CCW
;
583 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_CULL_FRONT_IS_CCW
;
588 /* =============================================================
591 static void r200PointSize( GLcontext
*ctx
, GLfloat size
)
593 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
594 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.ptp
.cmd
;
596 R200_STATECHANGE( rmesa
, cst
);
597 R200_STATECHANGE( rmesa
, ptp
);
598 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] &= ~0xffff;
599 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] |= ((GLuint
)(ctx
->Point
.Size
* 16.0));
600 /* this is the size param of the point size calculation (point size reg value
601 is not used when calculation is active). */
602 fcmd
[PTP_VPORT_SCALE_PTSIZE
] = ctx
->Point
.Size
;
605 static void r200PointParameter( GLcontext
*ctx
, GLenum pname
, const GLfloat
*params
)
607 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
608 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.ptp
.cmd
;
611 case GL_POINT_SIZE_MIN
:
612 /* Can clamp both in tcl and setup - just set both (as does fglrx) */
613 R200_STATECHANGE( rmesa
, lin
);
614 R200_STATECHANGE( rmesa
, ptp
);
615 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] &= 0xffff;
616 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] |= (GLuint
)(ctx
->Point
.MinSize
* 16.0) << 16;
617 fcmd
[PTP_CLAMP_MIN
] = ctx
->Point
.MinSize
;
619 case GL_POINT_SIZE_MAX
:
620 R200_STATECHANGE( rmesa
, cst
);
621 R200_STATECHANGE( rmesa
, ptp
);
622 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] &= 0xffff;
623 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] |= (GLuint
)(ctx
->Point
.MaxSize
* 16.0) << 16;
624 fcmd
[PTP_CLAMP_MAX
] = ctx
->Point
.MaxSize
;
626 case GL_POINT_DISTANCE_ATTENUATION
:
627 R200_STATECHANGE( rmesa
, vtx
);
628 R200_STATECHANGE( rmesa
, spr
);
629 R200_STATECHANGE( rmesa
, ptp
);
630 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.ptp
.cmd
;
631 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] &=
632 ~(R200_PS_MULT_MASK
| R200_PS_LIN_ATT_ZERO
| R200_PS_SE_SEL_STATE
);
633 /* can't rely on ctx->Point._Attenuated here and test for NEW_POINT in
634 r200ValidateState looks like overkill */
635 if (ctx
->Point
.Params
[0] != 1.0 ||
636 ctx
->Point
.Params
[1] != 0.0 ||
637 ctx
->Point
.Params
[2] != 0.0 ||
638 (ctx
->VertexProgram
.Enabled
&& ctx
->VertexProgram
.PointSizeEnabled
)) {
639 /* all we care for vp would be the ps_se_sel_state setting */
640 fcmd
[PTP_ATT_CONST_QUAD
] = ctx
->Point
.Params
[2];
641 fcmd
[PTP_ATT_CONST_LIN
] = ctx
->Point
.Params
[1];
642 fcmd
[PTP_ATT_CONST_CON
] = ctx
->Point
.Params
[0];
643 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |= R200_PS_MULT_ATTENCONST
;
644 if (ctx
->Point
.Params
[1] == 0.0)
645 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |= R200_PS_LIN_ATT_ZERO
;
646 /* FIXME: setting this here doesn't look quite ok - we only want to do
647 that if we're actually drawing points probably */
648 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_PT_SIZE
;
649 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |= R200_VTX_POINT_SIZE
;
652 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |=
653 R200_PS_SE_SEL_STATE
| R200_PS_MULT_CONST
;
654 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_PT_SIZE
;
655 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~R200_VTX_POINT_SIZE
;
658 case GL_POINT_FADE_THRESHOLD_SIZE
:
659 /* don't support multisampling, so doesn't matter. */
661 /* can't do these but don't need them.
662 case GL_POINT_SPRITE_R_MODE_NV:
663 case GL_POINT_SPRITE_COORD_ORIGIN: */
665 fprintf(stderr
, "bad pname parameter in r200PointParameter\n");
670 /* =============================================================
673 static void r200LineWidth( GLcontext
*ctx
, GLfloat widthf
)
675 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
677 R200_STATECHANGE( rmesa
, lin
);
678 R200_STATECHANGE( rmesa
, set
);
680 /* Line width is stored in U6.4 format.
681 * Same min/max limits for AA, non-AA lines.
683 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] &= ~0xffff;
684 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] |= (GLuint
)
685 (CLAMP(widthf
, ctx
->Const
.MinLineWidth
, ctx
->Const
.MaxLineWidth
) * 16.0);
687 if ( widthf
> 1.0 ) {
688 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_WIDELINE_ENABLE
;
690 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_WIDELINE_ENABLE
;
694 static void r200LineStipple( GLcontext
*ctx
, GLint factor
, GLushort pattern
)
696 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
698 R200_STATECHANGE( rmesa
, lin
);
699 rmesa
->hw
.lin
.cmd
[LIN_RE_LINE_PATTERN
] =
700 ((((GLuint
)factor
& 0xff) << 16) | ((GLuint
)pattern
));
704 /* =============================================================
707 static void r200ColorMask( GLcontext
*ctx
,
708 GLboolean r
, GLboolean g
,
709 GLboolean b
, GLboolean a
)
711 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
712 GLuint mask
= radeonPackColor( rmesa
->radeon
.radeonScreen
->cpp
,
713 ctx
->Color
.ColorMask
[RCOMP
],
714 ctx
->Color
.ColorMask
[GCOMP
],
715 ctx
->Color
.ColorMask
[BCOMP
],
716 ctx
->Color
.ColorMask
[ACOMP
] );
718 GLuint flag
= rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] & ~R200_PLANE_MASK_ENABLE
;
720 if (!(r
&& g
&& b
&& a
))
721 flag
|= R200_PLANE_MASK_ENABLE
;
723 if ( rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] != flag
) {
724 R200_STATECHANGE( rmesa
, ctx
);
725 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = flag
;
728 if ( rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
] != mask
) {
729 R200_STATECHANGE( rmesa
, msk
);
730 rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
] = mask
;
735 /* =============================================================
739 static void r200PolygonOffset( GLcontext
*ctx
,
740 GLfloat factor
, GLfloat units
)
742 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
743 float_ui32_type constant
= { units
* rmesa
->radeon
.state
.depth
.scale
};
744 float_ui32_type factoru
= { factor
};
749 /* fprintf(stderr, "%s f:%f u:%f\n", __FUNCTION__, factor, constant); */
751 R200_STATECHANGE( rmesa
, zbs
);
752 rmesa
->hw
.zbs
.cmd
[ZBS_SE_ZBIAS_FACTOR
] = factoru
.ui32
;
753 rmesa
->hw
.zbs
.cmd
[ZBS_SE_ZBIAS_CONSTANT
] = constant
.ui32
;
756 static void r200PolygonStipple( GLcontext
*ctx
, const GLubyte
*mask
)
758 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
760 drm_radeon_stipple_t stipple
;
762 /* Must flip pattern upside down.
764 for ( i
= 0 ; i
< 32 ; i
++ ) {
765 rmesa
->state
.stipple
.mask
[31 - i
] = ((GLuint
*) mask
)[i
];
768 /* TODO: push this into cmd mechanism
770 radeon_firevertices(&rmesa
->radeon
);
771 LOCK_HARDWARE( &rmesa
->radeon
);
773 /* FIXME: Use window x,y offsets into stipple RAM.
775 stipple
.mask
= rmesa
->state
.stipple
.mask
;
776 drmCommandWrite( rmesa
->radeon
.dri
.fd
, DRM_RADEON_STIPPLE
,
777 &stipple
, sizeof(stipple
) );
778 UNLOCK_HARDWARE( &rmesa
->radeon
);
781 static void r200PolygonMode( GLcontext
*ctx
, GLenum face
, GLenum mode
)
783 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
784 GLboolean flag
= (ctx
->_TriangleCaps
& DD_TRI_UNFILLED
) != 0;
786 /* Can't generally do unfilled via tcl, but some good special
789 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_UNFILLED
, flag
);
790 if (rmesa
->radeon
.TclFallback
) {
791 r200ChooseRenderState( ctx
);
792 r200ChooseVertexState( ctx
);
797 /* =============================================================
798 * Rendering attributes
800 * We really don't want to recalculate all this every time we bind a
801 * texture. These things shouldn't change all that often, so it makes
802 * sense to break them out of the core texture state update routines.
805 /* Examine lighting and texture state to determine if separate specular
808 static void r200UpdateSpecular( GLcontext
*ctx
)
810 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
811 uint32_t p
= rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
];
813 R200_STATECHANGE( rmesa
, tcl
);
814 R200_STATECHANGE( rmesa
, vtx
);
816 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~(3<<R200_VTX_COLOR_0_SHIFT
);
817 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~(3<<R200_VTX_COLOR_1_SHIFT
);
818 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_COLOR_0
;
819 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_COLOR_1
;
820 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LIGHTING_ENABLE
;
822 p
&= ~R200_SPECULAR_ENABLE
;
824 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_DIFFUSE_SPECULAR_COMBINE
;
827 if (ctx
->Light
.Enabled
&&
828 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
) {
829 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
830 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
) |
831 (R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
832 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_0
;
833 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_1
;
834 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHTING_ENABLE
;
835 p
|= R200_SPECULAR_ENABLE
;
836 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &=
837 ~R200_DIFFUSE_SPECULAR_COMBINE
;
839 else if (ctx
->Light
.Enabled
) {
840 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
841 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
));
842 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_0
;
843 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHTING_ENABLE
;
844 } else if (ctx
->Fog
.ColorSumEnabled
) {
845 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
846 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
) |
847 (R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
848 p
|= R200_SPECULAR_ENABLE
;
850 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
851 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
));
854 if (ctx
->Fog
.Enabled
) {
855 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
856 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
857 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_1
;
860 if ( rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] != p
) {
861 R200_STATECHANGE( rmesa
, ctx
);
862 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] = p
;
865 /* Update vertex/render formats
867 if (rmesa
->radeon
.TclFallback
) {
868 r200ChooseRenderState( ctx
);
869 r200ChooseVertexState( ctx
);
874 /* =============================================================
879 /* Update on colormaterial, material emmissive/ambient,
880 * lightmodel.globalambient
882 static void update_global_ambient( GLcontext
*ctx
)
884 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
885 float *fcmd
= (float *)R200_DB_STATE( glt
);
887 /* Need to do more if both emmissive & ambient are PREMULT:
888 * I believe this is not nessary when using source_material. This condition thus
889 * will never happen currently, and the function has no dependencies on materials now
891 if ((rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
] &
892 ((3 << R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
893 (3 << R200_FRONT_AMBIENT_SOURCE_SHIFT
))) == 0)
895 COPY_3V( &fcmd
[GLT_RED
],
896 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_EMISSION
]);
897 ACC_SCALE_3V( &fcmd
[GLT_RED
],
898 ctx
->Light
.Model
.Ambient
,
899 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_AMBIENT
]);
903 COPY_3V( &fcmd
[GLT_RED
], ctx
->Light
.Model
.Ambient
);
906 R200_DB_STATECHANGE(rmesa
, &rmesa
->hw
.glt
);
909 /* Update on change to
913 static void update_light_colors( GLcontext
*ctx
, GLuint p
)
915 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
917 /* fprintf(stderr, "%s\n", __FUNCTION__); */
920 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
921 float *fcmd
= (float *)R200_DB_STATE( lit
[p
] );
923 COPY_4V( &fcmd
[LIT_AMBIENT_RED
], l
->Ambient
);
924 COPY_4V( &fcmd
[LIT_DIFFUSE_RED
], l
->Diffuse
);
925 COPY_4V( &fcmd
[LIT_SPECULAR_RED
], l
->Specular
);
927 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
931 static void r200ColorMaterial( GLcontext
*ctx
, GLenum face
, GLenum mode
)
933 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
934 GLuint light_model_ctl1
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
];
935 light_model_ctl1
&= ~((0xf << R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
936 (0xf << R200_FRONT_AMBIENT_SOURCE_SHIFT
) |
937 (0xf << R200_FRONT_DIFFUSE_SOURCE_SHIFT
) |
938 (0xf << R200_FRONT_SPECULAR_SOURCE_SHIFT
) |
939 (0xf << R200_BACK_EMISSIVE_SOURCE_SHIFT
) |
940 (0xf << R200_BACK_AMBIENT_SOURCE_SHIFT
) |
941 (0xf << R200_BACK_DIFFUSE_SOURCE_SHIFT
) |
942 (0xf << R200_BACK_SPECULAR_SOURCE_SHIFT
));
944 if (ctx
->Light
.ColorMaterialEnabled
) {
945 GLuint mask
= ctx
->Light
.ColorMaterialBitmask
;
947 if (mask
& MAT_BIT_FRONT_EMISSION
) {
948 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
949 R200_FRONT_EMISSIVE_SOURCE_SHIFT
);
952 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
953 R200_FRONT_EMISSIVE_SOURCE_SHIFT
);
955 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
956 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
957 R200_FRONT_AMBIENT_SOURCE_SHIFT
);
960 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
961 R200_FRONT_AMBIENT_SOURCE_SHIFT
);
963 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
964 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
965 R200_FRONT_DIFFUSE_SOURCE_SHIFT
);
968 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
969 R200_FRONT_DIFFUSE_SOURCE_SHIFT
);
971 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
972 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
973 R200_FRONT_SPECULAR_SOURCE_SHIFT
);
976 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
977 R200_FRONT_SPECULAR_SOURCE_SHIFT
);
980 if (mask
& MAT_BIT_BACK_EMISSION
) {
981 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
982 R200_BACK_EMISSIVE_SOURCE_SHIFT
);
985 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
986 R200_BACK_EMISSIVE_SOURCE_SHIFT
);
988 if (mask
& MAT_BIT_BACK_AMBIENT
) {
989 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
990 R200_BACK_AMBIENT_SOURCE_SHIFT
);
992 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
993 R200_BACK_AMBIENT_SOURCE_SHIFT
);
995 if (mask
& MAT_BIT_BACK_DIFFUSE
) {
996 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
997 R200_BACK_DIFFUSE_SOURCE_SHIFT
);
999 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
1000 R200_BACK_DIFFUSE_SOURCE_SHIFT
);
1002 if (mask
& MAT_BIT_BACK_SPECULAR
) {
1003 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
1004 R200_BACK_SPECULAR_SOURCE_SHIFT
);
1007 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
1008 R200_BACK_SPECULAR_SOURCE_SHIFT
);
1012 /* Default to SOURCE_MATERIAL:
1015 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
1016 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_AMBIENT_SOURCE_SHIFT
) |
1017 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_DIFFUSE_SOURCE_SHIFT
) |
1018 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_SPECULAR_SOURCE_SHIFT
) |
1019 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_EMISSIVE_SOURCE_SHIFT
) |
1020 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_AMBIENT_SOURCE_SHIFT
) |
1021 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_DIFFUSE_SOURCE_SHIFT
) |
1022 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_SPECULAR_SOURCE_SHIFT
);
1025 if (light_model_ctl1
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
]) {
1026 R200_STATECHANGE( rmesa
, tcl
);
1027 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
] = light_model_ctl1
;
1033 void r200UpdateMaterial( GLcontext
*ctx
)
1035 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1036 GLfloat (*mat
)[4] = ctx
->Light
.Material
.Attrib
;
1037 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( mtl
[0] );
1038 GLfloat
*fcmd2
= (GLfloat
*)R200_DB_STATE( mtl
[1] );
1041 /* Might be possible and faster to update everything unconditionally? */
1042 if (ctx
->Light
.ColorMaterialEnabled
)
1043 mask
&= ~ctx
->Light
.ColorMaterialBitmask
;
1045 if (R200_DEBUG
& DEBUG_STATE
)
1046 fprintf(stderr
, "%s\n", __FUNCTION__
);
1048 if (mask
& MAT_BIT_FRONT_EMISSION
) {
1049 fcmd
[MTL_EMMISSIVE_RED
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][0];
1050 fcmd
[MTL_EMMISSIVE_GREEN
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][1];
1051 fcmd
[MTL_EMMISSIVE_BLUE
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][2];
1052 fcmd
[MTL_EMMISSIVE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][3];
1054 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
1055 fcmd
[MTL_AMBIENT_RED
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][0];
1056 fcmd
[MTL_AMBIENT_GREEN
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][1];
1057 fcmd
[MTL_AMBIENT_BLUE
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][2];
1058 fcmd
[MTL_AMBIENT_ALPHA
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][3];
1060 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
1061 fcmd
[MTL_DIFFUSE_RED
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][0];
1062 fcmd
[MTL_DIFFUSE_GREEN
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][1];
1063 fcmd
[MTL_DIFFUSE_BLUE
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][2];
1064 fcmd
[MTL_DIFFUSE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][3];
1066 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
1067 fcmd
[MTL_SPECULAR_RED
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][0];
1068 fcmd
[MTL_SPECULAR_GREEN
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][1];
1069 fcmd
[MTL_SPECULAR_BLUE
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][2];
1070 fcmd
[MTL_SPECULAR_ALPHA
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][3];
1072 if (mask
& MAT_BIT_FRONT_SHININESS
) {
1073 fcmd
[MTL_SHININESS
] = mat
[MAT_ATTRIB_FRONT_SHININESS
][0];
1076 if (mask
& MAT_BIT_BACK_EMISSION
) {
1077 fcmd2
[MTL_EMMISSIVE_RED
] = mat
[MAT_ATTRIB_BACK_EMISSION
][0];
1078 fcmd2
[MTL_EMMISSIVE_GREEN
] = mat
[MAT_ATTRIB_BACK_EMISSION
][1];
1079 fcmd2
[MTL_EMMISSIVE_BLUE
] = mat
[MAT_ATTRIB_BACK_EMISSION
][2];
1080 fcmd2
[MTL_EMMISSIVE_ALPHA
] = mat
[MAT_ATTRIB_BACK_EMISSION
][3];
1082 if (mask
& MAT_BIT_BACK_AMBIENT
) {
1083 fcmd2
[MTL_AMBIENT_RED
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][0];
1084 fcmd2
[MTL_AMBIENT_GREEN
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][1];
1085 fcmd2
[MTL_AMBIENT_BLUE
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][2];
1086 fcmd2
[MTL_AMBIENT_ALPHA
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][3];
1088 if (mask
& MAT_BIT_BACK_DIFFUSE
) {
1089 fcmd2
[MTL_DIFFUSE_RED
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][0];
1090 fcmd2
[MTL_DIFFUSE_GREEN
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][1];
1091 fcmd2
[MTL_DIFFUSE_BLUE
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][2];
1092 fcmd2
[MTL_DIFFUSE_ALPHA
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][3];
1094 if (mask
& MAT_BIT_BACK_SPECULAR
) {
1095 fcmd2
[MTL_SPECULAR_RED
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][0];
1096 fcmd2
[MTL_SPECULAR_GREEN
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][1];
1097 fcmd2
[MTL_SPECULAR_BLUE
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][2];
1098 fcmd2
[MTL_SPECULAR_ALPHA
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][3];
1100 if (mask
& MAT_BIT_BACK_SHININESS
) {
1101 fcmd2
[MTL_SHININESS
] = mat
[MAT_ATTRIB_BACK_SHININESS
][0];
1104 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mtl
[0] );
1105 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mtl
[1] );
1107 /* currently material changes cannot trigger a global ambient change, I believe this is correct
1108 update_global_ambient( ctx ); */
1113 * _MESA_NEW_NEED_EYE_COORDS
1115 * Uses derived state from mesa:
1120 * _ModelViewInvScale
1124 * which are calculated in light.c and are correct for the current
1125 * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
1126 * and _MESA_NEW_NEED_EYE_COORDS.
1128 static void update_light( GLcontext
*ctx
)
1130 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1132 /* Have to check these, or have an automatic shortcircuit mechanism
1133 * to remove noop statechanges. (Or just do a better job on the
1137 GLuint tmp
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
];
1139 if (ctx
->_NeedEyeCoords
)
1140 tmp
&= ~R200_LIGHT_IN_MODELSPACE
;
1142 tmp
|= R200_LIGHT_IN_MODELSPACE
;
1144 if (tmp
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
])
1146 R200_STATECHANGE( rmesa
, tcl
);
1147 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] = tmp
;
1152 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( eye
);
1153 fcmd
[EYE_X
] = ctx
->_EyeZDir
[0];
1154 fcmd
[EYE_Y
] = ctx
->_EyeZDir
[1];
1155 fcmd
[EYE_Z
] = - ctx
->_EyeZDir
[2];
1156 fcmd
[EYE_RESCALE_FACTOR
] = ctx
->_ModelViewInvScale
;
1157 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.eye
);
1162 if (ctx
->Light
.Enabled
) {
1164 for (p
= 0 ; p
< MAX_LIGHTS
; p
++) {
1165 if (ctx
->Light
.Light
[p
].Enabled
) {
1166 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1167 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( lit
[p
] );
1169 if (l
->EyePosition
[3] == 0.0) {
1170 COPY_3FV( &fcmd
[LIT_POSITION_X
], l
->_VP_inf_norm
);
1171 COPY_3FV( &fcmd
[LIT_DIRECTION_X
], l
->_h_inf_norm
);
1172 fcmd
[LIT_POSITION_W
] = 0;
1173 fcmd
[LIT_DIRECTION_W
] = 0;
1175 COPY_4V( &fcmd
[LIT_POSITION_X
], l
->_Position
);
1176 fcmd
[LIT_DIRECTION_X
] = -l
->_NormDirection
[0];
1177 fcmd
[LIT_DIRECTION_Y
] = -l
->_NormDirection
[1];
1178 fcmd
[LIT_DIRECTION_Z
] = -l
->_NormDirection
[2];
1179 fcmd
[LIT_DIRECTION_W
] = 0;
1182 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
1188 static void r200Lightfv( GLcontext
*ctx
, GLenum light
,
1189 GLenum pname
, const GLfloat
*params
)
1191 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1192 GLint p
= light
- GL_LIGHT0
;
1193 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1194 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.lit
[p
].cmd
;
1201 update_light_colors( ctx
, p
);
1204 case GL_SPOT_DIRECTION
:
1205 /* picked up in update_light */
1209 /* positions picked up in update_light, but can do flag here */
1210 GLuint flag
= (p
&1)? R200_LIGHT_1_IS_LOCAL
: R200_LIGHT_0_IS_LOCAL
;
1211 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1213 R200_STATECHANGE(rmesa
, tcl
);
1214 if (l
->EyePosition
[3] != 0.0F
)
1215 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1217 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1221 case GL_SPOT_EXPONENT
:
1222 R200_STATECHANGE(rmesa
, lit
[p
]);
1223 fcmd
[LIT_SPOT_EXPONENT
] = params
[0];
1226 case GL_SPOT_CUTOFF
: {
1227 GLuint flag
= (p
&1) ? R200_LIGHT_1_IS_SPOT
: R200_LIGHT_0_IS_SPOT
;
1228 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1230 R200_STATECHANGE(rmesa
, lit
[p
]);
1231 fcmd
[LIT_SPOT_CUTOFF
] = l
->_CosCutoff
;
1233 R200_STATECHANGE(rmesa
, tcl
);
1234 if (l
->SpotCutoff
!= 180.0F
)
1235 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1237 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1242 case GL_CONSTANT_ATTENUATION
:
1243 R200_STATECHANGE(rmesa
, lit
[p
]);
1244 fcmd
[LIT_ATTEN_CONST
] = params
[0];
1245 if ( params
[0] == 0.0 )
1246 fcmd
[LIT_ATTEN_CONST_INV
] = FLT_MAX
;
1248 fcmd
[LIT_ATTEN_CONST_INV
] = 1.0 / params
[0];
1250 case GL_LINEAR_ATTENUATION
:
1251 R200_STATECHANGE(rmesa
, lit
[p
]);
1252 fcmd
[LIT_ATTEN_LINEAR
] = params
[0];
1254 case GL_QUADRATIC_ATTENUATION
:
1255 R200_STATECHANGE(rmesa
, lit
[p
]);
1256 fcmd
[LIT_ATTEN_QUADRATIC
] = params
[0];
1262 /* Set RANGE_ATTEN only when needed */
1265 case GL_CONSTANT_ATTENUATION
:
1266 case GL_LINEAR_ATTENUATION
:
1267 case GL_QUADRATIC_ATTENUATION
: {
1268 GLuint
*icmd
= (GLuint
*)R200_DB_STATE( tcl
);
1269 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1270 GLuint atten_flag
= ( p
&1 ) ? R200_LIGHT_1_ENABLE_RANGE_ATTEN
1271 : R200_LIGHT_0_ENABLE_RANGE_ATTEN
;
1272 GLuint atten_const_flag
= ( p
&1 ) ? R200_LIGHT_1_CONSTANT_RANGE_ATTEN
1273 : R200_LIGHT_0_CONSTANT_RANGE_ATTEN
;
1275 if ( l
->EyePosition
[3] == 0.0F
||
1276 ( ( fcmd
[LIT_ATTEN_CONST
] == 0.0 || fcmd
[LIT_ATTEN_CONST
] == 1.0 ) &&
1277 fcmd
[LIT_ATTEN_QUADRATIC
] == 0.0 && fcmd
[LIT_ATTEN_LINEAR
] == 0.0 ) ) {
1278 /* Disable attenuation */
1279 icmd
[idx
] &= ~atten_flag
;
1281 if ( fcmd
[LIT_ATTEN_QUADRATIC
] == 0.0 && fcmd
[LIT_ATTEN_LINEAR
] == 0.0 ) {
1282 /* Enable only constant portion of attenuation calculation */
1283 icmd
[idx
] |= ( atten_flag
| atten_const_flag
);
1285 /* Enable full attenuation calculation */
1286 icmd
[idx
] &= ~atten_const_flag
;
1287 icmd
[idx
] |= atten_flag
;
1291 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.tcl
);
1299 static void r200UpdateLocalViewer ( GLcontext
*ctx
)
1301 /* It looks like for the texgen modes GL_SPHERE_MAP, GL_NORMAL_MAP and
1302 GL_REFLECTION_MAP we need R200_LOCAL_VIEWER set (fglrx does exactly that
1303 for these and only these modes). This means specular highlights may turn out
1304 wrong in some cases when lighting is enabled but GL_LIGHT_MODEL_LOCAL_VIEWER
1305 is not set, though it seems to happen rarely and the effect seems quite
1306 subtle. May need TCL fallback to fix it completely, though I'm not sure
1307 how you'd identify the cases where the specular highlights indeed will
1308 be wrong. Don't know if fglrx does something special in that case.
1310 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1311 R200_STATECHANGE( rmesa
, tcl
);
1312 if (ctx
->Light
.Model
.LocalViewer
||
1313 ctx
->Texture
._GenFlags
& TEXGEN_NEED_NORMALS
)
1314 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LOCAL_VIEWER
;
1316 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LOCAL_VIEWER
;
1319 static void r200LightModelfv( GLcontext
*ctx
, GLenum pname
,
1320 const GLfloat
*param
)
1322 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1325 case GL_LIGHT_MODEL_AMBIENT
:
1326 update_global_ambient( ctx
);
1329 case GL_LIGHT_MODEL_LOCAL_VIEWER
:
1330 r200UpdateLocalViewer( ctx
);
1333 case GL_LIGHT_MODEL_TWO_SIDE
:
1334 R200_STATECHANGE( rmesa
, tcl
);
1335 if (ctx
->Light
.Model
.TwoSide
)
1336 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHT_TWOSIDE
;
1338 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~(R200_LIGHT_TWOSIDE
);
1339 if (rmesa
->radeon
.TclFallback
) {
1340 r200ChooseRenderState( ctx
);
1341 r200ChooseVertexState( ctx
);
1345 case GL_LIGHT_MODEL_COLOR_CONTROL
:
1346 r200UpdateSpecular(ctx
);
1354 static void r200ShadeModel( GLcontext
*ctx
, GLenum mode
)
1356 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1357 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
1359 s
&= ~(R200_DIFFUSE_SHADE_MASK
|
1360 R200_ALPHA_SHADE_MASK
|
1361 R200_SPECULAR_SHADE_MASK
|
1362 R200_FOG_SHADE_MASK
|
1363 R200_DISC_FOG_SHADE_MASK
);
1367 s
|= (R200_DIFFUSE_SHADE_FLAT
|
1368 R200_ALPHA_SHADE_FLAT
|
1369 R200_SPECULAR_SHADE_FLAT
|
1370 R200_FOG_SHADE_FLAT
|
1371 R200_DISC_FOG_SHADE_FLAT
);
1374 s
|= (R200_DIFFUSE_SHADE_GOURAUD
|
1375 R200_ALPHA_SHADE_GOURAUD
|
1376 R200_SPECULAR_SHADE_GOURAUD
|
1377 R200_FOG_SHADE_GOURAUD
|
1378 R200_DISC_FOG_SHADE_GOURAUD
);
1384 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
1385 R200_STATECHANGE( rmesa
, set
);
1386 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
1391 /* =============================================================
1395 static void r200ClipPlane( GLcontext
*ctx
, GLenum plane
, const GLfloat
*eq
)
1397 GLint p
= (GLint
) plane
- (GLint
) GL_CLIP_PLANE0
;
1398 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1399 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1401 R200_STATECHANGE( rmesa
, ucp
[p
] );
1402 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1403 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1404 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1405 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1408 static void r200UpdateClipPlanes( GLcontext
*ctx
)
1410 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1413 for (p
= 0; p
< ctx
->Const
.MaxClipPlanes
; p
++) {
1414 if (ctx
->Transform
.ClipPlanesEnabled
& (1 << p
)) {
1415 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1417 R200_STATECHANGE( rmesa
, ucp
[p
] );
1418 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1419 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1420 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1421 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1427 /* =============================================================
1432 r200StencilFuncSeparate( GLcontext
*ctx
, GLenum face
, GLenum func
,
1433 GLint ref
, GLuint mask
)
1435 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1436 GLuint refmask
= (((ctx
->Stencil
.Ref
[0] & 0xff) << R200_STENCIL_REF_SHIFT
) |
1437 ((ctx
->Stencil
.ValueMask
[0] & 0xff) << R200_STENCIL_MASK_SHIFT
));
1439 R200_STATECHANGE( rmesa
, ctx
);
1440 R200_STATECHANGE( rmesa
, msk
);
1442 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_STENCIL_TEST_MASK
;
1443 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~(R200_STENCIL_REF_MASK
|
1444 R200_STENCIL_VALUE_MASK
);
1446 switch ( ctx
->Stencil
.Function
[0] ) {
1448 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEVER
;
1451 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LESS
;
1454 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_EQUAL
;
1457 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LEQUAL
;
1460 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GREATER
;
1463 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEQUAL
;
1466 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GEQUAL
;
1469 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_ALWAYS
;
1473 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |= refmask
;
1477 r200StencilMaskSeparate( GLcontext
*ctx
, GLenum face
, GLuint mask
)
1479 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1481 R200_STATECHANGE( rmesa
, msk
);
1482 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~R200_STENCIL_WRITE_MASK
;
1483 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |=
1484 ((ctx
->Stencil
.WriteMask
[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT
);
1488 r200StencilOpSeparate( GLcontext
*ctx
, GLenum face
, GLenum fail
,
1489 GLenum zfail
, GLenum zpass
)
1491 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1493 R200_STATECHANGE( rmesa
, ctx
);
1494 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~(R200_STENCIL_FAIL_MASK
|
1495 R200_STENCIL_ZFAIL_MASK
|
1496 R200_STENCIL_ZPASS_MASK
);
1498 switch ( ctx
->Stencil
.FailFunc
[0] ) {
1500 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_KEEP
;
1503 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_ZERO
;
1506 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_REPLACE
;
1509 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC
;
1512 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC
;
1514 case GL_INCR_WRAP_EXT
:
1515 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC_WRAP
;
1517 case GL_DECR_WRAP_EXT
:
1518 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC_WRAP
;
1521 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INVERT
;
1525 switch ( ctx
->Stencil
.ZFailFunc
[0] ) {
1527 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_KEEP
;
1530 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_ZERO
;
1533 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_REPLACE
;
1536 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC
;
1539 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC
;
1541 case GL_INCR_WRAP_EXT
:
1542 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC_WRAP
;
1544 case GL_DECR_WRAP_EXT
:
1545 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC_WRAP
;
1548 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INVERT
;
1552 switch ( ctx
->Stencil
.ZPassFunc
[0] ) {
1554 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_KEEP
;
1557 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_ZERO
;
1560 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_REPLACE
;
1563 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC
;
1566 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC
;
1568 case GL_INCR_WRAP_EXT
:
1569 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC_WRAP
;
1571 case GL_DECR_WRAP_EXT
:
1572 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC_WRAP
;
1575 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INVERT
;
1580 static void r200ClearStencil( GLcontext
*ctx
, GLint s
)
1582 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1584 rmesa
->radeon
.state
.stencil
.clear
=
1585 ((GLuint
) (ctx
->Stencil
.Clear
& 0xff) |
1586 (0xff << R200_STENCIL_MASK_SHIFT
) |
1587 ((ctx
->Stencil
.WriteMask
[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT
));
1591 /* =============================================================
1592 * Window position and viewport transformation
1596 * To correctly position primitives:
1598 #define SUBPIXEL_X 0.125
1599 #define SUBPIXEL_Y 0.125
1603 * Called when window size or position changes or viewport or depth range
1604 * state is changed. We update the hardware viewport state here.
1606 void r200UpdateWindow( GLcontext
*ctx
)
1608 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1609 __DRIdrawablePrivate
*dPriv
= rmesa
->radeon
.dri
.drawable
;
1610 GLfloat xoffset
= dPriv
? (GLfloat
) dPriv
->x
: 0;
1611 GLfloat yoffset
= dPriv
? (GLfloat
) dPriv
->y
+ dPriv
->h
: 0;
1612 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1614 float_ui32_type sx
= { v
[MAT_SX
] };
1615 float_ui32_type tx
= { v
[MAT_TX
] + xoffset
+ SUBPIXEL_X
};
1616 float_ui32_type sy
= { - v
[MAT_SY
] };
1617 float_ui32_type ty
= { (- v
[MAT_TY
]) + yoffset
+ SUBPIXEL_Y
};
1618 float_ui32_type sz
= { v
[MAT_SZ
] * rmesa
->radeon
.state
.depth
.scale
};
1619 float_ui32_type tz
= { v
[MAT_TZ
] * rmesa
->radeon
.state
.depth
.scale
};
1621 radeon_firevertices(&rmesa
->radeon
);
1622 R200_STATECHANGE( rmesa
, vpt
);
1624 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XSCALE
] = sx
.ui32
;
1625 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = tx
.ui32
;
1626 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YSCALE
] = sy
.ui32
;
1627 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = ty
.ui32
;
1628 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZSCALE
] = sz
.ui32
;
1629 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZOFFSET
] = tz
.ui32
;
1634 static void r200Viewport( GLcontext
*ctx
, GLint x
, GLint y
,
1635 GLsizei width
, GLsizei height
)
1637 /* Don't pipeline viewport changes, conflict with window offset
1638 * setting below. Could apply deltas to rescue pipelined viewport
1639 * values, or keep the originals hanging around.
1641 r200UpdateWindow( ctx
);
1644 static void r200DepthRange( GLcontext
*ctx
, GLclampd nearval
,
1647 r200UpdateWindow( ctx
);
1650 void r200UpdateViewportOffset( GLcontext
*ctx
)
1652 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1653 __DRIdrawablePrivate
*dPriv
= rmesa
->radeon
.dri
.drawable
;
1654 GLfloat xoffset
= (GLfloat
)dPriv
->x
;
1655 GLfloat yoffset
= (GLfloat
)dPriv
->y
+ dPriv
->h
;
1656 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1661 tx
.f
= v
[MAT_TX
] + xoffset
+ SUBPIXEL_X
;
1662 ty
.f
= (- v
[MAT_TY
]) + yoffset
+ SUBPIXEL_Y
;
1664 if ( rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] != tx
.ui32
||
1665 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] != ty
.ui32
)
1667 /* Note: this should also modify whatever data the context reset
1670 R200_STATECHANGE( rmesa
, vpt
);
1671 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = tx
.ui32
;
1672 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = ty
.ui32
;
1674 /* update polygon stipple x/y screen offset */
1677 GLuint m
= rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
];
1679 m
&= ~(R200_STIPPLE_X_OFFSET_MASK
|
1680 R200_STIPPLE_Y_OFFSET_MASK
);
1682 /* add magic offsets, then invert */
1683 stx
= 31 - ((rmesa
->radeon
.dri
.drawable
->x
- 1) & R200_STIPPLE_COORD_MASK
);
1684 sty
= 31 - ((rmesa
->radeon
.dri
.drawable
->y
+ rmesa
->radeon
.dri
.drawable
->h
- 1)
1685 & R200_STIPPLE_COORD_MASK
);
1687 m
|= ((stx
<< R200_STIPPLE_X_OFFSET_SHIFT
) |
1688 (sty
<< R200_STIPPLE_Y_OFFSET_SHIFT
));
1690 if ( rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] != m
) {
1691 R200_STATECHANGE( rmesa
, msc
);
1692 rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] = m
;
1697 radeonUpdateScissor( ctx
);
1702 /* =============================================================
1706 static void r200ClearColor( GLcontext
*ctx
, const GLfloat c
[4] )
1708 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1710 CLAMPED_FLOAT_TO_UBYTE(color
[0], c
[0]);
1711 CLAMPED_FLOAT_TO_UBYTE(color
[1], c
[1]);
1712 CLAMPED_FLOAT_TO_UBYTE(color
[2], c
[2]);
1713 CLAMPED_FLOAT_TO_UBYTE(color
[3], c
[3]);
1714 rmesa
->radeon
.state
.color
.clear
= radeonPackColor( rmesa
->radeon
.radeonScreen
->cpp
,
1716 color
[2], color
[3] );
1720 static void r200RenderMode( GLcontext
*ctx
, GLenum mode
)
1722 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1723 FALLBACK( rmesa
, R200_FALLBACK_RENDER_MODE
, (mode
!= GL_RENDER
) );
1727 static GLuint r200_rop_tab
[] = {
1730 R200_ROP_AND_REVERSE
,
1732 R200_ROP_AND_INVERTED
,
1739 R200_ROP_OR_REVERSE
,
1740 R200_ROP_COPY_INVERTED
,
1741 R200_ROP_OR_INVERTED
,
1746 static void r200LogicOpCode( GLcontext
*ctx
, GLenum opcode
)
1748 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1749 GLuint rop
= (GLuint
)opcode
- GL_CLEAR
;
1753 R200_STATECHANGE( rmesa
, msk
);
1754 rmesa
->hw
.msk
.cmd
[MSK_RB3D_ROPCNTL
] = r200_rop_tab
[rop
];
1758 static void r200DrawBuffer( GLcontext
*ctx
, GLenum mode
)
1760 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1762 if (R200_DEBUG
& DEBUG_DRI
)
1763 fprintf(stderr
, "%s %s\n", __FUNCTION__
,
1764 _mesa_lookup_enum_by_nr( mode
));
1766 radeon_firevertices(&rmesa
->radeon
); /* don't pipeline cliprect changes */
1768 if (ctx
->DrawBuffer
->_NumColorDrawBuffers
!= 1) {
1769 /* 0 (GL_NONE) buffers or multiple color drawing buffers */
1770 FALLBACK( rmesa
, R200_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
1774 switch ( ctx
->DrawBuffer
->_ColorDrawBufferIndexes
[0] ) {
1775 case BUFFER_FRONT_LEFT
:
1776 case BUFFER_BACK_LEFT
:
1777 FALLBACK( rmesa
, R200_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
1780 FALLBACK( rmesa
, R200_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
1784 radeonSetCliprects( &rmesa
->radeon
);
1785 radeonUpdatePageFlipping(&rmesa
->radeon
);
1787 /* We'll set the drawing engine's offset/pitch parameters later
1788 * when we update other state.
1793 static void r200ReadBuffer( GLcontext
*ctx
, GLenum mode
)
1795 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
1798 /* =============================================================
1799 * State enable/disable
1802 static void r200Enable( GLcontext
*ctx
, GLenum cap
, GLboolean state
)
1804 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1807 if ( R200_DEBUG
& DEBUG_STATE
)
1808 fprintf( stderr
, "%s( %s = %s )\n", __FUNCTION__
,
1809 _mesa_lookup_enum_by_nr( cap
),
1810 state
? "GL_TRUE" : "GL_FALSE" );
1813 /* Fast track this one...
1821 R200_STATECHANGE( rmesa
, ctx
);
1823 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ALPHA_TEST_ENABLE
;
1825 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ALPHA_TEST_ENABLE
;
1830 case GL_COLOR_LOGIC_OP
:
1831 r200_set_blend_state( ctx
);
1834 case GL_CLIP_PLANE0
:
1835 case GL_CLIP_PLANE1
:
1836 case GL_CLIP_PLANE2
:
1837 case GL_CLIP_PLANE3
:
1838 case GL_CLIP_PLANE4
:
1839 case GL_CLIP_PLANE5
:
1840 p
= cap
-GL_CLIP_PLANE0
;
1841 R200_STATECHANGE( rmesa
, tcl
);
1843 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= (R200_UCP_ENABLE_0
<<p
);
1844 r200ClipPlane( ctx
, cap
, NULL
);
1847 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~(R200_UCP_ENABLE_0
<<p
);
1851 case GL_COLOR_MATERIAL
:
1852 r200ColorMaterial( ctx
, 0, 0 );
1853 r200UpdateMaterial( ctx
);
1857 r200CullFace( ctx
, 0 );
1861 R200_STATECHANGE(rmesa
, ctx
);
1863 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_Z_ENABLE
;
1865 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_Z_ENABLE
;
1870 R200_STATECHANGE(rmesa
, ctx
);
1872 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_DITHER_ENABLE
;
1873 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~rmesa
->radeon
.state
.color
.roundEnable
;
1875 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_DITHER_ENABLE
;
1876 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= rmesa
->radeon
.state
.color
.roundEnable
;
1881 R200_STATECHANGE(rmesa
, ctx
);
1883 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_FOG_ENABLE
;
1884 r200Fogfv( ctx
, GL_FOG_MODE
, NULL
);
1886 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_FOG_ENABLE
;
1887 R200_STATECHANGE(rmesa
, tcl
);
1888 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_TCL_FOG_MASK
;
1890 r200UpdateSpecular( ctx
); /* for PK_SPEC */
1891 if (rmesa
->radeon
.TclFallback
)
1892 r200ChooseVertexState( ctx
);
1893 _mesa_allow_light_in_model( ctx
, !state
);
1904 R200_STATECHANGE(rmesa
, tcl
);
1905 p
= cap
- GL_LIGHT0
;
1907 flag
= (R200_LIGHT_1_ENABLE
|
1908 R200_LIGHT_1_ENABLE_AMBIENT
|
1909 R200_LIGHT_1_ENABLE_SPECULAR
);
1911 flag
= (R200_LIGHT_0_ENABLE
|
1912 R200_LIGHT_0_ENABLE_AMBIENT
|
1913 R200_LIGHT_0_ENABLE_SPECULAR
);
1916 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] |= flag
;
1918 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] &= ~flag
;
1922 update_light_colors( ctx
, p
);
1926 r200UpdateSpecular(ctx
);
1927 /* for reflection map fixup - might set recheck_texgen for all units too */
1928 rmesa
->radeon
.NewGLState
|= _NEW_TEXTURE
;
1931 case GL_LINE_SMOOTH
:
1932 R200_STATECHANGE( rmesa
, ctx
);
1934 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_LINE
;
1936 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_LINE
;
1940 case GL_LINE_STIPPLE
:
1941 R200_STATECHANGE( rmesa
, set
);
1943 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_PATTERN_ENABLE
;
1945 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_PATTERN_ENABLE
;
1950 R200_STATECHANGE( rmesa
, tcl
);
1952 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_NORMALIZE_NORMALS
;
1954 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_NORMALIZE_NORMALS
;
1958 /* Pointsize registers on r200 only work for point sprites, and point smooth
1959 * doesn't work for point sprites (and isn't needed for 1.0 sized aa points).
1960 * In any case, setting pointmin == pointsizemax == 1.0 for aa points
1961 * is enough to satisfy conform.
1963 case GL_POINT_SMOOTH
:
1966 /* These don't really do anything, as we don't use the 3vtx
1970 case GL_POLYGON_OFFSET_POINT
:
1971 R200_STATECHANGE( rmesa
, set
);
1973 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_POINT
;
1975 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_POINT
;
1979 case GL_POLYGON_OFFSET_LINE
:
1980 R200_STATECHANGE( rmesa
, set
);
1982 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_LINE
;
1984 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_LINE
;
1989 case GL_POINT_SPRITE_ARB
:
1990 R200_STATECHANGE( rmesa
, spr
);
1993 for (i
= 0; i
< 6; i
++) {
1994 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |=
1995 ctx
->Point
.CoordReplace
[i
] << (R200_PS_GEN_TEX_0_SHIFT
+ i
);
1998 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] &= ~R200_PS_GEN_TEX_MASK
;
2002 case GL_POLYGON_OFFSET_FILL
:
2003 R200_STATECHANGE( rmesa
, set
);
2005 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_TRI
;
2007 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_TRI
;
2011 case GL_POLYGON_SMOOTH
:
2012 R200_STATECHANGE( rmesa
, ctx
);
2014 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_POLY
;
2016 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_POLY
;
2020 case GL_POLYGON_STIPPLE
:
2021 R200_STATECHANGE(rmesa
, set
);
2023 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_STIPPLE_ENABLE
;
2025 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_STIPPLE_ENABLE
;
2029 case GL_RESCALE_NORMAL_EXT
: {
2030 GLboolean tmp
= ctx
->_NeedEyeCoords
? state
: !state
;
2031 R200_STATECHANGE( rmesa
, tcl
);
2033 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
2035 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
2040 case GL_SCISSOR_TEST
:
2041 radeon_firevertices(&rmesa
->radeon
);
2042 rmesa
->radeon
.state
.scissor
.enabled
= state
;
2043 radeonUpdateScissor( ctx
);
2046 case GL_STENCIL_TEST
:
2047 if ( rmesa
->radeon
.state
.stencil
.hwBuffer
) {
2048 R200_STATECHANGE( rmesa
, ctx
);
2050 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_STENCIL_ENABLE
;
2052 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_STENCIL_ENABLE
;
2055 FALLBACK( rmesa
, R200_FALLBACK_STENCIL
, state
);
2059 case GL_TEXTURE_GEN_Q
:
2060 case GL_TEXTURE_GEN_R
:
2061 case GL_TEXTURE_GEN_S
:
2062 case GL_TEXTURE_GEN_T
:
2063 /* Picked up in r200UpdateTextureState.
2065 rmesa
->recheck_texgen
[ctx
->Texture
.CurrentUnit
] = GL_TRUE
;
2068 case GL_COLOR_SUM_EXT
:
2069 r200UpdateSpecular ( ctx
);
2072 case GL_VERTEX_PROGRAM_ARB
:
2075 rmesa
->curr_vp_hw
= NULL
;
2076 R200_STATECHANGE( rmesa
, vap
);
2077 rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
] &= ~R200_VAP_PROG_VTX_SHADER_ENABLE
;
2078 /* mark all tcl atoms (tcl vector state got overwritten) dirty
2079 not sure about tcl scalar state - we need at least grd
2080 with vert progs too.
2081 ucp looks like it doesn't get overwritten (may even work
2082 with vp for pos-invariant progs if we're lucky) */
2083 R200_STATECHANGE( rmesa
, mtl
[0] );
2084 R200_STATECHANGE( rmesa
, mtl
[1] );
2085 R200_STATECHANGE( rmesa
, fog
);
2086 R200_STATECHANGE( rmesa
, glt
);
2087 R200_STATECHANGE( rmesa
, eye
);
2088 for (i
= R200_MTX_MV
; i
<= R200_MTX_TEX5
; i
++) {
2089 R200_STATECHANGE( rmesa
, mat
[i
] );
2091 for (i
= 0 ; i
< 8; i
++) {
2092 R200_STATECHANGE( rmesa
, lit
[i
] );
2094 R200_STATECHANGE( rmesa
, tcl
);
2095 for (i
= 0; i
<= ctx
->Const
.MaxClipPlanes
; i
++) {
2096 if (ctx
->Transform
.ClipPlanesEnabled
& (1 << i
)) {
2097 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= (R200_UCP_ENABLE_0
<< i
);
2100 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0 << i);
2103 /* ugly. Need to call everything which might change compsel. */
2104 r200UpdateSpecular( ctx
);
2106 /* shouldn't be necessary, as it's picked up anyway in r200ValidateState (_NEW_PROGRAM),
2107 but without it doom3 locks up at always the same places. Why? */
2108 /* FIXME: This can (and should) be replaced by a call to the TCL_STATE_FLUSH reg before
2109 accessing VAP_SE_VAP_CNTL. Requires drm changes (done). Remove after some time... */
2110 r200UpdateTextureState( ctx
);
2111 /* if we call r200UpdateTextureState we need the code below because we are calling it with
2112 non-current derived enabled values which may revert the state atoms for frag progs even when
2113 they already got disabled... ugh
2114 Should really figure out why we need to call r200UpdateTextureState in the first place */
2116 for (unit
= 0; unit
< R200_MAX_TEXTURE_UNITS
; unit
++) {
2117 R200_STATECHANGE( rmesa
, pix
[unit
] );
2118 R200_STATECHANGE( rmesa
, tex
[unit
] );
2119 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] &=
2120 ~(R200_TXFORMAT_ST_ROUTE_MASK
| R200_TXFORMAT_LOOKUP_DISABLE
);
2121 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] |= unit
<< R200_TXFORMAT_ST_ROUTE_SHIFT
;
2122 /* need to guard this with drmSupportsFragmentShader? Should never get here if
2123 we don't announce ATI_fs, right? */
2124 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXMULTI_CTL
] = 0;
2126 R200_STATECHANGE( rmesa
, cst
);
2127 R200_STATECHANGE( rmesa
, tf
);
2128 rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] = 0;
2132 /* picked up later */
2134 /* call functions which change hw state based on ARB_vp enabled or not. */
2135 r200PointParameter( ctx
, GL_POINT_DISTANCE_ATTENUATION
, NULL
);
2136 r200Fogfv( ctx
, GL_FOG_COORD_SRC
, NULL
);
2139 case GL_VERTEX_PROGRAM_POINT_SIZE_ARB
:
2140 r200PointParameter( ctx
, GL_POINT_DISTANCE_ATTENUATION
, NULL
);
2143 case GL_FRAGMENT_SHADER_ATI
:
2145 /* restore normal tex env colors and make sure tex env combine will get updated
2146 mark env atoms dirty (as their data was overwritten by afs even
2147 if they didn't change) and restore tex coord routing */
2149 for (unit
= 0; unit
< R200_MAX_TEXTURE_UNITS
; unit
++) {
2150 R200_STATECHANGE( rmesa
, pix
[unit
] );
2151 R200_STATECHANGE( rmesa
, tex
[unit
] );
2152 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] &=
2153 ~(R200_TXFORMAT_ST_ROUTE_MASK
| R200_TXFORMAT_LOOKUP_DISABLE
);
2154 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] |= unit
<< R200_TXFORMAT_ST_ROUTE_SHIFT
;
2155 /* need to guard this with drmSupportsFragmentShader? Should never get here if
2156 we don't announce ATI_fs, right? */
2157 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXMULTI_CTL
] = 0;
2159 R200_STATECHANGE( rmesa
, cst
);
2160 R200_STATECHANGE( rmesa
, tf
);
2161 rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] = 0;
2164 /* need to mark this dirty as pix/tf atoms have overwritten the data
2165 even if the data in the atoms didn't change */
2166 R200_STATECHANGE( rmesa
, atf
);
2167 R200_STATECHANGE( rmesa
, afs
[1] );
2168 /* everything else picked up in r200UpdateTextureState hopefully */
2177 void r200LightingSpaceChange( GLcontext
*ctx
)
2179 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2182 if (R200_DEBUG
& DEBUG_STATE
)
2183 fprintf(stderr
, "%s %d BEFORE %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
2184 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
2186 if (ctx
->_NeedEyeCoords
)
2187 tmp
= ctx
->Transform
.RescaleNormals
;
2189 tmp
= !ctx
->Transform
.RescaleNormals
;
2191 R200_STATECHANGE( rmesa
, tcl
);
2193 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
2195 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
2198 if (R200_DEBUG
& DEBUG_STATE
)
2199 fprintf(stderr
, "%s %d AFTER %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
2200 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
2203 /* =============================================================
2204 * Deferred state management - matrices, textures, other?
2210 static void upload_matrix( r200ContextPtr rmesa
, GLfloat
*src
, int idx
)
2212 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
2216 for (i
= 0 ; i
< 4 ; i
++) {
2220 *dest
++ = src
[i
+12];
2223 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
2226 static void upload_matrix_t( r200ContextPtr rmesa
, const GLfloat
*src
, int idx
)
2228 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
2229 memcpy(dest
, src
, 16*sizeof(float));
2230 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
2234 static void update_texturematrix( GLcontext
*ctx
)
2236 r200ContextPtr rmesa
= R200_CONTEXT( ctx
);
2237 GLuint tpc
= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
];
2238 GLuint compsel
= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
];
2241 if (R200_DEBUG
& DEBUG_STATE
)
2242 fprintf(stderr
, "%s before COMPSEL: %x\n", __FUNCTION__
,
2243 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]);
2245 rmesa
->TexMatEnabled
= 0;
2246 rmesa
->TexMatCompSel
= 0;
2248 for (unit
= 0 ; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
2249 if (!ctx
->Texture
.Unit
[unit
]._ReallyEnabled
)
2252 if (ctx
->TextureMatrixStack
[unit
].Top
->type
!= MATRIX_IDENTITY
) {
2253 rmesa
->TexMatEnabled
|= (R200_TEXGEN_TEXMAT_0_ENABLE
|
2254 R200_TEXMAT_0_ENABLE
) << unit
;
2256 rmesa
->TexMatCompSel
|= R200_OUTPUT_TEX_0
<< unit
;
2258 if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2259 /* Need to preconcatenate any active texgen
2260 * obj/eyeplane matrices:
2262 _math_matrix_mul_matrix( &rmesa
->tmpmat
,
2263 ctx
->TextureMatrixStack
[unit
].Top
,
2264 &rmesa
->TexGenMatrix
[unit
] );
2265 upload_matrix( rmesa
, rmesa
->tmpmat
.m
, R200_MTX_TEX0
+unit
);
2268 upload_matrix( rmesa
, ctx
->TextureMatrixStack
[unit
].Top
->m
,
2269 R200_MTX_TEX0
+unit
);
2272 else if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2273 upload_matrix( rmesa
, rmesa
->TexGenMatrix
[unit
].m
,
2274 R200_MTX_TEX0
+unit
);
2278 tpc
= (rmesa
->TexMatEnabled
| rmesa
->TexGenEnabled
);
2279 if (tpc
!= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
]) {
2280 R200_STATECHANGE(rmesa
, tcg
);
2281 rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
] = tpc
;
2284 compsel
&= ~R200_OUTPUT_TEX_MASK
;
2285 compsel
|= rmesa
->TexMatCompSel
| rmesa
->TexGenCompSel
;
2286 if (compsel
!= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]) {
2287 R200_STATECHANGE(rmesa
, vtx
);
2288 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] = compsel
;
2295 * Tell the card where to render (offset, pitch).
2296 * Effected by glDrawBuffer, etc
2299 r200UpdateDrawBuffer(GLcontext
*ctx
)
2301 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2302 struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
2303 struct radeon_renderbuffer
*rrb
;
2305 if (fb
->_ColorDrawBufferIndexes
[0] == BUFFER_FRONT_LEFT
) {
2307 rrb
= (void *) fb
->Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
;
2308 } else if (fb
->_ColorDrawBufferIndexes
[0] == BUFFER_BACK_LEFT
) {
2310 rrb
= (void *) fb
->Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
;
2312 /* drawing to multiple buffers, or none */
2319 R200_STATECHANGE( rmesa
, ctx
);
2322 /* Note: we used the (possibly) page-flipped values */
2323 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLOROFFSET
]
2324 = ((rrb
->flippedOffset
+ rmesa
->radeon
.radeonScreen
->fbLocation
)
2325 & R200_COLOROFFSET_MASK
);
2326 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLORPITCH
] = drb
->flippedPitch
;
2327 if (rmesa
->radeon
.sarea
->tiling_enabled
) {
2328 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLORPITCH
] |= R200_COLOR_TILE_ENABLE
;
2333 static GLboolean
r200ValidateBuffers(GLcontext
*ctx
)
2335 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2336 struct radeon_cs_space_check bos
[8];
2337 struct radeon_renderbuffer
*rrb
;
2340 int flushed
= 0, ret
;
2344 rrb
= radeon_get_colorbuffer(&rmesa
->radeon
);
2346 if (rrb
&& rrb
->bo
) {
2347 bos
[num_bo
].bo
= rrb
->bo
;
2348 bos
[num_bo
].read_domains
= 0;
2349 bos
[num_bo
].write_domain
= RADEON_GEM_DOMAIN_VRAM
;
2350 bos
[num_bo
].new_accounted
= 0;
2355 rrb
= radeon_get_depthbuffer(&rmesa
->radeon
);
2357 if (rrb
&& rrb
->bo
) {
2358 bos
[num_bo
].bo
= rrb
->bo
;
2359 bos
[num_bo
].read_domains
= 0;
2360 bos
[num_bo
].write_domain
= RADEON_GEM_DOMAIN_VRAM
;
2361 bos
[num_bo
].new_accounted
= 0;
2365 for (i
= 0; i
< ctx
->Const
.MaxTextureImageUnits
; ++i
) {
2368 if (!ctx
->Texture
.Unit
[i
]._ReallyEnabled
)
2371 t
= radeon_tex_obj(ctx
->Texture
.Unit
[i
]._Current
);
2372 bos
[num_bo
].bo
= t
->mt
->bo
;
2373 bos
[num_bo
].read_domains
= RADEON_GEM_DOMAIN_GTT
| RADEON_GEM_DOMAIN_VRAM
;
2374 bos
[num_bo
].write_domain
= 0;
2375 bos
[num_bo
].new_accounted
= 0;
2379 ret
= radeon_cs_space_check(rmesa
->radeon
.cmdbuf
.cs
, bos
, num_bo
);
2380 if (ret
== RADEON_CS_SPACE_OP_TO_BIG
)
2382 if (ret
== RADEON_CS_SPACE_FLUSH
) {
2392 GLboolean
r200ValidateState( GLcontext
*ctx
)
2394 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2395 GLuint new_state
= rmesa
->radeon
.NewGLState
;
2397 if (new_state
& (_NEW_BUFFERS
| _NEW_COLOR
| _NEW_PIXEL
)) {
2398 r200UpdateDrawBuffer(ctx
);
2401 if (new_state
& (_NEW_TEXTURE
| _NEW_PROGRAM
)) {
2402 r200UpdateTextureState( ctx
);
2403 new_state
|= rmesa
->radeon
.NewGLState
; /* may add TEXTURE_MATRIX */
2404 r200UpdateLocalViewer( ctx
);
2407 /* we need to do a space check here */
2408 if (!r200ValidateBuffers(ctx
))
2411 /* FIXME: don't really need most of these when vertex progs are enabled */
2413 /* Need an event driven matrix update?
2415 if (new_state
& (_NEW_MODELVIEW
|_NEW_PROJECTION
))
2416 upload_matrix( rmesa
, ctx
->_ModelProjectMatrix
.m
, R200_MTX_MVP
);
2418 /* Need these for lighting (shouldn't upload otherwise)
2420 if (new_state
& (_NEW_MODELVIEW
)) {
2421 upload_matrix( rmesa
, ctx
->ModelviewMatrixStack
.Top
->m
, R200_MTX_MV
);
2422 upload_matrix_t( rmesa
, ctx
->ModelviewMatrixStack
.Top
->inv
, R200_MTX_IMV
);
2425 /* Does this need to be triggered on eg. modelview for
2426 * texgen-derived objplane/eyeplane matrices?
2428 if (new_state
& (_NEW_TEXTURE
|_NEW_TEXTURE_MATRIX
)) {
2429 update_texturematrix( ctx
);
2432 if (new_state
& (_NEW_LIGHT
|_NEW_MODELVIEW
|_MESA_NEW_NEED_EYE_COORDS
)) {
2433 update_light( ctx
);
2436 /* emit all active clip planes if projection matrix changes.
2438 if (new_state
& (_NEW_PROJECTION
)) {
2439 if (ctx
->Transform
.ClipPlanesEnabled
)
2440 r200UpdateClipPlanes( ctx
);
2443 if (new_state
& (_NEW_PROGRAM
|
2444 /* need to test for pretty much anything due to possible parameter bindings */
2445 _NEW_MODELVIEW
|_NEW_PROJECTION
|_NEW_TRANSFORM
|
2446 _NEW_LIGHT
|_NEW_TEXTURE
|_NEW_TEXTURE_MATRIX
|
2447 _NEW_FOG
|_NEW_POINT
|_NEW_TRACK_MATRIX
)) {
2448 if (ctx
->VertexProgram
._Enabled
) {
2449 r200SetupVertexProg( ctx
);
2451 else TCL_FALLBACK(ctx
, R200_TCL_FALLBACK_VERTEX_PROGRAM
, 0);
2454 rmesa
->radeon
.NewGLState
= 0;
2459 static void r200InvalidateState( GLcontext
*ctx
, GLuint new_state
)
2461 _swrast_InvalidateState( ctx
, new_state
);
2462 _swsetup_InvalidateState( ctx
, new_state
);
2463 _vbo_InvalidateState( ctx
, new_state
);
2464 _tnl_InvalidateState( ctx
, new_state
);
2465 _ae_invalidate_state( ctx
, new_state
);
2466 R200_CONTEXT(ctx
)->radeon
.NewGLState
|= new_state
;
2469 /* A hack. The r200 can actually cope just fine with materials
2470 * between begin/ends, so fix this.
2471 * Should map to inputs just like the generic vertex arrays for vertex progs.
2472 * In theory there could still be too many and we'd still need a fallback.
2474 static GLboolean
check_material( GLcontext
*ctx
)
2476 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
2479 for (i
= _TNL_ATTRIB_MAT_FRONT_AMBIENT
;
2480 i
< _TNL_ATTRIB_MAT_BACK_INDEXES
;
2482 if (tnl
->vb
.AttribPtr
[i
] &&
2483 tnl
->vb
.AttribPtr
[i
]->stride
)
2489 static void r200WrapRunPipeline( GLcontext
*ctx
)
2491 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2492 GLboolean has_material
;
2495 fprintf(stderr
, "%s, newstate: %x\n", __FUNCTION__
, rmesa
->radeon
.NewGLState
);
2499 if (rmesa
->radeon
.NewGLState
)
2500 if (!r200ValidateState( ctx
))
2501 FALLBACK(rmesa
, RADEON_FALLBACK_TEXTURE
, GL_TRUE
);
2503 has_material
= !ctx
->VertexProgram
._Enabled
&& ctx
->Light
.Enabled
&& check_material( ctx
);
2506 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_TRUE
);
2509 /* Run the pipeline.
2511 _tnl_run_pipeline( ctx
);
2514 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_FALSE
);
2519 /* Initialize the driver's state functions.
2521 void r200InitStateFuncs( struct dd_function_table
*functions
)
2523 functions
->UpdateState
= r200InvalidateState
;
2524 functions
->LightingSpaceChange
= r200LightingSpaceChange
;
2526 functions
->DrawBuffer
= r200DrawBuffer
;
2527 functions
->ReadBuffer
= r200ReadBuffer
;
2529 functions
->AlphaFunc
= r200AlphaFunc
;
2530 functions
->BlendColor
= r200BlendColor
;
2531 functions
->BlendEquationSeparate
= r200BlendEquationSeparate
;
2532 functions
->BlendFuncSeparate
= r200BlendFuncSeparate
;
2533 functions
->ClearColor
= r200ClearColor
;
2534 functions
->ClearDepth
= r200ClearDepth
;
2535 functions
->ClearIndex
= NULL
;
2536 functions
->ClearStencil
= r200ClearStencil
;
2537 functions
->ClipPlane
= r200ClipPlane
;
2538 functions
->ColorMask
= r200ColorMask
;
2539 functions
->CullFace
= r200CullFace
;
2540 functions
->DepthFunc
= r200DepthFunc
;
2541 functions
->DepthMask
= r200DepthMask
;
2542 functions
->DepthRange
= r200DepthRange
;
2543 functions
->Enable
= r200Enable
;
2544 functions
->Fogfv
= r200Fogfv
;
2545 functions
->FrontFace
= r200FrontFace
;
2546 functions
->Hint
= NULL
;
2547 functions
->IndexMask
= NULL
;
2548 functions
->LightModelfv
= r200LightModelfv
;
2549 functions
->Lightfv
= r200Lightfv
;
2550 functions
->LineStipple
= r200LineStipple
;
2551 functions
->LineWidth
= r200LineWidth
;
2552 functions
->LogicOpcode
= r200LogicOpCode
;
2553 functions
->PolygonMode
= r200PolygonMode
;
2554 functions
->PolygonOffset
= r200PolygonOffset
;
2555 functions
->PolygonStipple
= r200PolygonStipple
;
2556 functions
->PointParameterfv
= r200PointParameter
;
2557 functions
->PointSize
= r200PointSize
;
2558 functions
->RenderMode
= r200RenderMode
;
2559 functions
->Scissor
= radeonScissor
;
2560 functions
->ShadeModel
= r200ShadeModel
;
2561 functions
->StencilFuncSeparate
= r200StencilFuncSeparate
;
2562 functions
->StencilMaskSeparate
= r200StencilMaskSeparate
;
2563 functions
->StencilOpSeparate
= r200StencilOpSeparate
;
2564 functions
->Viewport
= r200Viewport
;
2568 void r200InitTnlFuncs( GLcontext
*ctx
)
2570 TNL_CONTEXT(ctx
)->Driver
.NotifyMaterialChange
= r200UpdateMaterial
;
2571 TNL_CONTEXT(ctx
)->Driver
.RunPipeline
= r200WrapRunPipeline
;