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 <keithw@vmware.com>
36 #include "main/glheader.h"
37 #include "main/imports.h"
38 #include "main/enums.h"
39 #include "main/light.h"
40 #include "main/framebuffer.h"
41 #include "main/fbobject.h"
42 #include "main/state.h"
43 #include "main/stencil.h"
44 #include "main/viewport.h"
46 #include "swrast/swrast.h"
49 #include "tnl/t_pipeline.h"
50 #include "swrast_setup/swrast_setup.h"
51 #include "drivers/common/meta.h"
52 #include "util/bitscan.h"
54 #include "radeon_common.h"
55 #include "radeon_mipmap_tree.h"
56 #include "r200_context.h"
57 #include "r200_ioctl.h"
58 #include "r200_state.h"
61 #include "r200_swtcl.h"
62 #include "r200_vertprog.h"
64 #include "util/simple_list.h"
66 /* =============================================================
70 static void r200AlphaFunc( struct gl_context
*ctx
, GLenum func
, GLfloat ref
)
72 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
73 int pp_misc
= rmesa
->hw
.ctx
.cmd
[CTX_PP_MISC
];
76 CLAMPED_FLOAT_TO_UBYTE(refByte
, ref
);
78 R200_STATECHANGE( rmesa
, ctx
);
80 pp_misc
&= ~(R200_ALPHA_TEST_OP_MASK
| R200_REF_ALPHA_MASK
);
81 pp_misc
|= (refByte
& R200_REF_ALPHA_MASK
);
85 pp_misc
|= R200_ALPHA_TEST_FAIL
;
88 pp_misc
|= R200_ALPHA_TEST_LESS
;
91 pp_misc
|= R200_ALPHA_TEST_EQUAL
;
94 pp_misc
|= R200_ALPHA_TEST_LEQUAL
;
97 pp_misc
|= R200_ALPHA_TEST_GREATER
;
100 pp_misc
|= R200_ALPHA_TEST_NEQUAL
;
103 pp_misc
|= R200_ALPHA_TEST_GEQUAL
;
106 pp_misc
|= R200_ALPHA_TEST_PASS
;
110 rmesa
->hw
.ctx
.cmd
[CTX_PP_MISC
] = pp_misc
;
113 static void r200BlendColor( struct gl_context
*ctx
, const GLfloat cf
[4] )
116 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
117 R200_STATECHANGE( rmesa
, ctx
);
118 CLAMPED_FLOAT_TO_UBYTE(color
[0], cf
[0]);
119 CLAMPED_FLOAT_TO_UBYTE(color
[1], cf
[1]);
120 CLAMPED_FLOAT_TO_UBYTE(color
[2], cf
[2]);
121 CLAMPED_FLOAT_TO_UBYTE(color
[3], cf
[3]);
122 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCOLOR
] = radeonPackColor( 4, color
[0], color
[1], color
[2], color
[3] );
126 * Calculate the hardware blend factor setting. This same function is used
127 * for source and destination of both alpha and RGB.
130 * The hardware register value for the specified blend factor. This value
131 * will need to be shifted into the correct position for either source or
132 * destination factor.
135 * Since the two cases where source and destination are handled differently
136 * are essentially error cases, they should never happen. Determine if these
137 * cases can be removed.
139 static int blend_factor( GLenum factor
, GLboolean is_src
)
145 func
= R200_BLEND_GL_ZERO
;
148 func
= R200_BLEND_GL_ONE
;
151 func
= R200_BLEND_GL_DST_COLOR
;
153 case GL_ONE_MINUS_DST_COLOR
:
154 func
= R200_BLEND_GL_ONE_MINUS_DST_COLOR
;
157 func
= R200_BLEND_GL_SRC_COLOR
;
159 case GL_ONE_MINUS_SRC_COLOR
:
160 func
= R200_BLEND_GL_ONE_MINUS_SRC_COLOR
;
163 func
= R200_BLEND_GL_SRC_ALPHA
;
165 case GL_ONE_MINUS_SRC_ALPHA
:
166 func
= R200_BLEND_GL_ONE_MINUS_SRC_ALPHA
;
169 func
= R200_BLEND_GL_DST_ALPHA
;
171 case GL_ONE_MINUS_DST_ALPHA
:
172 func
= R200_BLEND_GL_ONE_MINUS_DST_ALPHA
;
174 case GL_SRC_ALPHA_SATURATE
:
175 func
= (is_src
) ? R200_BLEND_GL_SRC_ALPHA_SATURATE
: R200_BLEND_GL_ZERO
;
177 case GL_CONSTANT_COLOR
:
178 func
= R200_BLEND_GL_CONST_COLOR
;
180 case GL_ONE_MINUS_CONSTANT_COLOR
:
181 func
= R200_BLEND_GL_ONE_MINUS_CONST_COLOR
;
183 case GL_CONSTANT_ALPHA
:
184 func
= R200_BLEND_GL_CONST_ALPHA
;
186 case GL_ONE_MINUS_CONSTANT_ALPHA
:
187 func
= R200_BLEND_GL_ONE_MINUS_CONST_ALPHA
;
190 func
= (is_src
) ? R200_BLEND_GL_ONE
: R200_BLEND_GL_ZERO
;
196 * Sets both the blend equation and the blend function.
197 * This is done in a single
198 * function because some blend equations (i.e., \c GL_MIN and \c GL_MAX)
199 * change the interpretation of the blend function.
200 * Also, make sure that blend function and blend equation are set to their default
201 * value if color blending is not enabled, since at least blend equations GL_MIN
202 * and GL_FUNC_REVERSE_SUBTRACT will cause wrong results otherwise for
205 static void r200_set_blend_state( struct gl_context
* ctx
)
207 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
208 GLuint cntl
= rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &
209 ~(R200_ROP_ENABLE
| R200_ALPHA_BLEND_ENABLE
| R200_SEPARATE_ALPHA_ENABLE
);
211 int func
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
212 (R200_BLEND_GL_ZERO
<< R200_DST_BLEND_SHIFT
);
213 int eqn
= R200_COMB_FCN_ADD_CLAMP
;
214 int funcA
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
215 (R200_BLEND_GL_ZERO
<< R200_DST_BLEND_SHIFT
);
216 int eqnA
= R200_COMB_FCN_ADD_CLAMP
;
218 R200_STATECHANGE( rmesa
, ctx
);
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
;
235 func
= (blend_factor( ctx
->Color
.Blend
[0].SrcRGB
, GL_TRUE
) << R200_SRC_BLEND_SHIFT
) |
236 (blend_factor( ctx
->Color
.Blend
[0].DstRGB
, GL_FALSE
) << R200_DST_BLEND_SHIFT
);
238 switch(ctx
->Color
.Blend
[0].EquationRGB
) {
240 eqn
= R200_COMB_FCN_ADD_CLAMP
;
243 case GL_FUNC_SUBTRACT
:
244 eqn
= R200_COMB_FCN_SUB_CLAMP
;
247 case GL_FUNC_REVERSE_SUBTRACT
:
248 eqn
= R200_COMB_FCN_RSUB_CLAMP
;
252 eqn
= R200_COMB_FCN_MIN
;
253 func
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
254 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
258 eqn
= R200_COMB_FCN_MAX
;
259 func
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
260 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
264 fprintf( stderr
, "[%s:%u] Invalid RGB blend equation (0x%04x).\n",
265 __func__
, __LINE__
, ctx
->Color
.Blend
[0].EquationRGB
);
269 funcA
= (blend_factor( ctx
->Color
.Blend
[0].SrcA
, GL_TRUE
) << R200_SRC_BLEND_SHIFT
) |
270 (blend_factor( ctx
->Color
.Blend
[0].DstA
, GL_FALSE
) << R200_DST_BLEND_SHIFT
);
272 switch(ctx
->Color
.Blend
[0].EquationA
) {
274 eqnA
= R200_COMB_FCN_ADD_CLAMP
;
277 case GL_FUNC_SUBTRACT
:
278 eqnA
= R200_COMB_FCN_SUB_CLAMP
;
281 case GL_FUNC_REVERSE_SUBTRACT
:
282 eqnA
= R200_COMB_FCN_RSUB_CLAMP
;
286 eqnA
= R200_COMB_FCN_MIN
;
287 funcA
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
288 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
292 eqnA
= R200_COMB_FCN_MAX
;
293 funcA
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
294 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
298 fprintf( stderr
, "[%s:%u] Invalid A blend equation (0x%04x).\n",
299 __func__
, __LINE__
, ctx
->Color
.Blend
[0].EquationA
);
303 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ABLENDCNTL
] = eqnA
| funcA
;
304 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CBLENDCNTL
] = eqn
| func
;
308 static void r200BlendEquationSeparate( struct gl_context
*ctx
,
309 GLenum modeRGB
, GLenum modeA
)
311 r200_set_blend_state( ctx
);
314 static void r200BlendFuncSeparate( struct gl_context
*ctx
,
315 GLenum sfactorRGB
, GLenum dfactorRGB
,
316 GLenum sfactorA
, GLenum dfactorA
)
318 r200_set_blend_state( ctx
);
322 /* =============================================================
326 static void r200DepthFunc( struct gl_context
*ctx
, GLenum func
)
328 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
330 R200_STATECHANGE( rmesa
, ctx
);
331 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_Z_TEST_MASK
;
333 switch ( ctx
->Depth
.Func
) {
335 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_NEVER
;
338 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_LESS
;
341 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_EQUAL
;
344 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_LEQUAL
;
347 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_GREATER
;
350 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_NEQUAL
;
353 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_GEQUAL
;
356 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_ALWAYS
;
361 static void r200DepthMask( struct gl_context
*ctx
, GLboolean flag
)
363 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
364 R200_STATECHANGE( rmesa
, ctx
);
366 if ( ctx
->Depth
.Mask
) {
367 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_WRITE_ENABLE
;
369 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_Z_WRITE_ENABLE
;
374 /* =============================================================
379 static void r200Fogfv( struct gl_context
*ctx
, GLenum pname
, const GLfloat
*param
)
381 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
382 union { int i
; float f
; } c
, d
;
386 c
.i
= rmesa
->hw
.fog
.cmd
[FOG_C
];
387 d
.i
= rmesa
->hw
.fog
.cmd
[FOG_D
];
391 if (!ctx
->Fog
.Enabled
)
393 R200_STATECHANGE(rmesa
, tcl
);
394 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_TCL_FOG_MASK
;
395 switch (ctx
->Fog
.Mode
) {
397 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_LINEAR
;
398 if (ctx
->Fog
.Start
== ctx
->Fog
.End
) {
403 c
.f
= ctx
->Fog
.End
/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
404 d
.f
= -1.0/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
408 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_EXP
;
410 d
.f
= -ctx
->Fog
.Density
;
413 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_EXP2
;
415 d
.f
= -(ctx
->Fog
.Density
* ctx
->Fog
.Density
);
422 switch (ctx
->Fog
.Mode
) {
425 d
.f
= -ctx
->Fog
.Density
;
429 d
.f
= -(ctx
->Fog
.Density
* ctx
->Fog
.Density
);
437 if (ctx
->Fog
.Mode
== GL_LINEAR
) {
438 if (ctx
->Fog
.Start
== ctx
->Fog
.End
) {
442 c
.f
= ctx
->Fog
.End
/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
443 d
.f
= -1.0/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
448 R200_STATECHANGE( rmesa
, ctx
);
449 _mesa_unclamped_float_rgba_to_ubyte(col
, ctx
->Fog
.Color
);
450 i
= radeonPackColor( 4, col
[0], col
[1], col
[2], 0 );
451 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] &= ~R200_FOG_COLOR_MASK
;
452 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] |= i
;
454 case GL_FOG_COORD_SRC
: {
455 GLuint out_0
= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
];
456 GLuint fog
= rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
];
458 fog
&= ~R200_FOG_USE_MASK
;
459 if ( ctx
->Fog
.FogCoordinateSource
== GL_FOG_COORD
|| ctx
->VertexProgram
.Enabled
) {
460 fog
|= R200_FOG_USE_VTX_FOG
;
461 out_0
|= R200_VTX_DISCRETE_FOG
;
464 fog
|= R200_FOG_USE_SPEC_ALPHA
;
465 out_0
&= ~R200_VTX_DISCRETE_FOG
;
468 if ( fog
!= rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] ) {
469 R200_STATECHANGE( rmesa
, ctx
);
470 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] = fog
;
473 if (out_0
!= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
]) {
474 R200_STATECHANGE( rmesa
, vtx
);
475 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] = out_0
;
484 if (c
.i
!= rmesa
->hw
.fog
.cmd
[FOG_C
] || d
.i
!= rmesa
->hw
.fog
.cmd
[FOG_D
]) {
485 R200_STATECHANGE( rmesa
, fog
);
486 rmesa
->hw
.fog
.cmd
[FOG_C
] = c
.i
;
487 rmesa
->hw
.fog
.cmd
[FOG_D
] = d
.i
;
491 /* =============================================================
495 static void r200CullFace( struct gl_context
*ctx
, GLenum unused
)
497 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
498 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
499 GLuint t
= rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
];
501 s
|= R200_FFACE_SOLID
| R200_BFACE_SOLID
;
502 t
&= ~(R200_CULL_FRONT
| R200_CULL_BACK
);
504 if ( ctx
->Polygon
.CullFlag
) {
505 switch ( ctx
->Polygon
.CullFaceMode
) {
507 s
&= ~R200_FFACE_SOLID
;
508 t
|= R200_CULL_FRONT
;
511 s
&= ~R200_BFACE_SOLID
;
514 case GL_FRONT_AND_BACK
:
515 s
&= ~(R200_FFACE_SOLID
| R200_BFACE_SOLID
);
516 t
|= (R200_CULL_FRONT
| R200_CULL_BACK
);
521 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
522 R200_STATECHANGE(rmesa
, set
);
523 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
526 if ( rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] != t
) {
527 R200_STATECHANGE(rmesa
, tcl
);
528 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] = t
;
532 static void r200FrontFace( struct gl_context
*ctx
, GLenum mode
)
534 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
535 int cull_face
= (mode
== GL_CW
) ? R200_FFACE_CULL_CW
: R200_FFACE_CULL_CCW
;
537 R200_STATECHANGE( rmesa
, set
);
538 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_FFACE_CULL_DIR_MASK
;
540 R200_STATECHANGE( rmesa
, tcl
);
541 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_CULL_FRONT_IS_CCW
;
543 /* Winding is inverted when rendering to FBO */
544 if (ctx
->DrawBuffer
&& _mesa_is_user_fbo(ctx
->DrawBuffer
))
545 cull_face
= (mode
== GL_CCW
) ? R200_FFACE_CULL_CW
: R200_FFACE_CULL_CCW
;
546 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= cull_face
;
548 if ( mode
== GL_CCW
)
549 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_CULL_FRONT_IS_CCW
;
552 /* =============================================================
555 static void r200PointSize( struct gl_context
*ctx
, GLfloat size
)
557 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
558 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.ptp
.cmd
;
560 radeon_print(RADEON_STATE
, RADEON_TRACE
,
561 "%s(%p) size: %f, fixed point result: %d.%d (%d/16)\n",
563 ((GLuint
)(ctx
->Point
.Size
* 16.0))/16,
564 (((GLuint
)(ctx
->Point
.Size
* 16.0))&15)*100/16,
565 ((GLuint
)(ctx
->Point
.Size
* 16.0))&15);
567 R200_STATECHANGE( rmesa
, cst
);
568 R200_STATECHANGE( rmesa
, ptp
);
569 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] &= ~0xffff;
570 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] |= ((GLuint
)(ctx
->Point
.Size
* 16.0));
571 /* this is the size param of the point size calculation (point size reg value
572 is not used when calculation is active). */
573 fcmd
[PTP_VPORT_SCALE_PTSIZE
] = ctx
->Point
.Size
;
576 static void r200PointParameter( struct gl_context
*ctx
, GLenum pname
, const GLfloat
*params
)
578 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
579 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.ptp
.cmd
;
582 case GL_POINT_SIZE_MIN
:
583 /* Can clamp both in tcl and setup - just set both (as does fglrx) */
584 R200_STATECHANGE( rmesa
, lin
);
585 R200_STATECHANGE( rmesa
, ptp
);
586 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] &= 0xffff;
587 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] |= (GLuint
)(ctx
->Point
.MinSize
* 16.0) << 16;
588 fcmd
[PTP_CLAMP_MIN
] = ctx
->Point
.MinSize
;
590 case GL_POINT_SIZE_MAX
:
591 R200_STATECHANGE( rmesa
, cst
);
592 R200_STATECHANGE( rmesa
, ptp
);
593 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] &= 0xffff;
594 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] |= (GLuint
)(ctx
->Point
.MaxSize
* 16.0) << 16;
595 fcmd
[PTP_CLAMP_MAX
] = ctx
->Point
.MaxSize
;
597 case GL_POINT_DISTANCE_ATTENUATION
:
598 R200_STATECHANGE( rmesa
, vtx
);
599 R200_STATECHANGE( rmesa
, spr
);
600 R200_STATECHANGE( rmesa
, ptp
);
601 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.ptp
.cmd
;
602 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] &=
603 ~(R200_PS_MULT_MASK
| R200_PS_LIN_ATT_ZERO
| R200_PS_SE_SEL_STATE
);
604 /* can't rely on ctx->Point._Attenuated here and test for NEW_POINT in
605 r200ValidateState looks like overkill */
606 if (ctx
->Point
.Params
[0] != 1.0 ||
607 ctx
->Point
.Params
[1] != 0.0 ||
608 ctx
->Point
.Params
[2] != 0.0 ||
609 (ctx
->VertexProgram
.Enabled
&& ctx
->VertexProgram
.PointSizeEnabled
)) {
610 /* all we care for vp would be the ps_se_sel_state setting */
611 fcmd
[PTP_ATT_CONST_QUAD
] = ctx
->Point
.Params
[2];
612 fcmd
[PTP_ATT_CONST_LIN
] = ctx
->Point
.Params
[1];
613 fcmd
[PTP_ATT_CONST_CON
] = ctx
->Point
.Params
[0];
614 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |= R200_PS_MULT_ATTENCONST
;
615 if (ctx
->Point
.Params
[1] == 0.0)
616 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |= R200_PS_LIN_ATT_ZERO
;
617 /* FIXME: setting this here doesn't look quite ok - we only want to do
618 that if we're actually drawing points probably */
619 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_PT_SIZE
;
620 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |= R200_VTX_POINT_SIZE
;
623 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |=
624 R200_PS_SE_SEL_STATE
| R200_PS_MULT_CONST
;
625 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_PT_SIZE
;
626 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~R200_VTX_POINT_SIZE
;
629 case GL_POINT_FADE_THRESHOLD_SIZE
:
630 /* don't support multisampling, so doesn't matter. */
632 /* can't do these but don't need them.
633 case GL_POINT_SPRITE_R_MODE_NV:
634 case GL_POINT_SPRITE_COORD_ORIGIN: */
636 fprintf(stderr
, "bad pname parameter in r200PointParameter\n");
641 /* =============================================================
644 static void r200LineWidth( struct gl_context
*ctx
, GLfloat widthf
)
646 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
648 R200_STATECHANGE( rmesa
, lin
);
649 R200_STATECHANGE( rmesa
, set
);
651 /* Line width is stored in U6.4 format.
652 * Same min/max limits for AA, non-AA lines.
654 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] &= ~0xffff;
655 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] |= (GLuint
)
656 (CLAMP(widthf
, ctx
->Const
.MinLineWidth
, ctx
->Const
.MaxLineWidth
) * 16.0);
658 if ( widthf
> 1.0 ) {
659 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_WIDELINE_ENABLE
;
661 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_WIDELINE_ENABLE
;
665 static void r200LineStipple( struct gl_context
*ctx
, GLint factor
, GLushort pattern
)
667 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
669 R200_STATECHANGE( rmesa
, lin
);
670 rmesa
->hw
.lin
.cmd
[LIN_RE_LINE_PATTERN
] =
671 ((((GLuint
)factor
& 0xff) << 16) | ((GLuint
)pattern
));
675 /* =============================================================
678 static void r200ColorMask( struct gl_context
*ctx
,
679 GLboolean r
, GLboolean g
,
680 GLboolean b
, GLboolean a
)
682 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
684 struct radeon_renderbuffer
*rrb
;
685 GLuint flag
= rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] & ~R200_PLANE_MASK_ENABLE
;
687 rrb
= radeon_get_colorbuffer(&rmesa
->radeon
);
690 mask
= radeonPackColor( rrb
->cpp
,
691 GET_COLORMASK_BIT(ctx
->Color
.ColorMask
, 0, 0)*0xFF,
692 GET_COLORMASK_BIT(ctx
->Color
.ColorMask
, 0, 1)*0xFF,
693 GET_COLORMASK_BIT(ctx
->Color
.ColorMask
, 0, 2)*0xFF,
694 GET_COLORMASK_BIT(ctx
->Color
.ColorMask
, 0, 3)*0xFF );
697 if (!(r
&& g
&& b
&& a
))
698 flag
|= R200_PLANE_MASK_ENABLE
;
700 if ( rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] != flag
) {
701 R200_STATECHANGE( rmesa
, ctx
);
702 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = flag
;
705 if ( rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
] != mask
) {
706 R200_STATECHANGE( rmesa
, msk
);
707 rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
] = mask
;
712 /* =============================================================
716 static void r200PolygonOffset( struct gl_context
*ctx
,
717 GLfloat factor
, GLfloat units
, GLfloat clamp
)
719 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
720 const GLfloat depthScale
= 1.0F
/ ctx
->DrawBuffer
->_DepthMaxF
;
721 float_ui32_type constant
= { units
* depthScale
};
722 float_ui32_type factoru
= { factor
};
727 /* fprintf(stderr, "%s f:%f u:%f\n", __func__, factor, constant); */
729 R200_STATECHANGE( rmesa
, zbs
);
730 rmesa
->hw
.zbs
.cmd
[ZBS_SE_ZBIAS_FACTOR
] = factoru
.ui32
;
731 rmesa
->hw
.zbs
.cmd
[ZBS_SE_ZBIAS_CONSTANT
] = constant
.ui32
;
734 static void r200PolygonMode( struct gl_context
*ctx
, GLenum face
, GLenum mode
)
736 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
737 GLboolean unfilled
= (ctx
->Polygon
.FrontMode
!= GL_FILL
||
738 ctx
->Polygon
.BackMode
!= GL_FILL
);
740 /* Can't generally do unfilled via tcl, but some good special
743 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_UNFILLED
, unfilled
);
744 if (rmesa
->radeon
.TclFallback
) {
745 r200ChooseRenderState( ctx
);
746 r200ChooseVertexState( ctx
);
751 /* =============================================================
752 * Rendering attributes
754 * We really don't want to recalculate all this every time we bind a
755 * texture. These things shouldn't change all that often, so it makes
756 * sense to break them out of the core texture state update routines.
759 /* Examine lighting and texture state to determine if separate specular
762 static void r200UpdateSpecular( struct gl_context
*ctx
)
764 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
765 uint32_t p
= rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
];
767 R200_STATECHANGE( rmesa
, tcl
);
768 R200_STATECHANGE( rmesa
, vtx
);
770 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~(3<<R200_VTX_COLOR_0_SHIFT
);
771 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~(3<<R200_VTX_COLOR_1_SHIFT
);
772 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_COLOR_0
;
773 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_COLOR_1
;
774 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LIGHTING_ENABLE
;
776 p
&= ~R200_SPECULAR_ENABLE
;
778 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_DIFFUSE_SPECULAR_COMBINE
;
781 if (ctx
->Light
.Enabled
&&
782 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
) {
783 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
784 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
) |
785 (R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
786 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_0
;
787 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_1
;
788 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHTING_ENABLE
;
789 p
|= R200_SPECULAR_ENABLE
;
790 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &=
791 ~R200_DIFFUSE_SPECULAR_COMBINE
;
793 else if (ctx
->Light
.Enabled
) {
794 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
795 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
));
796 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_0
;
797 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHTING_ENABLE
;
798 } else if (ctx
->Fog
.ColorSumEnabled
) {
799 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
800 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
) |
801 (R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
802 p
|= R200_SPECULAR_ENABLE
;
804 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
805 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
));
808 if (ctx
->Fog
.Enabled
) {
809 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
810 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
811 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_1
;
814 if ( rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] != p
) {
815 R200_STATECHANGE( rmesa
, ctx
);
816 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] = p
;
819 /* Update vertex/render formats
821 if (rmesa
->radeon
.TclFallback
) {
822 r200ChooseRenderState( ctx
);
823 r200ChooseVertexState( ctx
);
828 /* =============================================================
833 /* Update on colormaterial, material emmissive/ambient,
834 * lightmodel.globalambient
836 static void update_global_ambient( struct gl_context
*ctx
)
838 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
839 float *fcmd
= (float *)R200_DB_STATE( glt
);
841 /* Need to do more if both emmissive & ambient are PREMULT:
842 * I believe this is not nessary when using source_material. This condition thus
843 * will never happen currently, and the function has no dependencies on materials now
845 if ((rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
] &
846 ((3 << R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
847 (3 << R200_FRONT_AMBIENT_SOURCE_SHIFT
))) == 0)
849 COPY_3V( &fcmd
[GLT_RED
],
850 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_EMISSION
]);
851 ACC_SCALE_3V( &fcmd
[GLT_RED
],
852 ctx
->Light
.Model
.Ambient
,
853 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_AMBIENT
]);
857 COPY_3V( &fcmd
[GLT_RED
], ctx
->Light
.Model
.Ambient
);
860 R200_DB_STATECHANGE(rmesa
, &rmesa
->hw
.glt
);
863 /* Update on change to
867 static void update_light_colors( struct gl_context
*ctx
, GLuint p
)
869 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
871 /* fprintf(stderr, "%s\n", __func__); */
874 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
875 float *fcmd
= (float *)R200_DB_STATE( lit
[p
] );
877 COPY_4V( &fcmd
[LIT_AMBIENT_RED
], l
->Ambient
);
878 COPY_4V( &fcmd
[LIT_DIFFUSE_RED
], l
->Diffuse
);
879 COPY_4V( &fcmd
[LIT_SPECULAR_RED
], l
->Specular
);
881 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
885 static void r200ColorMaterial( struct gl_context
*ctx
, GLenum face
, GLenum mode
)
887 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
888 GLuint light_model_ctl1
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
];
889 light_model_ctl1
&= ~((0xf << R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
890 (0xf << R200_FRONT_AMBIENT_SOURCE_SHIFT
) |
891 (0xf << R200_FRONT_DIFFUSE_SOURCE_SHIFT
) |
892 (0xf << R200_FRONT_SPECULAR_SOURCE_SHIFT
) |
893 (0xf << R200_BACK_EMISSIVE_SOURCE_SHIFT
) |
894 (0xf << R200_BACK_AMBIENT_SOURCE_SHIFT
) |
895 (0xf << R200_BACK_DIFFUSE_SOURCE_SHIFT
) |
896 (0xf << R200_BACK_SPECULAR_SOURCE_SHIFT
));
898 if (ctx
->Light
.ColorMaterialEnabled
) {
899 GLuint mask
= ctx
->Light
._ColorMaterialBitmask
;
901 if (mask
& MAT_BIT_FRONT_EMISSION
) {
902 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
903 R200_FRONT_EMISSIVE_SOURCE_SHIFT
);
906 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
907 R200_FRONT_EMISSIVE_SOURCE_SHIFT
);
909 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
910 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
911 R200_FRONT_AMBIENT_SOURCE_SHIFT
);
914 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
915 R200_FRONT_AMBIENT_SOURCE_SHIFT
);
917 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
918 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
919 R200_FRONT_DIFFUSE_SOURCE_SHIFT
);
922 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
923 R200_FRONT_DIFFUSE_SOURCE_SHIFT
);
925 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
926 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
927 R200_FRONT_SPECULAR_SOURCE_SHIFT
);
930 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
931 R200_FRONT_SPECULAR_SOURCE_SHIFT
);
934 if (mask
& MAT_BIT_BACK_EMISSION
) {
935 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
936 R200_BACK_EMISSIVE_SOURCE_SHIFT
);
939 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
940 R200_BACK_EMISSIVE_SOURCE_SHIFT
);
942 if (mask
& MAT_BIT_BACK_AMBIENT
) {
943 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
944 R200_BACK_AMBIENT_SOURCE_SHIFT
);
946 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
947 R200_BACK_AMBIENT_SOURCE_SHIFT
);
949 if (mask
& MAT_BIT_BACK_DIFFUSE
) {
950 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
951 R200_BACK_DIFFUSE_SOURCE_SHIFT
);
953 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
954 R200_BACK_DIFFUSE_SOURCE_SHIFT
);
956 if (mask
& MAT_BIT_BACK_SPECULAR
) {
957 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
958 R200_BACK_SPECULAR_SOURCE_SHIFT
);
961 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
962 R200_BACK_SPECULAR_SOURCE_SHIFT
);
966 /* Default to SOURCE_MATERIAL:
969 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
970 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_AMBIENT_SOURCE_SHIFT
) |
971 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_DIFFUSE_SOURCE_SHIFT
) |
972 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_SPECULAR_SOURCE_SHIFT
) |
973 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_EMISSIVE_SOURCE_SHIFT
) |
974 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_AMBIENT_SOURCE_SHIFT
) |
975 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_DIFFUSE_SOURCE_SHIFT
) |
976 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_SPECULAR_SOURCE_SHIFT
);
979 if (light_model_ctl1
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
]) {
980 R200_STATECHANGE( rmesa
, tcl
);
981 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
] = light_model_ctl1
;
987 void r200UpdateMaterial( struct gl_context
*ctx
)
989 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
990 GLfloat (*mat
)[4] = ctx
->Light
.Material
.Attrib
;
991 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( mtl
[0] );
992 GLfloat
*fcmd2
= (GLfloat
*)R200_DB_STATE( mtl
[1] );
995 /* Might be possible and faster to update everything unconditionally? */
996 if (ctx
->Light
.ColorMaterialEnabled
)
997 mask
&= ~ctx
->Light
._ColorMaterialBitmask
;
999 if (R200_DEBUG
& RADEON_STATE
)
1000 fprintf(stderr
, "%s\n", __func__
);
1002 if (mask
& MAT_BIT_FRONT_EMISSION
) {
1003 fcmd
[MTL_EMMISSIVE_RED
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][0];
1004 fcmd
[MTL_EMMISSIVE_GREEN
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][1];
1005 fcmd
[MTL_EMMISSIVE_BLUE
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][2];
1006 fcmd
[MTL_EMMISSIVE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][3];
1008 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
1009 fcmd
[MTL_AMBIENT_RED
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][0];
1010 fcmd
[MTL_AMBIENT_GREEN
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][1];
1011 fcmd
[MTL_AMBIENT_BLUE
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][2];
1012 fcmd
[MTL_AMBIENT_ALPHA
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][3];
1014 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
1015 fcmd
[MTL_DIFFUSE_RED
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][0];
1016 fcmd
[MTL_DIFFUSE_GREEN
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][1];
1017 fcmd
[MTL_DIFFUSE_BLUE
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][2];
1018 fcmd
[MTL_DIFFUSE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][3];
1020 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
1021 fcmd
[MTL_SPECULAR_RED
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][0];
1022 fcmd
[MTL_SPECULAR_GREEN
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][1];
1023 fcmd
[MTL_SPECULAR_BLUE
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][2];
1024 fcmd
[MTL_SPECULAR_ALPHA
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][3];
1026 if (mask
& MAT_BIT_FRONT_SHININESS
) {
1027 fcmd
[MTL_SHININESS
] = mat
[MAT_ATTRIB_FRONT_SHININESS
][0];
1030 if (mask
& MAT_BIT_BACK_EMISSION
) {
1031 fcmd2
[MTL_EMMISSIVE_RED
] = mat
[MAT_ATTRIB_BACK_EMISSION
][0];
1032 fcmd2
[MTL_EMMISSIVE_GREEN
] = mat
[MAT_ATTRIB_BACK_EMISSION
][1];
1033 fcmd2
[MTL_EMMISSIVE_BLUE
] = mat
[MAT_ATTRIB_BACK_EMISSION
][2];
1034 fcmd2
[MTL_EMMISSIVE_ALPHA
] = mat
[MAT_ATTRIB_BACK_EMISSION
][3];
1036 if (mask
& MAT_BIT_BACK_AMBIENT
) {
1037 fcmd2
[MTL_AMBIENT_RED
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][0];
1038 fcmd2
[MTL_AMBIENT_GREEN
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][1];
1039 fcmd2
[MTL_AMBIENT_BLUE
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][2];
1040 fcmd2
[MTL_AMBIENT_ALPHA
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][3];
1042 if (mask
& MAT_BIT_BACK_DIFFUSE
) {
1043 fcmd2
[MTL_DIFFUSE_RED
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][0];
1044 fcmd2
[MTL_DIFFUSE_GREEN
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][1];
1045 fcmd2
[MTL_DIFFUSE_BLUE
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][2];
1046 fcmd2
[MTL_DIFFUSE_ALPHA
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][3];
1048 if (mask
& MAT_BIT_BACK_SPECULAR
) {
1049 fcmd2
[MTL_SPECULAR_RED
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][0];
1050 fcmd2
[MTL_SPECULAR_GREEN
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][1];
1051 fcmd2
[MTL_SPECULAR_BLUE
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][2];
1052 fcmd2
[MTL_SPECULAR_ALPHA
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][3];
1054 if (mask
& MAT_BIT_BACK_SHININESS
) {
1055 fcmd2
[MTL_SHININESS
] = mat
[MAT_ATTRIB_BACK_SHININESS
][0];
1058 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mtl
[0] );
1059 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mtl
[1] );
1061 /* currently material changes cannot trigger a global ambient change, I believe this is correct
1062 update_global_ambient( ctx ); */
1067 * _MESA_NEW_NEED_EYE_COORDS
1069 * Uses derived state from mesa:
1073 * _NormSpotDirection
1074 * _ModelViewInvScale
1078 * which are calculated in light.c and are correct for the current
1079 * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
1080 * and _MESA_NEW_NEED_EYE_COORDS.
1082 static void update_light( struct gl_context
*ctx
)
1084 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1086 /* Have to check these, or have an automatic shortcircuit mechanism
1087 * to remove noop statechanges. (Or just do a better job on the
1091 GLuint tmp
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
];
1093 if (ctx
->_NeedEyeCoords
)
1094 tmp
&= ~R200_LIGHT_IN_MODELSPACE
;
1096 tmp
|= R200_LIGHT_IN_MODELSPACE
;
1098 if (tmp
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
])
1100 R200_STATECHANGE( rmesa
, tcl
);
1101 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] = tmp
;
1106 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( eye
);
1107 fcmd
[EYE_X
] = ctx
->_EyeZDir
[0];
1108 fcmd
[EYE_Y
] = ctx
->_EyeZDir
[1];
1109 fcmd
[EYE_Z
] = - ctx
->_EyeZDir
[2];
1110 fcmd
[EYE_RESCALE_FACTOR
] = ctx
->_ModelViewInvScale
;
1111 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.eye
);
1116 if (ctx
->Light
.Enabled
) {
1117 GLbitfield mask
= ctx
->Light
._EnabledLights
;
1119 const int p
= u_bit_scan(&mask
);
1120 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1121 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( lit
[p
] );
1123 if (l
->EyePosition
[3] == 0.0) {
1124 COPY_3FV( &fcmd
[LIT_POSITION_X
], l
->_VP_inf_norm
);
1125 COPY_3FV( &fcmd
[LIT_DIRECTION_X
], l
->_h_inf_norm
);
1126 fcmd
[LIT_POSITION_W
] = 0;
1127 fcmd
[LIT_DIRECTION_W
] = 0;
1129 COPY_4V( &fcmd
[LIT_POSITION_X
], l
->_Position
);
1130 fcmd
[LIT_DIRECTION_X
] = -l
->_NormSpotDirection
[0];
1131 fcmd
[LIT_DIRECTION_Y
] = -l
->_NormSpotDirection
[1];
1132 fcmd
[LIT_DIRECTION_Z
] = -l
->_NormSpotDirection
[2];
1133 fcmd
[LIT_DIRECTION_W
] = 0;
1136 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
1141 static void r200Lightfv( struct gl_context
*ctx
, GLenum light
,
1142 GLenum pname
, const GLfloat
*params
)
1144 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1145 GLint p
= light
- GL_LIGHT0
;
1146 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1147 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.lit
[p
].cmd
;
1154 update_light_colors( ctx
, p
);
1157 case GL_SPOT_DIRECTION
:
1158 /* picked up in update_light */
1162 /* positions picked up in update_light, but can do flag here */
1163 GLuint flag
= (p
&1)? R200_LIGHT_1_IS_LOCAL
: R200_LIGHT_0_IS_LOCAL
;
1164 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1166 R200_STATECHANGE(rmesa
, tcl
);
1167 if (l
->EyePosition
[3] != 0.0F
)
1168 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1170 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1174 case GL_SPOT_EXPONENT
:
1175 R200_STATECHANGE(rmesa
, lit
[p
]);
1176 fcmd
[LIT_SPOT_EXPONENT
] = params
[0];
1179 case GL_SPOT_CUTOFF
: {
1180 GLuint flag
= (p
&1) ? R200_LIGHT_1_IS_SPOT
: R200_LIGHT_0_IS_SPOT
;
1181 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1183 R200_STATECHANGE(rmesa
, lit
[p
]);
1184 fcmd
[LIT_SPOT_CUTOFF
] = l
->_CosCutoff
;
1186 R200_STATECHANGE(rmesa
, tcl
);
1187 if (l
->SpotCutoff
!= 180.0F
)
1188 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1190 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1195 case GL_CONSTANT_ATTENUATION
:
1196 R200_STATECHANGE(rmesa
, lit
[p
]);
1197 fcmd
[LIT_ATTEN_CONST
] = params
[0];
1198 if ( params
[0] == 0.0 )
1199 fcmd
[LIT_ATTEN_CONST_INV
] = FLT_MAX
;
1201 fcmd
[LIT_ATTEN_CONST_INV
] = 1.0 / params
[0];
1203 case GL_LINEAR_ATTENUATION
:
1204 R200_STATECHANGE(rmesa
, lit
[p
]);
1205 fcmd
[LIT_ATTEN_LINEAR
] = params
[0];
1207 case GL_QUADRATIC_ATTENUATION
:
1208 R200_STATECHANGE(rmesa
, lit
[p
]);
1209 fcmd
[LIT_ATTEN_QUADRATIC
] = params
[0];
1215 /* Set RANGE_ATTEN only when needed */
1218 case GL_CONSTANT_ATTENUATION
:
1219 case GL_LINEAR_ATTENUATION
:
1220 case GL_QUADRATIC_ATTENUATION
: {
1221 GLuint
*icmd
= (GLuint
*)R200_DB_STATE( tcl
);
1222 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1223 GLuint atten_flag
= ( p
&1 ) ? R200_LIGHT_1_ENABLE_RANGE_ATTEN
1224 : R200_LIGHT_0_ENABLE_RANGE_ATTEN
;
1225 GLuint atten_const_flag
= ( p
&1 ) ? R200_LIGHT_1_CONSTANT_RANGE_ATTEN
1226 : R200_LIGHT_0_CONSTANT_RANGE_ATTEN
;
1228 if ( l
->EyePosition
[3] == 0.0F
||
1229 ( ( fcmd
[LIT_ATTEN_CONST
] == 0.0 || fcmd
[LIT_ATTEN_CONST
] == 1.0 ) &&
1230 fcmd
[LIT_ATTEN_QUADRATIC
] == 0.0 && fcmd
[LIT_ATTEN_LINEAR
] == 0.0 ) ) {
1231 /* Disable attenuation */
1232 icmd
[idx
] &= ~atten_flag
;
1234 if ( fcmd
[LIT_ATTEN_QUADRATIC
] == 0.0 && fcmd
[LIT_ATTEN_LINEAR
] == 0.0 ) {
1235 /* Enable only constant portion of attenuation calculation */
1236 icmd
[idx
] |= ( atten_flag
| atten_const_flag
);
1238 /* Enable full attenuation calculation */
1239 icmd
[idx
] &= ~atten_const_flag
;
1240 icmd
[idx
] |= atten_flag
;
1244 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.tcl
);
1252 static void r200UpdateLocalViewer ( struct gl_context
*ctx
)
1254 /* It looks like for the texgen modes GL_SPHERE_MAP, GL_NORMAL_MAP and
1255 GL_REFLECTION_MAP we need R200_LOCAL_VIEWER set (fglrx does exactly that
1256 for these and only these modes). This means specular highlights may turn out
1257 wrong in some cases when lighting is enabled but GL_LIGHT_MODEL_LOCAL_VIEWER
1258 is not set, though it seems to happen rarely and the effect seems quite
1259 subtle. May need TCL fallback to fix it completely, though I'm not sure
1260 how you'd identify the cases where the specular highlights indeed will
1261 be wrong. Don't know if fglrx does something special in that case.
1263 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1264 R200_STATECHANGE( rmesa
, tcl
);
1265 if (ctx
->Light
.Model
.LocalViewer
||
1266 ctx
->Texture
._GenFlags
& TEXGEN_NEED_NORMALS
)
1267 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LOCAL_VIEWER
;
1269 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LOCAL_VIEWER
;
1272 static void r200LightModelfv( struct gl_context
*ctx
, GLenum pname
,
1273 const GLfloat
*param
)
1275 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1278 case GL_LIGHT_MODEL_AMBIENT
:
1279 update_global_ambient( ctx
);
1282 case GL_LIGHT_MODEL_LOCAL_VIEWER
:
1283 r200UpdateLocalViewer( ctx
);
1286 case GL_LIGHT_MODEL_TWO_SIDE
:
1287 R200_STATECHANGE( rmesa
, tcl
);
1288 if (ctx
->Light
.Model
.TwoSide
)
1289 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHT_TWOSIDE
;
1291 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~(R200_LIGHT_TWOSIDE
);
1292 if (rmesa
->radeon
.TclFallback
) {
1293 r200ChooseRenderState( ctx
);
1294 r200ChooseVertexState( ctx
);
1298 case GL_LIGHT_MODEL_COLOR_CONTROL
:
1299 r200UpdateSpecular(ctx
);
1307 static void r200ShadeModel( struct gl_context
*ctx
, GLenum mode
)
1309 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1310 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
1312 s
&= ~(R200_DIFFUSE_SHADE_MASK
|
1313 R200_ALPHA_SHADE_MASK
|
1314 R200_SPECULAR_SHADE_MASK
|
1315 R200_FOG_SHADE_MASK
|
1316 R200_DISC_FOG_SHADE_MASK
);
1320 s
|= (R200_DIFFUSE_SHADE_FLAT
|
1321 R200_ALPHA_SHADE_FLAT
|
1322 R200_SPECULAR_SHADE_FLAT
|
1323 R200_FOG_SHADE_FLAT
|
1324 R200_DISC_FOG_SHADE_FLAT
);
1327 s
|= (R200_DIFFUSE_SHADE_GOURAUD
|
1328 R200_ALPHA_SHADE_GOURAUD
|
1329 R200_SPECULAR_SHADE_GOURAUD
|
1330 R200_FOG_SHADE_GOURAUD
|
1331 R200_DISC_FOG_SHADE_GOURAUD
);
1337 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
1338 R200_STATECHANGE( rmesa
, set
);
1339 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
1344 /* =============================================================
1348 static void r200ClipPlane( struct gl_context
*ctx
, GLenum plane
, const GLfloat
*eq
)
1350 GLint p
= (GLint
) plane
- (GLint
) GL_CLIP_PLANE0
;
1351 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1352 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1354 R200_STATECHANGE( rmesa
, ucp
[p
] );
1355 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1356 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1357 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1358 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1361 static void r200UpdateClipPlanes( struct gl_context
*ctx
)
1363 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1364 GLbitfield mask
= ctx
->Transform
.ClipPlanesEnabled
;
1367 const int p
= u_bit_scan(&mask
);
1368 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1370 R200_STATECHANGE( rmesa
, ucp
[p
] );
1371 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1372 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1373 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1374 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1379 /* =============================================================
1384 r200StencilFuncSeparate( struct gl_context
*ctx
, GLenum face
, GLenum func
,
1385 GLint ref
, GLuint mask
)
1387 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1388 GLuint refmask
= ((_mesa_get_stencil_ref(ctx
, 0) << R200_STENCIL_REF_SHIFT
) |
1389 ((ctx
->Stencil
.ValueMask
[0] & 0xff) << R200_STENCIL_MASK_SHIFT
));
1391 R200_STATECHANGE( rmesa
, ctx
);
1392 R200_STATECHANGE( rmesa
, msk
);
1394 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_STENCIL_TEST_MASK
;
1395 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~(R200_STENCIL_REF_MASK
|
1396 R200_STENCIL_VALUE_MASK
);
1398 switch ( ctx
->Stencil
.Function
[0] ) {
1400 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEVER
;
1403 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LESS
;
1406 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_EQUAL
;
1409 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LEQUAL
;
1412 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GREATER
;
1415 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEQUAL
;
1418 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GEQUAL
;
1421 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_ALWAYS
;
1425 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |= refmask
;
1429 r200StencilMaskSeparate( struct gl_context
*ctx
, GLenum face
, GLuint mask
)
1431 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1433 R200_STATECHANGE( rmesa
, msk
);
1434 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~R200_STENCIL_WRITE_MASK
;
1435 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |=
1436 ((ctx
->Stencil
.WriteMask
[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT
);
1440 r200StencilOpSeparate( struct gl_context
*ctx
, GLenum face
, GLenum fail
,
1441 GLenum zfail
, GLenum zpass
)
1443 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1445 R200_STATECHANGE( rmesa
, ctx
);
1446 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~(R200_STENCIL_FAIL_MASK
|
1447 R200_STENCIL_ZFAIL_MASK
|
1448 R200_STENCIL_ZPASS_MASK
);
1450 switch ( ctx
->Stencil
.FailFunc
[0] ) {
1452 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_KEEP
;
1455 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_ZERO
;
1458 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_REPLACE
;
1461 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC
;
1464 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC
;
1466 case GL_INCR_WRAP_EXT
:
1467 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC_WRAP
;
1469 case GL_DECR_WRAP_EXT
:
1470 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC_WRAP
;
1473 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INVERT
;
1477 switch ( ctx
->Stencil
.ZFailFunc
[0] ) {
1479 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_KEEP
;
1482 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_ZERO
;
1485 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_REPLACE
;
1488 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC
;
1491 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC
;
1493 case GL_INCR_WRAP_EXT
:
1494 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC_WRAP
;
1496 case GL_DECR_WRAP_EXT
:
1497 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC_WRAP
;
1500 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INVERT
;
1504 switch ( ctx
->Stencil
.ZPassFunc
[0] ) {
1506 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_KEEP
;
1509 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_ZERO
;
1512 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_REPLACE
;
1515 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC
;
1518 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC
;
1520 case GL_INCR_WRAP_EXT
:
1521 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC_WRAP
;
1523 case GL_DECR_WRAP_EXT
:
1524 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC_WRAP
;
1527 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INVERT
;
1533 /* =============================================================
1534 * Window position and viewport transformation
1538 * Called when window size or position changes or viewport or depth range
1539 * state is changed. We update the hardware viewport state here.
1541 void r200UpdateWindow( struct gl_context
*ctx
)
1543 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1544 __DRIdrawable
*dPriv
= radeon_get_drawable(&rmesa
->radeon
);
1545 GLfloat xoffset
= 0;
1546 GLfloat yoffset
= dPriv
? (GLfloat
) dPriv
->h
: 0;
1547 const GLboolean render_to_fbo
= (ctx
->DrawBuffer
? _mesa_is_user_fbo(ctx
->DrawBuffer
) : 0);
1548 float scale
[3], translate
[3];
1549 GLfloat y_scale
, y_bias
;
1551 if (render_to_fbo
) {
1559 _mesa_get_viewport_xform(ctx
, 0, scale
, translate
);
1560 float_ui32_type sx
= { scale
[0] };
1561 float_ui32_type sy
= { scale
[1] * y_scale
};
1562 float_ui32_type sz
= { scale
[2] };
1563 float_ui32_type tx
= { translate
[0] + xoffset
};
1564 float_ui32_type ty
= { (translate
[1] * y_scale
) + y_bias
};
1565 float_ui32_type tz
= { translate
[2] };
1567 R200_STATECHANGE( rmesa
, vpt
);
1569 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XSCALE
] = sx
.ui32
;
1570 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = tx
.ui32
;
1571 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YSCALE
] = sy
.ui32
;
1572 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = ty
.ui32
;
1573 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZSCALE
] = sz
.ui32
;
1574 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZOFFSET
] = tz
.ui32
;
1577 void r200_vtbl_update_scissor( struct gl_context
*ctx
)
1579 r200ContextPtr r200
= R200_CONTEXT(ctx
);
1580 unsigned x1
, y1
, x2
, y2
;
1581 struct radeon_renderbuffer
*rrb
;
1583 R200_SET_STATE(r200
, set
, SET_RE_CNTL
, R200_SCISSOR_ENABLE
| r200
->hw
.set
.cmd
[SET_RE_CNTL
]);
1585 if (r200
->radeon
.state
.scissor
.enabled
) {
1586 x1
= r200
->radeon
.state
.scissor
.rect
.x1
;
1587 y1
= r200
->radeon
.state
.scissor
.rect
.y1
;
1588 x2
= r200
->radeon
.state
.scissor
.rect
.x2
;
1589 y2
= r200
->radeon
.state
.scissor
.rect
.y2
;
1591 rrb
= radeon_get_colorbuffer(&r200
->radeon
);
1594 x2
= rrb
->base
.Base
.Width
- 1;
1595 y2
= rrb
->base
.Base
.Height
- 1;
1598 R200_SET_STATE(r200
, sci
, SCI_XY_1
, x1
| (y1
<< 16));
1599 R200_SET_STATE(r200
, sci
, SCI_XY_2
, x2
| (y2
<< 16));
1603 static void r200Viewport(struct gl_context
*ctx
)
1605 /* Don't pipeline viewport changes, conflict with window offset
1606 * setting below. Could apply deltas to rescue pipelined viewport
1607 * values, or keep the originals hanging around.
1609 r200UpdateWindow( ctx
);
1611 radeon_viewport(ctx
);
1614 static void r200DepthRange(struct gl_context
*ctx
)
1616 r200UpdateWindow( ctx
);
1619 /* =============================================================
1623 static void r200RenderMode( struct gl_context
*ctx
, GLenum mode
)
1625 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1626 FALLBACK( rmesa
, R200_FALLBACK_RENDER_MODE
, (mode
!= GL_RENDER
) );
1629 static void r200LogicOpCode(struct gl_context
*ctx
, enum gl_logicop_mode opcode
)
1631 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1633 assert((unsigned) opcode
<= 15);
1635 R200_STATECHANGE( rmesa
, msk
);
1636 rmesa
->hw
.msk
.cmd
[MSK_RB3D_ROPCNTL
] = opcode
;
1639 /* =============================================================
1640 * State enable/disable
1643 static void r200Enable( struct gl_context
*ctx
, GLenum cap
, GLboolean state
)
1645 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1648 if ( R200_DEBUG
& RADEON_STATE
)
1649 fprintf( stderr
, "%s( %s = %s )\n", __func__
,
1650 _mesa_enum_to_string( cap
),
1651 state
? "GL_TRUE" : "GL_FALSE" );
1654 /* Fast track this one...
1662 R200_STATECHANGE( rmesa
, ctx
);
1664 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ALPHA_TEST_ENABLE
;
1666 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ALPHA_TEST_ENABLE
;
1671 case GL_COLOR_LOGIC_OP
:
1672 r200_set_blend_state( ctx
);
1675 case GL_CLIP_PLANE0
:
1676 case GL_CLIP_PLANE1
:
1677 case GL_CLIP_PLANE2
:
1678 case GL_CLIP_PLANE3
:
1679 case GL_CLIP_PLANE4
:
1680 case GL_CLIP_PLANE5
:
1681 p
= cap
-GL_CLIP_PLANE0
;
1682 R200_STATECHANGE( rmesa
, tcl
);
1684 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= (R200_UCP_ENABLE_0
<<p
);
1685 r200ClipPlane( ctx
, cap
, NULL
);
1688 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~(R200_UCP_ENABLE_0
<<p
);
1692 case GL_COLOR_MATERIAL
:
1693 r200ColorMaterial( ctx
, 0, 0 );
1694 r200UpdateMaterial( ctx
);
1698 r200CullFace( ctx
, 0 );
1702 R200_STATECHANGE(rmesa
, ctx
);
1704 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_Z_ENABLE
;
1706 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_Z_ENABLE
;
1711 R200_STATECHANGE(rmesa
, ctx
);
1713 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_DITHER_ENABLE
;
1714 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~rmesa
->radeon
.state
.color
.roundEnable
;
1716 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_DITHER_ENABLE
;
1717 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= rmesa
->radeon
.state
.color
.roundEnable
;
1722 R200_STATECHANGE(rmesa
, ctx
);
1724 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_FOG_ENABLE
;
1725 r200Fogfv( ctx
, GL_FOG_MODE
, NULL
);
1727 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_FOG_ENABLE
;
1728 R200_STATECHANGE(rmesa
, tcl
);
1729 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_TCL_FOG_MASK
;
1731 r200UpdateSpecular( ctx
); /* for PK_SPEC */
1732 if (rmesa
->radeon
.TclFallback
)
1733 r200ChooseVertexState( ctx
);
1734 _mesa_allow_light_in_model( ctx
, !state
);
1745 R200_STATECHANGE(rmesa
, tcl
);
1746 p
= cap
- GL_LIGHT0
;
1748 flag
= (R200_LIGHT_1_ENABLE
|
1749 R200_LIGHT_1_ENABLE_AMBIENT
|
1750 R200_LIGHT_1_ENABLE_SPECULAR
);
1752 flag
= (R200_LIGHT_0_ENABLE
|
1753 R200_LIGHT_0_ENABLE_AMBIENT
|
1754 R200_LIGHT_0_ENABLE_SPECULAR
);
1757 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] |= flag
;
1759 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] &= ~flag
;
1763 update_light_colors( ctx
, p
);
1767 r200UpdateSpecular(ctx
);
1768 /* for reflection map fixup - might set recheck_texgen for all units too */
1769 rmesa
->radeon
.NewGLState
|= _NEW_TEXTURE
;
1772 case GL_LINE_SMOOTH
:
1773 R200_STATECHANGE( rmesa
, ctx
);
1775 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_LINE
;
1777 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_LINE
;
1781 case GL_LINE_STIPPLE
:
1782 R200_STATECHANGE( rmesa
, set
);
1784 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_PATTERN_ENABLE
;
1786 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_PATTERN_ENABLE
;
1791 R200_STATECHANGE( rmesa
, tcl
);
1793 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_NORMALIZE_NORMALS
;
1795 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_NORMALIZE_NORMALS
;
1799 /* Pointsize registers on r200 only work for point sprites, and point smooth
1800 * doesn't work for point sprites (and isn't needed for 1.0 sized aa points).
1801 * In any case, setting pointmin == pointsizemax == 1.0 for aa points
1802 * is enough to satisfy conform.
1804 case GL_POINT_SMOOTH
:
1807 /* These don't really do anything, as we don't use the 3vtx
1811 case GL_POLYGON_OFFSET_POINT
:
1812 R200_STATECHANGE( rmesa
, set
);
1814 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_POINT
;
1816 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_POINT
;
1820 case GL_POLYGON_OFFSET_LINE
:
1821 R200_STATECHANGE( rmesa
, set
);
1823 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_LINE
;
1825 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_LINE
;
1830 case GL_POINT_SPRITE_ARB
:
1831 R200_STATECHANGE( rmesa
, spr
);
1833 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |= R200_PS_GEN_TEX_MASK
&
1834 (ctx
->Point
.CoordReplace
<< R200_PS_GEN_TEX_0_SHIFT
);
1836 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] &= ~R200_PS_GEN_TEX_MASK
;
1840 case GL_POLYGON_OFFSET_FILL
:
1841 R200_STATECHANGE( rmesa
, set
);
1843 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_TRI
;
1845 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_TRI
;
1849 case GL_POLYGON_SMOOTH
:
1850 R200_STATECHANGE( rmesa
, ctx
);
1852 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_POLY
;
1854 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_POLY
;
1858 case GL_POLYGON_STIPPLE
:
1859 R200_STATECHANGE(rmesa
, set
);
1861 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_STIPPLE_ENABLE
;
1863 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_STIPPLE_ENABLE
;
1867 case GL_RESCALE_NORMAL_EXT
: {
1868 GLboolean tmp
= ctx
->_NeedEyeCoords
? state
: !state
;
1869 R200_STATECHANGE( rmesa
, tcl
);
1871 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
1873 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
1878 case GL_SCISSOR_TEST
:
1879 radeon_firevertices(&rmesa
->radeon
);
1880 rmesa
->radeon
.state
.scissor
.enabled
= state
;
1881 radeonUpdateScissor( ctx
);
1884 case GL_STENCIL_TEST
:
1886 GLboolean hw_stencil
= GL_FALSE
;
1887 if (ctx
->DrawBuffer
) {
1888 struct radeon_renderbuffer
*rrbStencil
1889 = radeon_get_renderbuffer(ctx
->DrawBuffer
, BUFFER_STENCIL
);
1890 hw_stencil
= (rrbStencil
&& rrbStencil
->bo
);
1894 R200_STATECHANGE( rmesa
, ctx
);
1896 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_STENCIL_ENABLE
;
1898 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_STENCIL_ENABLE
;
1901 FALLBACK( rmesa
, R200_FALLBACK_STENCIL
, state
);
1906 case GL_TEXTURE_GEN_Q
:
1907 case GL_TEXTURE_GEN_R
:
1908 case GL_TEXTURE_GEN_S
:
1909 case GL_TEXTURE_GEN_T
:
1910 /* Picked up in r200UpdateTextureState.
1912 rmesa
->recheck_texgen
[ctx
->Texture
.CurrentUnit
] = GL_TRUE
;
1915 case GL_COLOR_SUM_EXT
:
1916 r200UpdateSpecular ( ctx
);
1919 case GL_VERTEX_PROGRAM_ARB
:
1922 rmesa
->curr_vp_hw
= NULL
;
1923 R200_STATECHANGE( rmesa
, vap
);
1924 rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
] &= ~R200_VAP_PROG_VTX_SHADER_ENABLE
;
1925 /* mark all tcl atoms (tcl vector state got overwritten) dirty
1926 not sure about tcl scalar state - we need at least grd
1927 with vert progs too.
1928 ucp looks like it doesn't get overwritten (may even work
1929 with vp for pos-invariant progs if we're lucky) */
1930 R200_STATECHANGE( rmesa
, mtl
[0] );
1931 R200_STATECHANGE( rmesa
, mtl
[1] );
1932 R200_STATECHANGE( rmesa
, fog
);
1933 R200_STATECHANGE( rmesa
, glt
);
1934 R200_STATECHANGE( rmesa
, eye
);
1935 for (i
= R200_MTX_MV
; i
<= R200_MTX_TEX5
; i
++) {
1936 R200_STATECHANGE( rmesa
, mat
[i
] );
1938 for (i
= 0 ; i
< 8; i
++) {
1939 R200_STATECHANGE( rmesa
, lit
[i
] );
1941 R200_STATECHANGE( rmesa
, tcl
);
1942 for (i
= 0; i
<= ctx
->Const
.MaxClipPlanes
; i
++) {
1943 if (ctx
->Transform
.ClipPlanesEnabled
& (1 << i
)) {
1944 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= (R200_UCP_ENABLE_0
<< i
);
1947 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0 << i);
1950 /* ugly. Need to call everything which might change compsel. */
1951 r200UpdateSpecular( ctx
);
1953 /* shouldn't be necessary, as it's picked up anyway in r200ValidateState (_NEW_PROGRAM),
1954 but without it doom3 locks up at always the same places. Why? */
1955 /* FIXME: This can (and should) be replaced by a call to the TCL_STATE_FLUSH reg before
1956 accessing VAP_SE_VAP_CNTL. Requires drm changes (done). Remove after some time... */
1957 r200UpdateTextureState( ctx
);
1958 /* if we call r200UpdateTextureState we need the code below because we are calling it with
1959 non-current derived enabled values which may revert the state atoms for frag progs even when
1960 they already got disabled... ugh
1961 Should really figure out why we need to call r200UpdateTextureState in the first place */
1963 for (unit
= 0; unit
< R200_MAX_TEXTURE_UNITS
; unit
++) {
1964 R200_STATECHANGE( rmesa
, pix
[unit
] );
1965 R200_STATECHANGE( rmesa
, tex
[unit
] );
1966 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] &=
1967 ~(R200_TXFORMAT_ST_ROUTE_MASK
| R200_TXFORMAT_LOOKUP_DISABLE
);
1968 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] |= unit
<< R200_TXFORMAT_ST_ROUTE_SHIFT
;
1969 /* need to guard this with drmSupportsFragmentShader? Should never get here if
1970 we don't announce ATI_fs, right? */
1971 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXMULTI_CTL
] = 0;
1973 R200_STATECHANGE( rmesa
, cst
);
1974 R200_STATECHANGE( rmesa
, tf
);
1975 rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] = 0;
1979 /* picked up later */
1981 /* call functions which change hw state based on ARB_vp enabled or not. */
1982 r200PointParameter( ctx
, GL_POINT_DISTANCE_ATTENUATION
, NULL
);
1983 r200Fogfv( ctx
, GL_FOG_COORD_SRC
, NULL
);
1986 case GL_VERTEX_PROGRAM_POINT_SIZE_ARB
:
1987 r200PointParameter( ctx
, GL_POINT_DISTANCE_ATTENUATION
, NULL
);
1990 case GL_FRAGMENT_SHADER_ATI
:
1992 /* restore normal tex env colors and make sure tex env combine will get updated
1993 mark env atoms dirty (as their data was overwritten by afs even
1994 if they didn't change) and restore tex coord routing */
1996 for (unit
= 0; unit
< R200_MAX_TEXTURE_UNITS
; unit
++) {
1997 R200_STATECHANGE( rmesa
, pix
[unit
] );
1998 R200_STATECHANGE( rmesa
, tex
[unit
] );
1999 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] &=
2000 ~(R200_TXFORMAT_ST_ROUTE_MASK
| R200_TXFORMAT_LOOKUP_DISABLE
);
2001 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] |= unit
<< R200_TXFORMAT_ST_ROUTE_SHIFT
;
2002 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXMULTI_CTL
] = 0;
2004 R200_STATECHANGE( rmesa
, cst
);
2005 R200_STATECHANGE( rmesa
, tf
);
2006 rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] = 0;
2009 /* need to mark this dirty as pix/tf atoms have overwritten the data
2010 even if the data in the atoms didn't change */
2011 R200_STATECHANGE( rmesa
, atf
);
2012 R200_STATECHANGE( rmesa
, afs
[1] );
2013 /* everything else picked up in r200UpdateTextureState hopefully */
2022 void r200LightingSpaceChange( struct gl_context
*ctx
)
2024 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2027 if (R200_DEBUG
& RADEON_STATE
)
2028 fprintf(stderr
, "%s %d BEFORE %x\n", __func__
, ctx
->_NeedEyeCoords
,
2029 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
2031 if (ctx
->_NeedEyeCoords
)
2032 tmp
= ctx
->Transform
.RescaleNormals
;
2034 tmp
= !ctx
->Transform
.RescaleNormals
;
2036 R200_STATECHANGE( rmesa
, tcl
);
2038 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
2040 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
2043 if (R200_DEBUG
& RADEON_STATE
)
2044 fprintf(stderr
, "%s %d AFTER %x\n", __func__
, ctx
->_NeedEyeCoords
,
2045 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
2048 /* =============================================================
2049 * Deferred state management - matrices, textures, other?
2055 static void upload_matrix( r200ContextPtr rmesa
, GLfloat
*src
, int idx
)
2057 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
2061 for (i
= 0 ; i
< 4 ; i
++) {
2065 *dest
++ = src
[i
+12];
2068 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
2071 static void upload_matrix_t( r200ContextPtr rmesa
, const GLfloat
*src
, int idx
)
2073 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
2074 memcpy(dest
, src
, 16*sizeof(float));
2075 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
2079 static void update_texturematrix( struct gl_context
*ctx
)
2081 r200ContextPtr rmesa
= R200_CONTEXT( ctx
);
2082 GLuint tpc
= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
];
2083 GLuint compsel
= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
];
2086 if (R200_DEBUG
& RADEON_STATE
)
2087 fprintf(stderr
, "%s before COMPSEL: %x\n", __func__
,
2088 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]);
2090 rmesa
->TexMatEnabled
= 0;
2091 rmesa
->TexMatCompSel
= 0;
2093 for (unit
= 0 ; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
2094 if (!ctx
->Texture
.Unit
[unit
]._Current
)
2097 if (ctx
->TextureMatrixStack
[unit
].Top
->type
!= MATRIX_IDENTITY
) {
2098 rmesa
->TexMatEnabled
|= (R200_TEXGEN_TEXMAT_0_ENABLE
|
2099 R200_TEXMAT_0_ENABLE
) << unit
;
2101 rmesa
->TexMatCompSel
|= R200_OUTPUT_TEX_0
<< unit
;
2103 if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2104 /* Need to preconcatenate any active texgen
2105 * obj/eyeplane matrices:
2107 _math_matrix_mul_matrix( &rmesa
->tmpmat
,
2108 ctx
->TextureMatrixStack
[unit
].Top
,
2109 &rmesa
->TexGenMatrix
[unit
] );
2110 upload_matrix( rmesa
, rmesa
->tmpmat
.m
, R200_MTX_TEX0
+unit
);
2113 upload_matrix( rmesa
, ctx
->TextureMatrixStack
[unit
].Top
->m
,
2114 R200_MTX_TEX0
+unit
);
2117 else if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2118 upload_matrix( rmesa
, rmesa
->TexGenMatrix
[unit
].m
,
2119 R200_MTX_TEX0
+unit
);
2123 tpc
= (rmesa
->TexMatEnabled
| rmesa
->TexGenEnabled
);
2124 if (tpc
!= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
]) {
2125 R200_STATECHANGE(rmesa
, tcg
);
2126 rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
] = tpc
;
2129 compsel
&= ~R200_OUTPUT_TEX_MASK
;
2130 compsel
|= rmesa
->TexMatCompSel
| rmesa
->TexGenCompSel
;
2131 if (compsel
!= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]) {
2132 R200_STATECHANGE(rmesa
, vtx
);
2133 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] = compsel
;
2137 GLboolean
r200ValidateBuffers(struct gl_context
*ctx
)
2139 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2140 struct radeon_renderbuffer
*rrb
;
2141 struct radeon_dma_bo
*dma_bo
;
2144 if (RADEON_DEBUG
& RADEON_IOCTL
)
2145 fprintf(stderr
, "%s\n", __func__
);
2146 radeon_cs_space_reset_bos(rmesa
->radeon
.cmdbuf
.cs
);
2148 rrb
= radeon_get_colorbuffer(&rmesa
->radeon
);
2150 if (rrb
&& rrb
->bo
) {
2151 radeon_cs_space_add_persistent_bo(rmesa
->radeon
.cmdbuf
.cs
, rrb
->bo
,
2152 0, RADEON_GEM_DOMAIN_VRAM
);
2156 rrb
= radeon_get_depthbuffer(&rmesa
->radeon
);
2158 if (rrb
&& rrb
->bo
) {
2159 radeon_cs_space_add_persistent_bo(rmesa
->radeon
.cmdbuf
.cs
, rrb
->bo
,
2160 0, RADEON_GEM_DOMAIN_VRAM
);
2163 for (i
= 0; i
< ctx
->Const
.Program
[MESA_SHADER_FRAGMENT
].MaxTextureImageUnits
; ++i
) {
2166 if (!ctx
->Texture
.Unit
[i
]._Current
)
2169 t
= radeon_tex_obj(ctx
->Texture
.Unit
[i
]._Current
);
2170 if (t
->image_override
&& t
->bo
)
2171 radeon_cs_space_add_persistent_bo(rmesa
->radeon
.cmdbuf
.cs
, t
->bo
,
2172 RADEON_GEM_DOMAIN_GTT
| RADEON_GEM_DOMAIN_VRAM
, 0);
2174 radeon_cs_space_add_persistent_bo(rmesa
->radeon
.cmdbuf
.cs
, t
->mt
->bo
,
2175 RADEON_GEM_DOMAIN_GTT
| RADEON_GEM_DOMAIN_VRAM
, 0);
2178 dma_bo
= first_elem(&rmesa
->radeon
.dma
.reserved
);
2180 ret
= radeon_cs_space_check_with_bo(rmesa
->radeon
.cmdbuf
.cs
, dma_bo
->bo
, RADEON_GEM_DOMAIN_GTT
, 0);
2187 GLboolean
r200ValidateState( struct gl_context
*ctx
)
2189 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2190 GLuint new_state
= rmesa
->radeon
.NewGLState
;
2192 if (new_state
& _NEW_BUFFERS
) {
2193 _mesa_update_framebuffer(ctx
, ctx
->ReadBuffer
, ctx
->DrawBuffer
);
2194 /* this updates the DrawBuffer's Width/Height if it's a FBO */
2195 _mesa_update_draw_buffer_bounds(ctx
, ctx
->DrawBuffer
);
2197 R200_STATECHANGE(rmesa
, ctx
);
2200 if (new_state
& (_NEW_TEXTURE
| _NEW_PROGRAM
| _NEW_PROGRAM_CONSTANTS
)) {
2201 r200UpdateTextureState( ctx
);
2202 new_state
|= rmesa
->radeon
.NewGLState
; /* may add TEXTURE_MATRIX */
2203 r200UpdateLocalViewer( ctx
);
2206 /* we need to do a space check here */
2207 if (!r200ValidateBuffers(ctx
))
2210 /* FIXME: don't really need most of these when vertex progs are enabled */
2212 /* Need an event driven matrix update?
2214 if (new_state
& (_NEW_MODELVIEW
|_NEW_PROJECTION
))
2215 upload_matrix( rmesa
, ctx
->_ModelProjectMatrix
.m
, R200_MTX_MVP
);
2217 /* Need these for lighting (shouldn't upload otherwise)
2219 if (new_state
& (_NEW_MODELVIEW
)) {
2220 upload_matrix( rmesa
, ctx
->ModelviewMatrixStack
.Top
->m
, R200_MTX_MV
);
2221 upload_matrix_t( rmesa
, ctx
->ModelviewMatrixStack
.Top
->inv
, R200_MTX_IMV
);
2224 /* Does this need to be triggered on eg. modelview for
2225 * texgen-derived objplane/eyeplane matrices?
2227 if (new_state
& (_NEW_TEXTURE
|_NEW_TEXTURE_MATRIX
)) {
2228 update_texturematrix( ctx
);
2231 if (new_state
& (_NEW_LIGHT
|_NEW_MODELVIEW
|_MESA_NEW_NEED_EYE_COORDS
)) {
2232 update_light( ctx
);
2235 /* emit all active clip planes if projection matrix changes.
2237 if (new_state
& (_NEW_PROJECTION
)) {
2238 if (ctx
->Transform
.ClipPlanesEnabled
)
2239 r200UpdateClipPlanes( ctx
);
2242 if (new_state
& (_NEW_PROGRAM
|
2243 _NEW_PROGRAM_CONSTANTS
|
2244 /* need to test for pretty much anything due to possible parameter bindings */
2245 _NEW_MODELVIEW
|_NEW_PROJECTION
|_NEW_TRANSFORM
|
2246 _NEW_LIGHT
|_NEW_TEXTURE
|_NEW_TEXTURE_MATRIX
|
2247 _NEW_FOG
|_NEW_POINT
|_NEW_TRACK_MATRIX
)) {
2248 if (_mesa_arb_vertex_program_enabled(ctx
)) {
2249 r200SetupVertexProg( ctx
);
2251 else TCL_FALLBACK(ctx
, R200_TCL_FALLBACK_VERTEX_PROGRAM
, 0);
2254 rmesa
->radeon
.NewGLState
= 0;
2259 static void r200InvalidateState(struct gl_context
*ctx
)
2261 GLuint new_state
= ctx
->NewState
;
2263 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2265 if (new_state
& (_NEW_SCISSOR
| _NEW_BUFFERS
| _NEW_VIEWPORT
))
2266 _mesa_update_draw_buffer_bounds(ctx
, ctx
->DrawBuffer
);
2268 _swrast_InvalidateState( ctx
, new_state
);
2269 _swsetup_InvalidateState( ctx
, new_state
);
2270 _tnl_InvalidateState( ctx
, new_state
);
2271 R200_CONTEXT(ctx
)->radeon
.NewGLState
|= new_state
;
2273 if (new_state
& _NEW_PROGRAM
)
2274 rmesa
->curr_vp_hw
= NULL
;
2277 /* A hack. The r200 can actually cope just fine with materials
2278 * between begin/ends, so fix this.
2279 * Should map to inputs just like the generic vertex arrays for vertex progs.
2280 * In theory there could still be too many and we'd still need a fallback.
2282 static GLboolean
check_material( struct gl_context
*ctx
)
2284 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
2287 for (i
= _TNL_ATTRIB_MAT_FRONT_AMBIENT
;
2288 i
< _TNL_ATTRIB_MAT_BACK_INDEXES
;
2290 if (tnl
->vb
.AttribPtr
[i
] &&
2291 tnl
->vb
.AttribPtr
[i
]->stride
)
2297 static void r200WrapRunPipeline( struct gl_context
*ctx
)
2299 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2300 GLboolean has_material
;
2303 fprintf(stderr
, "%s, newstate: %x\n", __func__
, rmesa
->radeon
.NewGLState
);
2307 if (rmesa
->radeon
.NewGLState
)
2308 if (!r200ValidateState( ctx
))
2309 FALLBACK(rmesa
, RADEON_FALLBACK_TEXTURE
, GL_TRUE
);
2311 has_material
= !_mesa_arb_vertex_program_enabled(ctx
) &&
2312 ctx
->Light
.Enabled
&& check_material( ctx
);
2315 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_TRUE
);
2318 /* Run the pipeline.
2320 _tnl_run_pipeline( ctx
);
2323 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_FALSE
);
2328 static void r200PolygonStipple( struct gl_context
*ctx
, const GLubyte
*mask
)
2330 r200ContextPtr r200
= R200_CONTEXT(ctx
);
2333 radeon_firevertices(&r200
->radeon
);
2335 radeon_print(RADEON_STATE
, RADEON_TRACE
,
2336 "%s(%p) first 32 bits are %x.\n",
2341 R200_STATECHANGE(r200
, stp
);
2343 /* Must flip pattern upside down.
2345 for ( i
= 31 ; i
>= 0; i
--) {
2346 r200
->hw
.stp
.cmd
[3 + i
] = ((GLuint
*) mask
)[i
];
2349 /* Initialize the driver's state functions.
2351 void r200InitStateFuncs( radeonContextPtr radeon
, struct dd_function_table
*functions
)
2353 functions
->UpdateState
= r200InvalidateState
;
2354 functions
->LightingSpaceChange
= r200LightingSpaceChange
;
2356 functions
->DrawBuffer
= radeonDrawBuffer
;
2357 functions
->ReadBuffer
= radeonReadBuffer
;
2359 functions
->CopyPixels
= _mesa_meta_CopyPixels
;
2360 functions
->DrawPixels
= _mesa_meta_DrawPixels
;
2361 functions
->ReadPixels
= radeonReadPixels
;
2363 functions
->AlphaFunc
= r200AlphaFunc
;
2364 functions
->BlendColor
= r200BlendColor
;
2365 functions
->BlendEquationSeparate
= r200BlendEquationSeparate
;
2366 functions
->BlendFuncSeparate
= r200BlendFuncSeparate
;
2367 functions
->ClipPlane
= r200ClipPlane
;
2368 functions
->ColorMask
= r200ColorMask
;
2369 functions
->CullFace
= r200CullFace
;
2370 functions
->DepthFunc
= r200DepthFunc
;
2371 functions
->DepthMask
= r200DepthMask
;
2372 functions
->DepthRange
= r200DepthRange
;
2373 functions
->Enable
= r200Enable
;
2374 functions
->Fogfv
= r200Fogfv
;
2375 functions
->FrontFace
= r200FrontFace
;
2376 functions
->LightModelfv
= r200LightModelfv
;
2377 functions
->Lightfv
= r200Lightfv
;
2378 functions
->LineStipple
= r200LineStipple
;
2379 functions
->LineWidth
= r200LineWidth
;
2380 functions
->LogicOpcode
= r200LogicOpCode
;
2381 functions
->PolygonMode
= r200PolygonMode
;
2382 functions
->PolygonOffset
= r200PolygonOffset
;
2383 functions
->PolygonStipple
= r200PolygonStipple
;
2384 functions
->PointParameterfv
= r200PointParameter
;
2385 functions
->PointSize
= r200PointSize
;
2386 functions
->RenderMode
= r200RenderMode
;
2387 functions
->Scissor
= radeonScissor
;
2388 functions
->ShadeModel
= r200ShadeModel
;
2389 functions
->StencilFuncSeparate
= r200StencilFuncSeparate
;
2390 functions
->StencilMaskSeparate
= r200StencilMaskSeparate
;
2391 functions
->StencilOpSeparate
= r200StencilOpSeparate
;
2392 functions
->Viewport
= r200Viewport
;
2396 void r200InitTnlFuncs( struct gl_context
*ctx
)
2398 TNL_CONTEXT(ctx
)->Driver
.NotifyMaterialChange
= r200UpdateMaterial
;
2399 TNL_CONTEXT(ctx
)->Driver
.RunPipeline
= r200WrapRunPipeline
;