2 /**************************************************************************
4 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
6 The Weather Channel (TM) funded Tungsten Graphics to develop the
7 initial release of the Radeon 8500 driver under the XFree86 license.
8 This notice must be preserved.
10 Permission is hereby granted, free of charge, to any person obtaining
11 a copy of this software and associated documentation files (the
12 "Software"), to deal in the Software without restriction, including
13 without limitation the rights to use, copy, modify, merge, publish,
14 distribute, sublicense, and/or sell copies of the Software, and to
15 permit persons to whom the Software is furnished to do so, subject to
16 the following conditions:
18 The above copyright notice and this permission notice (including the
19 next paragraph) shall be included in all copies or substantial
20 portions of the Software.
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
25 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
26 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 **************************************************************************/
34 * Keith Whitwell <keith@tungstengraphics.com>
39 #include "api_arrayelt.h"
43 #include "framebuffer.h"
45 #include "swrast/swrast.h"
48 #include "tnl/t_pipeline.h"
49 #include "swrast_setup/swrast_setup.h"
51 #include "r200_context.h"
52 #include "r200_ioctl.h"
53 #include "r200_state.h"
56 #include "r200_swtcl.h"
57 #include "r200_vertprog.h"
59 #include "drirenderbuffer.h"
62 /* =============================================================
66 static void r200AlphaFunc( GLcontext
*ctx
, GLenum func
, GLfloat ref
)
68 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
69 int pp_misc
= rmesa
->hw
.ctx
.cmd
[CTX_PP_MISC
];
72 CLAMPED_FLOAT_TO_UBYTE(refByte
, ref
);
74 R200_STATECHANGE( rmesa
, ctx
);
76 pp_misc
&= ~(R200_ALPHA_TEST_OP_MASK
| R200_REF_ALPHA_MASK
);
77 pp_misc
|= (refByte
& R200_REF_ALPHA_MASK
);
81 pp_misc
|= R200_ALPHA_TEST_FAIL
;
84 pp_misc
|= R200_ALPHA_TEST_LESS
;
87 pp_misc
|= R200_ALPHA_TEST_EQUAL
;
90 pp_misc
|= R200_ALPHA_TEST_LEQUAL
;
93 pp_misc
|= R200_ALPHA_TEST_GREATER
;
96 pp_misc
|= R200_ALPHA_TEST_NEQUAL
;
99 pp_misc
|= R200_ALPHA_TEST_GEQUAL
;
102 pp_misc
|= R200_ALPHA_TEST_PASS
;
106 rmesa
->hw
.ctx
.cmd
[CTX_PP_MISC
] = pp_misc
;
109 static void r200BlendColor( GLcontext
*ctx
, const GLfloat cf
[4] )
112 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
113 R200_STATECHANGE( rmesa
, ctx
);
114 CLAMPED_FLOAT_TO_UBYTE(color
[0], cf
[0]);
115 CLAMPED_FLOAT_TO_UBYTE(color
[1], cf
[1]);
116 CLAMPED_FLOAT_TO_UBYTE(color
[2], cf
[2]);
117 CLAMPED_FLOAT_TO_UBYTE(color
[3], cf
[3]);
118 if (rmesa
->r200Screen
->drmSupportsBlendColor
)
119 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCOLOR
] = r200PackColor( 4, color
[0], color
[1], color
[2], color
[3] );
123 * Calculate the hardware blend factor setting. This same function is used
124 * for source and destination of both alpha and RGB.
127 * The hardware register value for the specified blend factor. This value
128 * will need to be shifted into the correct position for either source or
129 * destination factor.
132 * Since the two cases where source and destination are handled differently
133 * are essentially error cases, they should never happen. Determine if these
134 * cases can be removed.
136 static int blend_factor( GLenum factor
, GLboolean is_src
)
142 func
= R200_BLEND_GL_ZERO
;
145 func
= R200_BLEND_GL_ONE
;
148 func
= R200_BLEND_GL_DST_COLOR
;
150 case GL_ONE_MINUS_DST_COLOR
:
151 func
= R200_BLEND_GL_ONE_MINUS_DST_COLOR
;
154 func
= R200_BLEND_GL_SRC_COLOR
;
156 case GL_ONE_MINUS_SRC_COLOR
:
157 func
= R200_BLEND_GL_ONE_MINUS_SRC_COLOR
;
160 func
= R200_BLEND_GL_SRC_ALPHA
;
162 case GL_ONE_MINUS_SRC_ALPHA
:
163 func
= R200_BLEND_GL_ONE_MINUS_SRC_ALPHA
;
166 func
= R200_BLEND_GL_DST_ALPHA
;
168 case GL_ONE_MINUS_DST_ALPHA
:
169 func
= R200_BLEND_GL_ONE_MINUS_DST_ALPHA
;
171 case GL_SRC_ALPHA_SATURATE
:
172 func
= (is_src
) ? R200_BLEND_GL_SRC_ALPHA_SATURATE
: R200_BLEND_GL_ZERO
;
174 case GL_CONSTANT_COLOR
:
175 func
= R200_BLEND_GL_CONST_COLOR
;
177 case GL_ONE_MINUS_CONSTANT_COLOR
:
178 func
= R200_BLEND_GL_ONE_MINUS_CONST_COLOR
;
180 case GL_CONSTANT_ALPHA
:
181 func
= R200_BLEND_GL_CONST_ALPHA
;
183 case GL_ONE_MINUS_CONSTANT_ALPHA
:
184 func
= R200_BLEND_GL_ONE_MINUS_CONST_ALPHA
;
187 func
= (is_src
) ? R200_BLEND_GL_ONE
: R200_BLEND_GL_ZERO
;
193 * Sets both the blend equation and the blend function.
194 * This is done in a single
195 * function because some blend equations (i.e., \c GL_MIN and \c GL_MAX)
196 * change the interpretation of the blend function.
197 * Also, make sure that blend function and blend equation are set to their default
198 * value if color blending is not enabled, since at least blend equations GL_MIN
199 * and GL_FUNC_REVERSE_SUBTRACT will cause wrong results otherwise for
202 static void r200_set_blend_state( GLcontext
* ctx
)
204 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
205 GLuint cntl
= rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &
206 ~(R200_ROP_ENABLE
| R200_ALPHA_BLEND_ENABLE
| R200_SEPARATE_ALPHA_ENABLE
);
208 int func
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
209 (R200_BLEND_GL_ZERO
<< R200_DST_BLEND_SHIFT
);
210 int eqn
= R200_COMB_FCN_ADD_CLAMP
;
211 int funcA
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
212 (R200_BLEND_GL_ZERO
<< R200_DST_BLEND_SHIFT
);
213 int eqnA
= R200_COMB_FCN_ADD_CLAMP
;
215 R200_STATECHANGE( rmesa
, ctx
);
217 if (rmesa
->r200Screen
->drmSupportsBlendColor
) {
218 if (ctx
->Color
.ColorLogicOpEnabled
) {
219 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
| R200_ROP_ENABLE
;
220 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ABLENDCNTL
] = eqn
| func
;
221 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CBLENDCNTL
] = eqn
| func
;
223 } else if (ctx
->Color
.BlendEnabled
) {
224 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
| R200_ALPHA_BLEND_ENABLE
| R200_SEPARATE_ALPHA_ENABLE
;
227 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
;
228 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ABLENDCNTL
] = eqn
| func
;
229 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CBLENDCNTL
] = eqn
| func
;
234 if (ctx
->Color
.ColorLogicOpEnabled
) {
235 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
| R200_ROP_ENABLE
;
236 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] = eqn
| func
;
238 } else if (ctx
->Color
.BlendEnabled
) {
239 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
| R200_ALPHA_BLEND_ENABLE
;
242 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
;
243 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] = eqn
| func
;
248 func
= (blend_factor( ctx
->Color
.BlendSrcRGB
, GL_TRUE
) << R200_SRC_BLEND_SHIFT
) |
249 (blend_factor( ctx
->Color
.BlendDstRGB
, GL_FALSE
) << R200_DST_BLEND_SHIFT
);
251 switch(ctx
->Color
.BlendEquationRGB
) {
253 eqn
= R200_COMB_FCN_ADD_CLAMP
;
256 case GL_FUNC_SUBTRACT
:
257 eqn
= R200_COMB_FCN_SUB_CLAMP
;
260 case GL_FUNC_REVERSE_SUBTRACT
:
261 eqn
= R200_COMB_FCN_RSUB_CLAMP
;
265 eqn
= R200_COMB_FCN_MIN
;
266 func
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
267 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
271 eqn
= R200_COMB_FCN_MAX
;
272 func
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
273 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
277 fprintf( stderr
, "[%s:%u] Invalid RGB blend equation (0x%04x).\n",
278 __FUNCTION__
, __LINE__
, ctx
->Color
.BlendEquationRGB
);
282 if (!rmesa
->r200Screen
->drmSupportsBlendColor
) {
283 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] = eqn
| func
;
287 funcA
= (blend_factor( ctx
->Color
.BlendSrcA
, GL_TRUE
) << R200_SRC_BLEND_SHIFT
) |
288 (blend_factor( ctx
->Color
.BlendDstA
, GL_FALSE
) << R200_DST_BLEND_SHIFT
);
290 switch(ctx
->Color
.BlendEquationA
) {
292 eqnA
= R200_COMB_FCN_ADD_CLAMP
;
295 case GL_FUNC_SUBTRACT
:
296 eqnA
= R200_COMB_FCN_SUB_CLAMP
;
299 case GL_FUNC_REVERSE_SUBTRACT
:
300 eqnA
= R200_COMB_FCN_RSUB_CLAMP
;
304 eqnA
= R200_COMB_FCN_MIN
;
305 funcA
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
306 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
310 eqnA
= R200_COMB_FCN_MAX
;
311 funcA
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
312 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
316 fprintf( stderr
, "[%s:%u] Invalid A blend equation (0x%04x).\n",
317 __FUNCTION__
, __LINE__
, ctx
->Color
.BlendEquationA
);
321 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ABLENDCNTL
] = eqnA
| funcA
;
322 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CBLENDCNTL
] = eqn
| func
;
326 static void r200BlendEquationSeparate( GLcontext
*ctx
,
327 GLenum modeRGB
, GLenum modeA
)
329 r200_set_blend_state( ctx
);
332 static void r200BlendFuncSeparate( GLcontext
*ctx
,
333 GLenum sfactorRGB
, GLenum dfactorRGB
,
334 GLenum sfactorA
, GLenum dfactorA
)
336 r200_set_blend_state( ctx
);
340 /* =============================================================
344 static void r200DepthFunc( GLcontext
*ctx
, GLenum func
)
346 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
348 R200_STATECHANGE( rmesa
, ctx
);
349 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_Z_TEST_MASK
;
351 switch ( ctx
->Depth
.Func
) {
353 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_NEVER
;
356 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_LESS
;
359 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_EQUAL
;
362 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_LEQUAL
;
365 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_GREATER
;
368 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_NEQUAL
;
371 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_GEQUAL
;
374 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_ALWAYS
;
379 static void r200ClearDepth( GLcontext
*ctx
, GLclampd d
)
381 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
382 GLuint format
= (rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &
383 R200_DEPTH_FORMAT_MASK
);
386 case R200_DEPTH_FORMAT_16BIT_INT_Z
:
387 rmesa
->state
.depth
.clear
= d
* 0x0000ffff;
389 case R200_DEPTH_FORMAT_24BIT_INT_Z
:
390 rmesa
->state
.depth
.clear
= d
* 0x00ffffff;
395 static void r200DepthMask( GLcontext
*ctx
, GLboolean flag
)
397 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
398 R200_STATECHANGE( rmesa
, ctx
);
400 if ( ctx
->Depth
.Mask
) {
401 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_WRITE_ENABLE
;
403 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_Z_WRITE_ENABLE
;
408 /* =============================================================
413 static void r200Fogfv( GLcontext
*ctx
, GLenum pname
, const GLfloat
*param
)
415 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
416 union { int i
; float f
; } c
, d
;
420 c
.i
= rmesa
->hw
.fog
.cmd
[FOG_C
];
421 d
.i
= rmesa
->hw
.fog
.cmd
[FOG_D
];
425 if (!ctx
->Fog
.Enabled
)
427 R200_STATECHANGE(rmesa
, tcl
);
428 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_TCL_FOG_MASK
;
429 switch (ctx
->Fog
.Mode
) {
431 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_LINEAR
;
432 if (ctx
->Fog
.Start
== ctx
->Fog
.End
) {
437 c
.f
= ctx
->Fog
.End
/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
438 d
.f
= -1.0/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
442 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_EXP
;
444 d
.f
= -ctx
->Fog
.Density
;
447 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_EXP2
;
449 d
.f
= -(ctx
->Fog
.Density
* ctx
->Fog
.Density
);
456 switch (ctx
->Fog
.Mode
) {
459 d
.f
= -ctx
->Fog
.Density
;
463 d
.f
= -(ctx
->Fog
.Density
* ctx
->Fog
.Density
);
471 if (ctx
->Fog
.Mode
== GL_LINEAR
) {
472 if (ctx
->Fog
.Start
== ctx
->Fog
.End
) {
476 c
.f
= ctx
->Fog
.End
/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
477 d
.f
= -1.0/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
482 R200_STATECHANGE( rmesa
, ctx
);
483 UNCLAMPED_FLOAT_TO_RGB_CHAN( col
, ctx
->Fog
.Color
);
484 i
= r200PackColor( 4, col
[0], col
[1], col
[2], 0 );
485 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] &= ~R200_FOG_COLOR_MASK
;
486 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] |= i
;
488 case GL_FOG_COORD_SRC
: {
489 GLuint out_0
= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
];
490 GLuint fog
= rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
];
492 fog
&= ~R200_FOG_USE_MASK
;
493 if ( ctx
->Fog
.FogCoordinateSource
== GL_FOG_COORD
|| ctx
->VertexProgram
.Enabled
) {
494 fog
|= R200_FOG_USE_VTX_FOG
;
495 out_0
|= R200_VTX_DISCRETE_FOG
;
498 fog
|= R200_FOG_USE_SPEC_ALPHA
;
499 out_0
&= ~R200_VTX_DISCRETE_FOG
;
502 if ( fog
!= rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] ) {
503 R200_STATECHANGE( rmesa
, ctx
);
504 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] = fog
;
507 if (out_0
!= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
]) {
508 R200_STATECHANGE( rmesa
, vtx
);
509 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] = out_0
;
518 if (c
.i
!= rmesa
->hw
.fog
.cmd
[FOG_C
] || d
.i
!= rmesa
->hw
.fog
.cmd
[FOG_D
]) {
519 R200_STATECHANGE( rmesa
, fog
);
520 rmesa
->hw
.fog
.cmd
[FOG_C
] = c
.i
;
521 rmesa
->hw
.fog
.cmd
[FOG_D
] = d
.i
;
526 /* =============================================================
531 static GLboolean
intersect_rect( drm_clip_rect_t
*out
,
536 if ( b
->x1
> out
->x1
) out
->x1
= b
->x1
;
537 if ( b
->y1
> out
->y1
) out
->y1
= b
->y1
;
538 if ( b
->x2
< out
->x2
) out
->x2
= b
->x2
;
539 if ( b
->y2
< out
->y2
) out
->y2
= b
->y2
;
540 if ( out
->x1
>= out
->x2
) return GL_FALSE
;
541 if ( out
->y1
>= out
->y2
) return GL_FALSE
;
546 void r200RecalcScissorRects( r200ContextPtr rmesa
)
548 drm_clip_rect_t
*out
;
551 /* Grow cliprect store?
553 if (rmesa
->state
.scissor
.numAllocedClipRects
< rmesa
->numClipRects
) {
554 while (rmesa
->state
.scissor
.numAllocedClipRects
< rmesa
->numClipRects
) {
555 rmesa
->state
.scissor
.numAllocedClipRects
+= 1; /* zero case */
556 rmesa
->state
.scissor
.numAllocedClipRects
*= 2;
559 if (rmesa
->state
.scissor
.pClipRects
)
560 FREE(rmesa
->state
.scissor
.pClipRects
);
562 rmesa
->state
.scissor
.pClipRects
=
563 MALLOC( rmesa
->state
.scissor
.numAllocedClipRects
*
564 sizeof(drm_clip_rect_t
) );
566 if ( rmesa
->state
.scissor
.pClipRects
== NULL
) {
567 rmesa
->state
.scissor
.numAllocedClipRects
= 0;
572 out
= rmesa
->state
.scissor
.pClipRects
;
573 rmesa
->state
.scissor
.numClipRects
= 0;
575 for ( i
= 0 ; i
< rmesa
->numClipRects
; i
++ ) {
576 if ( intersect_rect( out
,
577 &rmesa
->pClipRects
[i
],
578 &rmesa
->state
.scissor
.rect
) ) {
579 rmesa
->state
.scissor
.numClipRects
++;
586 static void r200UpdateScissor( GLcontext
*ctx
)
588 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
590 if ( rmesa
->dri
.drawable
) {
591 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
593 int x
= ctx
->Scissor
.X
;
594 int y
= dPriv
->h
- ctx
->Scissor
.Y
- ctx
->Scissor
.Height
;
595 int w
= ctx
->Scissor
.X
+ ctx
->Scissor
.Width
- 1;
596 int h
= dPriv
->h
- ctx
->Scissor
.Y
- 1;
598 rmesa
->state
.scissor
.rect
.x1
= x
+ dPriv
->x
;
599 rmesa
->state
.scissor
.rect
.y1
= y
+ dPriv
->y
;
600 rmesa
->state
.scissor
.rect
.x2
= w
+ dPriv
->x
+ 1;
601 rmesa
->state
.scissor
.rect
.y2
= h
+ dPriv
->y
+ 1;
603 r200RecalcScissorRects( rmesa
);
608 static void r200Scissor( GLcontext
*ctx
,
609 GLint x
, GLint y
, GLsizei w
, GLsizei h
)
611 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
613 if ( ctx
->Scissor
.Enabled
) {
614 R200_FIREVERTICES( rmesa
); /* don't pipeline cliprect changes */
615 r200UpdateScissor( ctx
);
621 /* =============================================================
625 static void r200CullFace( GLcontext
*ctx
, GLenum unused
)
627 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
628 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
629 GLuint t
= rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
];
631 s
|= R200_FFACE_SOLID
| R200_BFACE_SOLID
;
632 t
&= ~(R200_CULL_FRONT
| R200_CULL_BACK
);
634 if ( ctx
->Polygon
.CullFlag
) {
635 switch ( ctx
->Polygon
.CullFaceMode
) {
637 s
&= ~R200_FFACE_SOLID
;
638 t
|= R200_CULL_FRONT
;
641 s
&= ~R200_BFACE_SOLID
;
644 case GL_FRONT_AND_BACK
:
645 s
&= ~(R200_FFACE_SOLID
| R200_BFACE_SOLID
);
646 t
|= (R200_CULL_FRONT
| R200_CULL_BACK
);
651 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
652 R200_STATECHANGE(rmesa
, set
);
653 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
656 if ( rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] != t
) {
657 R200_STATECHANGE(rmesa
, tcl
);
658 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] = t
;
662 static void r200FrontFace( GLcontext
*ctx
, GLenum mode
)
664 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
666 R200_STATECHANGE( rmesa
, set
);
667 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_FFACE_CULL_DIR_MASK
;
669 R200_STATECHANGE( rmesa
, tcl
);
670 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_CULL_FRONT_IS_CCW
;
674 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_FFACE_CULL_CW
;
677 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_FFACE_CULL_CCW
;
678 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_CULL_FRONT_IS_CCW
;
683 /* =============================================================
686 static void r200PointSize( GLcontext
*ctx
, GLfloat size
)
688 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
689 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.ptp
.cmd
;
691 R200_STATECHANGE( rmesa
, cst
);
692 R200_STATECHANGE( rmesa
, ptp
);
693 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] &= ~0xffff;
694 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] |= ((GLuint
)(ctx
->Point
.Size
* 16.0));
695 /* this is the size param of the point size calculation (point size reg value
696 is not used when calculation is active). */
697 fcmd
[PTP_VPORT_SCALE_PTSIZE
] = ctx
->Point
.Size
;
700 static void r200PointParameter( GLcontext
*ctx
, GLenum pname
, const GLfloat
*params
)
702 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
703 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.ptp
.cmd
;
706 case GL_POINT_SIZE_MIN
:
707 /* Can clamp both in tcl and setup - just set both (as does fglrx) */
708 R200_STATECHANGE( rmesa
, lin
);
709 R200_STATECHANGE( rmesa
, ptp
);
710 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] &= 0xffff;
711 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] |= (GLuint
)(ctx
->Point
.MinSize
* 16.0) << 16;
712 fcmd
[PTP_CLAMP_MIN
] = ctx
->Point
.MinSize
;
714 case GL_POINT_SIZE_MAX
:
715 R200_STATECHANGE( rmesa
, cst
);
716 R200_STATECHANGE( rmesa
, ptp
);
717 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] &= 0xffff;
718 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] |= (GLuint
)(ctx
->Point
.MaxSize
* 16.0) << 16;
719 fcmd
[PTP_CLAMP_MAX
] = ctx
->Point
.MaxSize
;
721 case GL_POINT_DISTANCE_ATTENUATION
:
722 R200_STATECHANGE( rmesa
, vtx
);
723 R200_STATECHANGE( rmesa
, spr
);
724 R200_STATECHANGE( rmesa
, ptp
);
725 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.ptp
.cmd
;
726 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] &=
727 ~(R200_PS_MULT_MASK
| R200_PS_LIN_ATT_ZERO
| R200_PS_SE_SEL_STATE
);
728 /* can't rely on ctx->Point._Attenuated here and test for NEW_POINT in
729 r200ValidateState looks like overkill */
730 if (ctx
->Point
.Params
[0] != 1.0 ||
731 ctx
->Point
.Params
[1] != 0.0 ||
732 ctx
->Point
.Params
[2] != 0.0 ||
733 (ctx
->VertexProgram
.Enabled
&& ctx
->VertexProgram
.PointSizeEnabled
)) {
734 /* all we care for vp would be the ps_se_sel_state setting */
735 fcmd
[PTP_ATT_CONST_QUAD
] = ctx
->Point
.Params
[2];
736 fcmd
[PTP_ATT_CONST_LIN
] = ctx
->Point
.Params
[1];
737 fcmd
[PTP_ATT_CONST_CON
] = ctx
->Point
.Params
[0];
738 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |= R200_PS_MULT_ATTENCONST
;
739 if (ctx
->Point
.Params
[1] == 0.0)
740 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |= R200_PS_LIN_ATT_ZERO
;
741 /* FIXME: setting this here doesn't look quite ok - we only want to do
742 that if we're actually drawing points probably */
743 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_PT_SIZE
;
744 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |= R200_VTX_POINT_SIZE
;
747 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |=
748 R200_PS_SE_SEL_STATE
| R200_PS_MULT_CONST
;
749 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_PT_SIZE
;
750 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~R200_VTX_POINT_SIZE
;
753 case GL_POINT_FADE_THRESHOLD_SIZE
:
754 /* don't support multisampling, so doesn't matter. */
756 /* can't do these but don't need them.
757 case GL_POINT_SPRITE_R_MODE_NV:
758 case GL_POINT_SPRITE_COORD_ORIGIN: */
760 fprintf(stderr
, "bad pname parameter in r200PointParameter\n");
765 /* =============================================================
768 static void r200LineWidth( GLcontext
*ctx
, GLfloat widthf
)
770 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
772 R200_STATECHANGE( rmesa
, lin
);
773 R200_STATECHANGE( rmesa
, set
);
775 /* Line width is stored in U6.4 format.
777 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] &= ~0xffff;
778 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] |= (GLuint
)(ctx
->Line
._Width
* 16.0);
780 if ( widthf
> 1.0 ) {
781 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_WIDELINE_ENABLE
;
783 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_WIDELINE_ENABLE
;
787 static void r200LineStipple( GLcontext
*ctx
, GLint factor
, GLushort pattern
)
789 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
791 R200_STATECHANGE( rmesa
, lin
);
792 rmesa
->hw
.lin
.cmd
[LIN_RE_LINE_PATTERN
] =
793 ((((GLuint
)factor
& 0xff) << 16) | ((GLuint
)pattern
));
797 /* =============================================================
800 static void r200ColorMask( GLcontext
*ctx
,
801 GLboolean r
, GLboolean g
,
802 GLboolean b
, GLboolean a
)
804 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
805 GLuint mask
= r200PackColor( rmesa
->r200Screen
->cpp
,
806 ctx
->Color
.ColorMask
[RCOMP
],
807 ctx
->Color
.ColorMask
[GCOMP
],
808 ctx
->Color
.ColorMask
[BCOMP
],
809 ctx
->Color
.ColorMask
[ACOMP
] );
811 GLuint flag
= rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] & ~R200_PLANE_MASK_ENABLE
;
813 if (!(r
&& g
&& b
&& a
))
814 flag
|= R200_PLANE_MASK_ENABLE
;
816 if ( rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] != flag
) {
817 R200_STATECHANGE( rmesa
, ctx
);
818 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = flag
;
821 if ( rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
] != mask
) {
822 R200_STATECHANGE( rmesa
, msk
);
823 rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
] = mask
;
828 /* =============================================================
832 static void r200PolygonOffset( GLcontext
*ctx
,
833 GLfloat factor
, GLfloat units
)
835 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
836 float_ui32_type constant
= { units
* rmesa
->state
.depth
.scale
};
837 float_ui32_type factoru
= { factor
};
842 /* fprintf(stderr, "%s f:%f u:%f\n", __FUNCTION__, factor, constant); */
844 R200_STATECHANGE( rmesa
, zbs
);
845 rmesa
->hw
.zbs
.cmd
[ZBS_SE_ZBIAS_FACTOR
] = factoru
.ui32
;
846 rmesa
->hw
.zbs
.cmd
[ZBS_SE_ZBIAS_CONSTANT
] = constant
.ui32
;
849 static void r200PolygonStipple( GLcontext
*ctx
, const GLubyte
*mask
)
851 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
853 drm_radeon_stipple_t stipple
;
855 /* Must flip pattern upside down.
857 for ( i
= 0 ; i
< 32 ; i
++ ) {
858 rmesa
->state
.stipple
.mask
[31 - i
] = ((GLuint
*) mask
)[i
];
861 /* TODO: push this into cmd mechanism
863 R200_FIREVERTICES( rmesa
);
864 LOCK_HARDWARE( rmesa
);
866 /* FIXME: Use window x,y offsets into stipple RAM.
868 stipple
.mask
= rmesa
->state
.stipple
.mask
;
869 drmCommandWrite( rmesa
->dri
.fd
, DRM_RADEON_STIPPLE
,
870 &stipple
, sizeof(stipple
) );
871 UNLOCK_HARDWARE( rmesa
);
874 static void r200PolygonMode( GLcontext
*ctx
, GLenum face
, GLenum mode
)
876 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
877 GLboolean flag
= (ctx
->_TriangleCaps
& DD_TRI_UNFILLED
) != 0;
879 /* Can't generally do unfilled via tcl, but some good special
882 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_UNFILLED
, flag
);
883 if (rmesa
->TclFallback
) {
884 r200ChooseRenderState( ctx
);
885 r200ChooseVertexState( ctx
);
890 /* =============================================================
891 * Rendering attributes
893 * We really don't want to recalculate all this every time we bind a
894 * texture. These things shouldn't change all that often, so it makes
895 * sense to break them out of the core texture state update routines.
898 /* Examine lighting and texture state to determine if separate specular
901 static void r200UpdateSpecular( GLcontext
*ctx
)
903 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
904 u_int32_t p
= rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
];
906 R200_STATECHANGE( rmesa
, tcl
);
907 R200_STATECHANGE( rmesa
, vtx
);
909 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~(3<<R200_VTX_COLOR_0_SHIFT
);
910 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~(3<<R200_VTX_COLOR_1_SHIFT
);
911 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_COLOR_0
;
912 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_COLOR_1
;
913 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LIGHTING_ENABLE
;
915 p
&= ~R200_SPECULAR_ENABLE
;
917 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_DIFFUSE_SPECULAR_COMBINE
;
920 if (ctx
->Light
.Enabled
&&
921 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
) {
922 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
923 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
) |
924 (R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
925 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_0
;
926 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_1
;
927 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHTING_ENABLE
;
928 p
|= R200_SPECULAR_ENABLE
;
929 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &=
930 ~R200_DIFFUSE_SPECULAR_COMBINE
;
932 else if (ctx
->Light
.Enabled
) {
933 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
934 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
));
935 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_0
;
936 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHTING_ENABLE
;
937 } else if (ctx
->Fog
.ColorSumEnabled
) {
938 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
939 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
) |
940 (R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
941 p
|= R200_SPECULAR_ENABLE
;
943 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
944 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
));
947 if (ctx
->Fog
.Enabled
) {
948 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
949 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
950 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_1
;
953 if ( rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] != p
) {
954 R200_STATECHANGE( rmesa
, ctx
);
955 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] = p
;
958 /* Update vertex/render formats
960 if (rmesa
->TclFallback
) {
961 r200ChooseRenderState( ctx
);
962 r200ChooseVertexState( ctx
);
967 /* =============================================================
972 /* Update on colormaterial, material emmissive/ambient,
973 * lightmodel.globalambient
975 static void update_global_ambient( GLcontext
*ctx
)
977 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
978 float *fcmd
= (float *)R200_DB_STATE( glt
);
980 /* Need to do more if both emmissive & ambient are PREMULT:
981 * I believe this is not nessary when using source_material. This condition thus
982 * will never happen currently, and the function has no dependencies on materials now
984 if ((rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
] &
985 ((3 << R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
986 (3 << R200_FRONT_AMBIENT_SOURCE_SHIFT
))) == 0)
988 COPY_3V( &fcmd
[GLT_RED
],
989 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_EMISSION
]);
990 ACC_SCALE_3V( &fcmd
[GLT_RED
],
991 ctx
->Light
.Model
.Ambient
,
992 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_AMBIENT
]);
996 COPY_3V( &fcmd
[GLT_RED
], ctx
->Light
.Model
.Ambient
);
999 R200_DB_STATECHANGE(rmesa
, &rmesa
->hw
.glt
);
1002 /* Update on change to
1004 * - light[p].enabled
1006 static void update_light_colors( GLcontext
*ctx
, GLuint p
)
1008 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1010 /* fprintf(stderr, "%s\n", __FUNCTION__); */
1013 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1014 float *fcmd
= (float *)R200_DB_STATE( lit
[p
] );
1016 COPY_4V( &fcmd
[LIT_AMBIENT_RED
], l
->Ambient
);
1017 COPY_4V( &fcmd
[LIT_DIFFUSE_RED
], l
->Diffuse
);
1018 COPY_4V( &fcmd
[LIT_SPECULAR_RED
], l
->Specular
);
1020 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
1024 static void r200ColorMaterial( GLcontext
*ctx
, GLenum face
, GLenum mode
)
1026 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1027 GLuint light_model_ctl1
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
];
1028 light_model_ctl1
&= ~((0xf << R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
1029 (0xf << R200_FRONT_AMBIENT_SOURCE_SHIFT
) |
1030 (0xf << R200_FRONT_DIFFUSE_SOURCE_SHIFT
) |
1031 (0xf << R200_FRONT_SPECULAR_SOURCE_SHIFT
) |
1032 (0xf << R200_BACK_EMISSIVE_SOURCE_SHIFT
) |
1033 (0xf << R200_BACK_AMBIENT_SOURCE_SHIFT
) |
1034 (0xf << R200_BACK_DIFFUSE_SOURCE_SHIFT
) |
1035 (0xf << R200_BACK_SPECULAR_SOURCE_SHIFT
));
1037 if (ctx
->Light
.ColorMaterialEnabled
) {
1038 GLuint mask
= ctx
->Light
.ColorMaterialBitmask
;
1040 if (mask
& MAT_BIT_FRONT_EMISSION
) {
1041 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
1042 R200_FRONT_EMISSIVE_SOURCE_SHIFT
);
1045 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
1046 R200_FRONT_EMISSIVE_SOURCE_SHIFT
);
1048 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
1049 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
1050 R200_FRONT_AMBIENT_SOURCE_SHIFT
);
1053 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
1054 R200_FRONT_AMBIENT_SOURCE_SHIFT
);
1056 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
1057 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
1058 R200_FRONT_DIFFUSE_SOURCE_SHIFT
);
1061 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
1062 R200_FRONT_DIFFUSE_SOURCE_SHIFT
);
1064 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
1065 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
1066 R200_FRONT_SPECULAR_SOURCE_SHIFT
);
1069 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
1070 R200_FRONT_SPECULAR_SOURCE_SHIFT
);
1073 if (mask
& MAT_BIT_BACK_EMISSION
) {
1074 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
1075 R200_BACK_EMISSIVE_SOURCE_SHIFT
);
1078 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
1079 R200_BACK_EMISSIVE_SOURCE_SHIFT
);
1081 if (mask
& MAT_BIT_BACK_AMBIENT
) {
1082 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
1083 R200_BACK_AMBIENT_SOURCE_SHIFT
);
1085 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
1086 R200_BACK_AMBIENT_SOURCE_SHIFT
);
1088 if (mask
& MAT_BIT_BACK_DIFFUSE
) {
1089 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
1090 R200_BACK_DIFFUSE_SOURCE_SHIFT
);
1092 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
1093 R200_BACK_DIFFUSE_SOURCE_SHIFT
);
1095 if (mask
& MAT_BIT_BACK_SPECULAR
) {
1096 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
1097 R200_BACK_SPECULAR_SOURCE_SHIFT
);
1100 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
1101 R200_BACK_SPECULAR_SOURCE_SHIFT
);
1105 /* Default to SOURCE_MATERIAL:
1108 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
1109 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_AMBIENT_SOURCE_SHIFT
) |
1110 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_DIFFUSE_SOURCE_SHIFT
) |
1111 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_SPECULAR_SOURCE_SHIFT
) |
1112 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_EMISSIVE_SOURCE_SHIFT
) |
1113 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_AMBIENT_SOURCE_SHIFT
) |
1114 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_DIFFUSE_SOURCE_SHIFT
) |
1115 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_SPECULAR_SOURCE_SHIFT
);
1118 if (light_model_ctl1
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
]) {
1119 R200_STATECHANGE( rmesa
, tcl
);
1120 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
] = light_model_ctl1
;
1126 void r200UpdateMaterial( GLcontext
*ctx
)
1128 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1129 GLfloat (*mat
)[4] = ctx
->Light
.Material
.Attrib
;
1130 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( mtl
[0] );
1131 GLfloat
*fcmd2
= (GLfloat
*)R200_DB_STATE( mtl
[1] );
1134 /* Might be possible and faster to update everything unconditionally? */
1135 if (ctx
->Light
.ColorMaterialEnabled
)
1136 mask
&= ~ctx
->Light
.ColorMaterialBitmask
;
1138 if (R200_DEBUG
& DEBUG_STATE
)
1139 fprintf(stderr
, "%s\n", __FUNCTION__
);
1141 if (mask
& MAT_BIT_FRONT_EMISSION
) {
1142 fcmd
[MTL_EMMISSIVE_RED
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][0];
1143 fcmd
[MTL_EMMISSIVE_GREEN
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][1];
1144 fcmd
[MTL_EMMISSIVE_BLUE
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][2];
1145 fcmd
[MTL_EMMISSIVE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][3];
1147 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
1148 fcmd
[MTL_AMBIENT_RED
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][0];
1149 fcmd
[MTL_AMBIENT_GREEN
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][1];
1150 fcmd
[MTL_AMBIENT_BLUE
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][2];
1151 fcmd
[MTL_AMBIENT_ALPHA
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][3];
1153 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
1154 fcmd
[MTL_DIFFUSE_RED
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][0];
1155 fcmd
[MTL_DIFFUSE_GREEN
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][1];
1156 fcmd
[MTL_DIFFUSE_BLUE
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][2];
1157 fcmd
[MTL_DIFFUSE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][3];
1159 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
1160 fcmd
[MTL_SPECULAR_RED
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][0];
1161 fcmd
[MTL_SPECULAR_GREEN
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][1];
1162 fcmd
[MTL_SPECULAR_BLUE
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][2];
1163 fcmd
[MTL_SPECULAR_ALPHA
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][3];
1165 if (mask
& MAT_BIT_FRONT_SHININESS
) {
1166 fcmd
[MTL_SHININESS
] = mat
[MAT_ATTRIB_FRONT_SHININESS
][0];
1169 if (mask
& MAT_BIT_BACK_EMISSION
) {
1170 fcmd2
[MTL_EMMISSIVE_RED
] = mat
[MAT_ATTRIB_BACK_EMISSION
][0];
1171 fcmd2
[MTL_EMMISSIVE_GREEN
] = mat
[MAT_ATTRIB_BACK_EMISSION
][1];
1172 fcmd2
[MTL_EMMISSIVE_BLUE
] = mat
[MAT_ATTRIB_BACK_EMISSION
][2];
1173 fcmd2
[MTL_EMMISSIVE_ALPHA
] = mat
[MAT_ATTRIB_BACK_EMISSION
][3];
1175 if (mask
& MAT_BIT_BACK_AMBIENT
) {
1176 fcmd2
[MTL_AMBIENT_RED
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][0];
1177 fcmd2
[MTL_AMBIENT_GREEN
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][1];
1178 fcmd2
[MTL_AMBIENT_BLUE
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][2];
1179 fcmd2
[MTL_AMBIENT_ALPHA
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][3];
1181 if (mask
& MAT_BIT_BACK_DIFFUSE
) {
1182 fcmd2
[MTL_DIFFUSE_RED
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][0];
1183 fcmd2
[MTL_DIFFUSE_GREEN
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][1];
1184 fcmd2
[MTL_DIFFUSE_BLUE
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][2];
1185 fcmd2
[MTL_DIFFUSE_ALPHA
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][3];
1187 if (mask
& MAT_BIT_BACK_SPECULAR
) {
1188 fcmd2
[MTL_SPECULAR_RED
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][0];
1189 fcmd2
[MTL_SPECULAR_GREEN
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][1];
1190 fcmd2
[MTL_SPECULAR_BLUE
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][2];
1191 fcmd2
[MTL_SPECULAR_ALPHA
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][3];
1193 if (mask
& MAT_BIT_BACK_SHININESS
) {
1194 fcmd2
[MTL_SHININESS
] = mat
[MAT_ATTRIB_BACK_SHININESS
][0];
1197 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mtl
[0] );
1198 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mtl
[1] );
1200 /* currently material changes cannot trigger a global ambient change, I believe this is correct
1201 update_global_ambient( ctx ); */
1206 * _MESA_NEW_NEED_EYE_COORDS
1208 * Uses derived state from mesa:
1213 * _ModelViewInvScale
1217 * which are calculated in light.c and are correct for the current
1218 * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
1219 * and _MESA_NEW_NEED_EYE_COORDS.
1221 static void update_light( GLcontext
*ctx
)
1223 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1225 /* Have to check these, or have an automatic shortcircuit mechanism
1226 * to remove noop statechanges. (Or just do a better job on the
1230 GLuint tmp
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
];
1232 if (ctx
->_NeedEyeCoords
)
1233 tmp
&= ~R200_LIGHT_IN_MODELSPACE
;
1235 tmp
|= R200_LIGHT_IN_MODELSPACE
;
1237 if (tmp
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
])
1239 R200_STATECHANGE( rmesa
, tcl
);
1240 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] = tmp
;
1245 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( eye
);
1246 fcmd
[EYE_X
] = ctx
->_EyeZDir
[0];
1247 fcmd
[EYE_Y
] = ctx
->_EyeZDir
[1];
1248 fcmd
[EYE_Z
] = - ctx
->_EyeZDir
[2];
1249 fcmd
[EYE_RESCALE_FACTOR
] = ctx
->_ModelViewInvScale
;
1250 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.eye
);
1255 if (ctx
->Light
.Enabled
) {
1257 for (p
= 0 ; p
< MAX_LIGHTS
; p
++) {
1258 if (ctx
->Light
.Light
[p
].Enabled
) {
1259 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1260 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( lit
[p
] );
1262 if (l
->EyePosition
[3] == 0.0) {
1263 COPY_3FV( &fcmd
[LIT_POSITION_X
], l
->_VP_inf_norm
);
1264 COPY_3FV( &fcmd
[LIT_DIRECTION_X
], l
->_h_inf_norm
);
1265 fcmd
[LIT_POSITION_W
] = 0;
1266 fcmd
[LIT_DIRECTION_W
] = 0;
1268 COPY_4V( &fcmd
[LIT_POSITION_X
], l
->_Position
);
1269 fcmd
[LIT_DIRECTION_X
] = -l
->_NormDirection
[0];
1270 fcmd
[LIT_DIRECTION_Y
] = -l
->_NormDirection
[1];
1271 fcmd
[LIT_DIRECTION_Z
] = -l
->_NormDirection
[2];
1272 fcmd
[LIT_DIRECTION_W
] = 0;
1275 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
1281 static void r200Lightfv( GLcontext
*ctx
, GLenum light
,
1282 GLenum pname
, const GLfloat
*params
)
1284 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1285 GLint p
= light
- GL_LIGHT0
;
1286 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1287 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.lit
[p
].cmd
;
1294 update_light_colors( ctx
, p
);
1297 case GL_SPOT_DIRECTION
:
1298 /* picked up in update_light */
1302 /* positions picked up in update_light, but can do flag here */
1303 GLuint flag
= (p
&1)? R200_LIGHT_1_IS_LOCAL
: R200_LIGHT_0_IS_LOCAL
;
1304 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1306 R200_STATECHANGE(rmesa
, tcl
);
1307 if (l
->EyePosition
[3] != 0.0F
)
1308 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1310 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1314 case GL_SPOT_EXPONENT
:
1315 R200_STATECHANGE(rmesa
, lit
[p
]);
1316 fcmd
[LIT_SPOT_EXPONENT
] = params
[0];
1319 case GL_SPOT_CUTOFF
: {
1320 GLuint flag
= (p
&1) ? R200_LIGHT_1_IS_SPOT
: R200_LIGHT_0_IS_SPOT
;
1321 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1323 R200_STATECHANGE(rmesa
, lit
[p
]);
1324 fcmd
[LIT_SPOT_CUTOFF
] = l
->_CosCutoff
;
1326 R200_STATECHANGE(rmesa
, tcl
);
1327 if (l
->SpotCutoff
!= 180.0F
)
1328 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1330 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1335 case GL_CONSTANT_ATTENUATION
:
1336 R200_STATECHANGE(rmesa
, lit
[p
]);
1337 fcmd
[LIT_ATTEN_CONST
] = params
[0];
1338 if ( params
[0] == 0.0 )
1339 fcmd
[LIT_ATTEN_CONST_INV
] = FLT_MAX
;
1341 fcmd
[LIT_ATTEN_CONST_INV
] = 1.0 / params
[0];
1343 case GL_LINEAR_ATTENUATION
:
1344 R200_STATECHANGE(rmesa
, lit
[p
]);
1345 fcmd
[LIT_ATTEN_LINEAR
] = params
[0];
1347 case GL_QUADRATIC_ATTENUATION
:
1348 R200_STATECHANGE(rmesa
, lit
[p
]);
1349 fcmd
[LIT_ATTEN_QUADRATIC
] = params
[0];
1355 /* Set RANGE_ATTEN only when needed */
1358 case GL_CONSTANT_ATTENUATION
:
1359 case GL_LINEAR_ATTENUATION
:
1360 case GL_QUADRATIC_ATTENUATION
: {
1361 GLuint
*icmd
= (GLuint
*)R200_DB_STATE( tcl
);
1362 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1363 GLuint atten_flag
= ( p
&1 ) ? R200_LIGHT_1_ENABLE_RANGE_ATTEN
1364 : R200_LIGHT_0_ENABLE_RANGE_ATTEN
;
1365 GLuint atten_const_flag
= ( p
&1 ) ? R200_LIGHT_1_CONSTANT_RANGE_ATTEN
1366 : R200_LIGHT_0_CONSTANT_RANGE_ATTEN
;
1368 if ( l
->EyePosition
[3] == 0.0F
||
1369 ( ( fcmd
[LIT_ATTEN_CONST
] == 0.0 || fcmd
[LIT_ATTEN_CONST
] == 1.0 ) &&
1370 fcmd
[LIT_ATTEN_QUADRATIC
] == 0.0 && fcmd
[LIT_ATTEN_LINEAR
] == 0.0 ) ) {
1371 /* Disable attenuation */
1372 icmd
[idx
] &= ~atten_flag
;
1374 if ( fcmd
[LIT_ATTEN_QUADRATIC
] == 0.0 && fcmd
[LIT_ATTEN_LINEAR
] == 0.0 ) {
1375 /* Enable only constant portion of attenuation calculation */
1376 icmd
[idx
] |= ( atten_flag
| atten_const_flag
);
1378 /* Enable full attenuation calculation */
1379 icmd
[idx
] &= ~atten_const_flag
;
1380 icmd
[idx
] |= atten_flag
;
1384 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.tcl
);
1392 static void r200UpdateLocalViewer ( GLcontext
*ctx
)
1394 /* It looks like for the texgen modes GL_SPHERE_MAP, GL_NORMAL_MAP and
1395 GL_REFLECTION_MAP we need R200_LOCAL_VIEWER set (fglrx does exactly that
1396 for these and only these modes). This means specular highlights may turn out
1397 wrong in some cases when lighting is enabled but GL_LIGHT_MODEL_LOCAL_VIEWER
1398 is not set, though it seems to happen rarely and the effect seems quite
1399 subtle. May need TCL fallback to fix it completely, though I'm not sure
1400 how you'd identify the cases where the specular highlights indeed will
1401 be wrong. Don't know if fglrx does something special in that case.
1403 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1404 R200_STATECHANGE( rmesa
, tcl
);
1405 if (ctx
->Light
.Model
.LocalViewer
||
1406 ctx
->Texture
._GenFlags
& TEXGEN_NEED_NORMALS
)
1407 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LOCAL_VIEWER
;
1409 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LOCAL_VIEWER
;
1412 static void r200LightModelfv( GLcontext
*ctx
, GLenum pname
,
1413 const GLfloat
*param
)
1415 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1418 case GL_LIGHT_MODEL_AMBIENT
:
1419 update_global_ambient( ctx
);
1422 case GL_LIGHT_MODEL_LOCAL_VIEWER
:
1423 r200UpdateLocalViewer( ctx
);
1426 case GL_LIGHT_MODEL_TWO_SIDE
:
1427 R200_STATECHANGE( rmesa
, tcl
);
1428 if (ctx
->Light
.Model
.TwoSide
)
1429 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHT_TWOSIDE
;
1431 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~(R200_LIGHT_TWOSIDE
);
1432 if (rmesa
->TclFallback
) {
1433 r200ChooseRenderState( ctx
);
1434 r200ChooseVertexState( ctx
);
1438 case GL_LIGHT_MODEL_COLOR_CONTROL
:
1439 r200UpdateSpecular(ctx
);
1447 static void r200ShadeModel( GLcontext
*ctx
, GLenum mode
)
1449 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1450 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
1452 s
&= ~(R200_DIFFUSE_SHADE_MASK
|
1453 R200_ALPHA_SHADE_MASK
|
1454 R200_SPECULAR_SHADE_MASK
|
1455 R200_FOG_SHADE_MASK
|
1456 R200_DISC_FOG_SHADE_MASK
);
1460 s
|= (R200_DIFFUSE_SHADE_FLAT
|
1461 R200_ALPHA_SHADE_FLAT
|
1462 R200_SPECULAR_SHADE_FLAT
|
1463 R200_FOG_SHADE_FLAT
|
1464 R200_DISC_FOG_SHADE_FLAT
);
1467 s
|= (R200_DIFFUSE_SHADE_GOURAUD
|
1468 R200_ALPHA_SHADE_GOURAUD
|
1469 R200_SPECULAR_SHADE_GOURAUD
|
1470 R200_FOG_SHADE_GOURAUD
|
1471 R200_DISC_FOG_SHADE_GOURAUD
);
1477 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
1478 R200_STATECHANGE( rmesa
, set
);
1479 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
1484 /* =============================================================
1488 static void r200ClipPlane( GLcontext
*ctx
, GLenum plane
, const GLfloat
*eq
)
1490 GLint p
= (GLint
) plane
- (GLint
) GL_CLIP_PLANE0
;
1491 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1492 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1494 R200_STATECHANGE( rmesa
, ucp
[p
] );
1495 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1496 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1497 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1498 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1501 static void r200UpdateClipPlanes( GLcontext
*ctx
)
1503 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1506 for (p
= 0; p
< ctx
->Const
.MaxClipPlanes
; p
++) {
1507 if (ctx
->Transform
.ClipPlanesEnabled
& (1 << p
)) {
1508 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1510 R200_STATECHANGE( rmesa
, ucp
[p
] );
1511 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1512 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1513 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1514 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1520 /* =============================================================
1525 r200StencilFuncSeparate( GLcontext
*ctx
, GLenum face
, GLenum func
,
1526 GLint ref
, GLuint mask
)
1528 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1529 GLuint refmask
= (((ctx
->Stencil
.Ref
[0] & 0xff) << R200_STENCIL_REF_SHIFT
) |
1530 ((ctx
->Stencil
.ValueMask
[0] & 0xff) << R200_STENCIL_MASK_SHIFT
));
1532 R200_STATECHANGE( rmesa
, ctx
);
1533 R200_STATECHANGE( rmesa
, msk
);
1535 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_STENCIL_TEST_MASK
;
1536 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~(R200_STENCIL_REF_MASK
|
1537 R200_STENCIL_VALUE_MASK
);
1539 switch ( ctx
->Stencil
.Function
[0] ) {
1541 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEVER
;
1544 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LESS
;
1547 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_EQUAL
;
1550 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LEQUAL
;
1553 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GREATER
;
1556 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEQUAL
;
1559 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GEQUAL
;
1562 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_ALWAYS
;
1566 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |= refmask
;
1570 r200StencilMaskSeparate( GLcontext
*ctx
, GLenum face
, GLuint mask
)
1572 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1574 R200_STATECHANGE( rmesa
, msk
);
1575 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~R200_STENCIL_WRITE_MASK
;
1576 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |=
1577 ((ctx
->Stencil
.WriteMask
[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT
);
1581 r200StencilOpSeparate( GLcontext
*ctx
, GLenum face
, GLenum fail
,
1582 GLenum zfail
, GLenum zpass
)
1584 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1586 R200_STATECHANGE( rmesa
, ctx
);
1587 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~(R200_STENCIL_FAIL_MASK
|
1588 R200_STENCIL_ZFAIL_MASK
|
1589 R200_STENCIL_ZPASS_MASK
);
1591 switch ( ctx
->Stencil
.FailFunc
[0] ) {
1593 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_KEEP
;
1596 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_ZERO
;
1599 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_REPLACE
;
1602 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC
;
1605 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC
;
1607 case GL_INCR_WRAP_EXT
:
1608 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC_WRAP
;
1610 case GL_DECR_WRAP_EXT
:
1611 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC_WRAP
;
1614 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INVERT
;
1618 switch ( ctx
->Stencil
.ZFailFunc
[0] ) {
1620 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_KEEP
;
1623 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_ZERO
;
1626 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_REPLACE
;
1629 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC
;
1632 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC
;
1634 case GL_INCR_WRAP_EXT
:
1635 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC_WRAP
;
1637 case GL_DECR_WRAP_EXT
:
1638 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC_WRAP
;
1641 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INVERT
;
1645 switch ( ctx
->Stencil
.ZPassFunc
[0] ) {
1647 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_KEEP
;
1650 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_ZERO
;
1653 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_REPLACE
;
1656 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC
;
1659 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC
;
1661 case GL_INCR_WRAP_EXT
:
1662 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC_WRAP
;
1664 case GL_DECR_WRAP_EXT
:
1665 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC_WRAP
;
1668 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INVERT
;
1673 static void r200ClearStencil( GLcontext
*ctx
, GLint s
)
1675 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1677 rmesa
->state
.stencil
.clear
=
1678 ((GLuint
) (ctx
->Stencil
.Clear
& 0xff) |
1679 (0xff << R200_STENCIL_MASK_SHIFT
) |
1680 ((ctx
->Stencil
.WriteMask
[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT
));
1684 /* =============================================================
1685 * Window position and viewport transformation
1689 * To correctly position primitives:
1691 #define SUBPIXEL_X 0.125
1692 #define SUBPIXEL_Y 0.125
1694 void r200UpdateWindow( GLcontext
*ctx
)
1696 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1697 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
1698 GLfloat xoffset
= (GLfloat
)dPriv
->x
;
1699 GLfloat yoffset
= (GLfloat
)dPriv
->y
+ dPriv
->h
;
1700 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1702 float_ui32_type sx
= { v
[MAT_SX
] };
1703 float_ui32_type tx
= { v
[MAT_TX
] + xoffset
+ SUBPIXEL_X
};
1704 float_ui32_type sy
= { - v
[MAT_SY
] };
1705 float_ui32_type ty
= { (- v
[MAT_TY
]) + yoffset
+ SUBPIXEL_Y
};
1706 float_ui32_type sz
= { v
[MAT_SZ
] * rmesa
->state
.depth
.scale
};
1707 float_ui32_type tz
= { v
[MAT_TZ
] * rmesa
->state
.depth
.scale
};
1709 R200_FIREVERTICES( rmesa
);
1710 R200_STATECHANGE( rmesa
, vpt
);
1712 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XSCALE
] = sx
.ui32
;
1713 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = tx
.ui32
;
1714 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YSCALE
] = sy
.ui32
;
1715 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = ty
.ui32
;
1716 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZSCALE
] = sz
.ui32
;
1717 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZOFFSET
] = tz
.ui32
;
1722 static void r200Viewport( GLcontext
*ctx
, GLint x
, GLint y
,
1723 GLsizei width
, GLsizei height
)
1725 /* Don't pipeline viewport changes, conflict with window offset
1726 * setting below. Could apply deltas to rescue pipelined viewport
1727 * values, or keep the originals hanging around.
1729 r200UpdateWindow( ctx
);
1732 static void r200DepthRange( GLcontext
*ctx
, GLclampd nearval
,
1735 r200UpdateWindow( ctx
);
1738 void r200UpdateViewportOffset( GLcontext
*ctx
)
1740 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1741 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
1742 GLfloat xoffset
= (GLfloat
)dPriv
->x
;
1743 GLfloat yoffset
= (GLfloat
)dPriv
->y
+ dPriv
->h
;
1744 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1749 tx
.f
= v
[MAT_TX
] + xoffset
+ SUBPIXEL_X
;
1750 ty
.f
= (- v
[MAT_TY
]) + yoffset
+ SUBPIXEL_Y
;
1752 if ( rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] != tx
.ui32
||
1753 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] != ty
.ui32
)
1755 /* Note: this should also modify whatever data the context reset
1758 R200_STATECHANGE( rmesa
, vpt
);
1759 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = tx
.ui32
;
1760 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = ty
.ui32
;
1762 /* update polygon stipple x/y screen offset */
1765 GLuint m
= rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
];
1767 m
&= ~(R200_STIPPLE_X_OFFSET_MASK
|
1768 R200_STIPPLE_Y_OFFSET_MASK
);
1770 /* add magic offsets, then invert */
1771 stx
= 31 - ((rmesa
->dri
.drawable
->x
- 1) & R200_STIPPLE_COORD_MASK
);
1772 sty
= 31 - ((rmesa
->dri
.drawable
->y
+ rmesa
->dri
.drawable
->h
- 1)
1773 & R200_STIPPLE_COORD_MASK
);
1775 m
|= ((stx
<< R200_STIPPLE_X_OFFSET_SHIFT
) |
1776 (sty
<< R200_STIPPLE_Y_OFFSET_SHIFT
));
1778 if ( rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] != m
) {
1779 R200_STATECHANGE( rmesa
, msc
);
1780 rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] = m
;
1785 r200UpdateScissor( ctx
);
1790 /* =============================================================
1794 static void r200ClearColor( GLcontext
*ctx
, const GLfloat c
[4] )
1796 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1798 CLAMPED_FLOAT_TO_UBYTE(color
[0], c
[0]);
1799 CLAMPED_FLOAT_TO_UBYTE(color
[1], c
[1]);
1800 CLAMPED_FLOAT_TO_UBYTE(color
[2], c
[2]);
1801 CLAMPED_FLOAT_TO_UBYTE(color
[3], c
[3]);
1802 rmesa
->state
.color
.clear
= r200PackColor( rmesa
->r200Screen
->cpp
,
1804 color
[2], color
[3] );
1808 static void r200RenderMode( GLcontext
*ctx
, GLenum mode
)
1810 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1811 FALLBACK( rmesa
, R200_FALLBACK_RENDER_MODE
, (mode
!= GL_RENDER
) );
1815 static GLuint r200_rop_tab
[] = {
1818 R200_ROP_AND_REVERSE
,
1820 R200_ROP_AND_INVERTED
,
1827 R200_ROP_OR_REVERSE
,
1828 R200_ROP_COPY_INVERTED
,
1829 R200_ROP_OR_INVERTED
,
1834 static void r200LogicOpCode( GLcontext
*ctx
, GLenum opcode
)
1836 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1837 GLuint rop
= (GLuint
)opcode
- GL_CLEAR
;
1841 R200_STATECHANGE( rmesa
, msk
);
1842 rmesa
->hw
.msk
.cmd
[MSK_RB3D_ROPCNTL
] = r200_rop_tab
[rop
];
1846 void r200SetCliprects( r200ContextPtr rmesa
, GLenum mode
)
1848 __DRIdrawablePrivate
*const drawable
= rmesa
->dri
.drawable
;
1849 __DRIdrawablePrivate
*const readable
= rmesa
->dri
.readable
;
1850 GLframebuffer
*const draw_fb
= (GLframebuffer
*) drawable
->driverPrivate
;
1851 GLframebuffer
*const read_fb
= (GLframebuffer
*) readable
->driverPrivate
;
1855 rmesa
->numClipRects
= drawable
->numClipRects
;
1856 rmesa
->pClipRects
= drawable
->pClipRects
;
1859 /* Can't ignore 2d windows if we are page flipping.
1861 if ( drawable
->numBackClipRects
== 0 || rmesa
->doPageFlip
) {
1862 rmesa
->numClipRects
= drawable
->numClipRects
;
1863 rmesa
->pClipRects
= drawable
->pClipRects
;
1866 rmesa
->numClipRects
= drawable
->numBackClipRects
;
1867 rmesa
->pClipRects
= drawable
->pBackClipRects
;
1871 fprintf(stderr
, "bad mode in r200SetCliprects\n");
1875 if ((draw_fb
->Width
!= drawable
->w
) || (draw_fb
->Height
!= drawable
->h
)) {
1876 _mesa_resize_framebuffer(rmesa
->glCtx
, draw_fb
,
1877 drawable
->w
, drawable
->h
);
1878 draw_fb
->Initialized
= GL_TRUE
;
1881 if (drawable
!= readable
) {
1882 if ((read_fb
->Width
!= readable
->w
) ||
1883 (read_fb
->Height
!= readable
->h
)) {
1884 _mesa_resize_framebuffer(rmesa
->glCtx
, read_fb
,
1885 readable
->w
, readable
->h
);
1886 read_fb
->Initialized
= GL_TRUE
;
1890 if (rmesa
->state
.scissor
.enabled
)
1891 r200RecalcScissorRects( rmesa
);
1893 rmesa
->lastStamp
= drawable
->lastStamp
;
1897 static void r200DrawBuffer( GLcontext
*ctx
, GLenum mode
)
1899 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1901 if (R200_DEBUG
& DEBUG_DRI
)
1902 fprintf(stderr
, "%s %s\n", __FUNCTION__
,
1903 _mesa_lookup_enum_by_nr( mode
));
1905 R200_FIREVERTICES(rmesa
); /* don't pipeline cliprect changes */
1908 * _ColorDrawBufferMask is easier to cope with than <mode>.
1909 * Check for software fallback, update cliprects.
1911 switch ( ctx
->DrawBuffer
->_ColorDrawBufferMask
[0] ) {
1912 case BUFFER_BIT_FRONT_LEFT
:
1913 FALLBACK( rmesa
, R200_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
1914 r200SetCliprects( rmesa
, GL_FRONT_LEFT
);
1916 case BUFFER_BIT_BACK_LEFT
:
1917 FALLBACK( rmesa
, R200_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
1918 r200SetCliprects( rmesa
, GL_BACK_LEFT
);
1921 /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */
1922 FALLBACK( rmesa
, R200_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
1926 /* We'll set the drawing engine's offset/pitch parameters later
1927 * when we update other state.
1932 static void r200ReadBuffer( GLcontext
*ctx
, GLenum mode
)
1934 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
1937 /* =============================================================
1938 * State enable/disable
1941 static void r200Enable( GLcontext
*ctx
, GLenum cap
, GLboolean state
)
1943 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1946 if ( R200_DEBUG
& DEBUG_STATE
)
1947 fprintf( stderr
, "%s( %s = %s )\n", __FUNCTION__
,
1948 _mesa_lookup_enum_by_nr( cap
),
1949 state
? "GL_TRUE" : "GL_FALSE" );
1952 /* Fast track this one...
1960 R200_STATECHANGE( rmesa
, ctx
);
1962 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ALPHA_TEST_ENABLE
;
1964 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ALPHA_TEST_ENABLE
;
1969 case GL_COLOR_LOGIC_OP
:
1970 r200_set_blend_state( ctx
);
1973 case GL_CLIP_PLANE0
:
1974 case GL_CLIP_PLANE1
:
1975 case GL_CLIP_PLANE2
:
1976 case GL_CLIP_PLANE3
:
1977 case GL_CLIP_PLANE4
:
1978 case GL_CLIP_PLANE5
:
1979 p
= cap
-GL_CLIP_PLANE0
;
1980 R200_STATECHANGE( rmesa
, tcl
);
1982 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= (R200_UCP_ENABLE_0
<<p
);
1983 r200ClipPlane( ctx
, cap
, NULL
);
1986 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~(R200_UCP_ENABLE_0
<<p
);
1990 case GL_COLOR_MATERIAL
:
1991 r200ColorMaterial( ctx
, 0, 0 );
1992 r200UpdateMaterial( ctx
);
1996 r200CullFace( ctx
, 0 );
2000 R200_STATECHANGE(rmesa
, ctx
);
2002 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_Z_ENABLE
;
2004 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_Z_ENABLE
;
2009 R200_STATECHANGE(rmesa
, ctx
);
2011 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_DITHER_ENABLE
;
2012 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~rmesa
->state
.color
.roundEnable
;
2014 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_DITHER_ENABLE
;
2015 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= rmesa
->state
.color
.roundEnable
;
2020 R200_STATECHANGE(rmesa
, ctx
);
2022 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_FOG_ENABLE
;
2023 r200Fogfv( ctx
, GL_FOG_MODE
, NULL
);
2025 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_FOG_ENABLE
;
2026 R200_STATECHANGE(rmesa
, tcl
);
2027 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_TCL_FOG_MASK
;
2029 r200UpdateSpecular( ctx
); /* for PK_SPEC */
2030 if (rmesa
->TclFallback
)
2031 r200ChooseVertexState( ctx
);
2032 _mesa_allow_light_in_model( ctx
, !state
);
2043 R200_STATECHANGE(rmesa
, tcl
);
2044 p
= cap
- GL_LIGHT0
;
2046 flag
= (R200_LIGHT_1_ENABLE
|
2047 R200_LIGHT_1_ENABLE_AMBIENT
|
2048 R200_LIGHT_1_ENABLE_SPECULAR
);
2050 flag
= (R200_LIGHT_0_ENABLE
|
2051 R200_LIGHT_0_ENABLE_AMBIENT
|
2052 R200_LIGHT_0_ENABLE_SPECULAR
);
2055 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] |= flag
;
2057 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] &= ~flag
;
2061 update_light_colors( ctx
, p
);
2065 r200UpdateSpecular(ctx
);
2066 /* for reflection map fixup - might set recheck_texgen for all units too */
2067 rmesa
->NewGLState
|= _NEW_TEXTURE
;
2070 case GL_LINE_SMOOTH
:
2071 R200_STATECHANGE( rmesa
, ctx
);
2073 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_LINE
;
2075 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_LINE
;
2079 case GL_LINE_STIPPLE
:
2080 R200_STATECHANGE( rmesa
, set
);
2082 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_PATTERN_ENABLE
;
2084 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_PATTERN_ENABLE
;
2089 R200_STATECHANGE( rmesa
, tcl
);
2091 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_NORMALIZE_NORMALS
;
2093 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_NORMALIZE_NORMALS
;
2097 /* Pointsize registers on r200 only work for point sprites, and point smooth
2098 * doesn't work for point sprites (and isn't needed for 1.0 sized aa points).
2099 * In any case, setting pointmin == pointsizemax == 1.0 for aa points
2100 * is enough to satisfy conform.
2102 case GL_POINT_SMOOTH
:
2105 /* These don't really do anything, as we don't use the 3vtx
2109 case GL_POLYGON_OFFSET_POINT
:
2110 R200_STATECHANGE( rmesa
, set
);
2112 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_POINT
;
2114 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_POINT
;
2118 case GL_POLYGON_OFFSET_LINE
:
2119 R200_STATECHANGE( rmesa
, set
);
2121 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_LINE
;
2123 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_LINE
;
2128 case GL_POINT_SPRITE_ARB
:
2129 R200_STATECHANGE( rmesa
, spr
);
2132 for (i
= 0; i
< 6; i
++) {
2133 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |=
2134 ctx
->Point
.CoordReplace
[i
] << (R200_PS_GEN_TEX_0_SHIFT
+ i
);
2137 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] &= ~R200_PS_GEN_TEX_MASK
;
2141 case GL_POLYGON_OFFSET_FILL
:
2142 R200_STATECHANGE( rmesa
, set
);
2144 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_TRI
;
2146 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_TRI
;
2150 case GL_POLYGON_SMOOTH
:
2151 R200_STATECHANGE( rmesa
, ctx
);
2153 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_POLY
;
2155 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_POLY
;
2159 case GL_POLYGON_STIPPLE
:
2160 R200_STATECHANGE(rmesa
, set
);
2162 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_STIPPLE_ENABLE
;
2164 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_STIPPLE_ENABLE
;
2168 case GL_RESCALE_NORMAL_EXT
: {
2169 GLboolean tmp
= ctx
->_NeedEyeCoords
? state
: !state
;
2170 R200_STATECHANGE( rmesa
, tcl
);
2172 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
2174 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
2179 case GL_SCISSOR_TEST
:
2180 R200_FIREVERTICES( rmesa
);
2181 rmesa
->state
.scissor
.enabled
= state
;
2182 r200UpdateScissor( ctx
);
2185 case GL_STENCIL_TEST
:
2186 if ( rmesa
->state
.stencil
.hwBuffer
) {
2187 R200_STATECHANGE( rmesa
, ctx
);
2189 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_STENCIL_ENABLE
;
2191 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_STENCIL_ENABLE
;
2194 FALLBACK( rmesa
, R200_FALLBACK_STENCIL
, state
);
2198 case GL_TEXTURE_GEN_Q
:
2199 case GL_TEXTURE_GEN_R
:
2200 case GL_TEXTURE_GEN_S
:
2201 case GL_TEXTURE_GEN_T
:
2202 /* Picked up in r200UpdateTextureState.
2204 rmesa
->recheck_texgen
[ctx
->Texture
.CurrentUnit
] = GL_TRUE
;
2207 case GL_COLOR_SUM_EXT
:
2208 r200UpdateSpecular ( ctx
);
2211 case GL_VERTEX_PROGRAM_ARB
:
2214 rmesa
->curr_vp_hw
= NULL
;
2215 R200_STATECHANGE( rmesa
, vap
);
2216 rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
] &= ~R200_VAP_PROG_VTX_SHADER_ENABLE
;
2217 /* mark all tcl atoms (tcl vector state got overwritten) dirty
2218 not sure about tcl scalar state - we need at least grd
2219 with vert progs too.
2220 ucp looks like it doesn't get overwritten (may even work
2221 with vp for pos-invariant progs if we're lucky) */
2222 R200_STATECHANGE( rmesa
, mtl
[0] );
2223 R200_STATECHANGE( rmesa
, mtl
[1] );
2224 R200_STATECHANGE( rmesa
, fog
);
2225 R200_STATECHANGE( rmesa
, glt
);
2226 R200_STATECHANGE( rmesa
, eye
);
2227 for (i
= R200_MTX_MV
; i
<= R200_MTX_TEX5
; i
++) {
2228 R200_STATECHANGE( rmesa
, mat
[i
] );
2230 for (i
= 0 ; i
< 8; i
++) {
2231 R200_STATECHANGE( rmesa
, lit
[i
] );
2233 R200_STATECHANGE( rmesa
, tcl
);
2234 for (i
= 0; i
<= ctx
->Const
.MaxClipPlanes
; i
++) {
2235 if (ctx
->Transform
.ClipPlanesEnabled
& (1 << i
)) {
2236 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= (R200_UCP_ENABLE_0
<< i
);
2239 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0 << i);
2242 /* ugly. Need to call everything which might change compsel. */
2243 r200UpdateSpecular( ctx
);
2245 /* shouldn't be necessary, as it's picked up anyway in r200ValidateState (_NEW_PROGRAM),
2246 but without it doom3 locks up at always the same places. Why? */
2247 /* FIXME: This can (and should) be replaced by a call to the TCL_STATE_FLUSH reg before
2248 accessing VAP_SE_VAP_CNTL. Requires drm changes (done). Remove after some time... */
2249 r200UpdateTextureState( ctx
);
2250 /* if we call r200UpdateTextureState we need the code below because we are calling it with
2251 non-current derived enabled values which may revert the state atoms for frag progs even when
2252 they already got disabled... ugh
2253 Should really figure out why we need to call r200UpdateTextureState in the first place */
2255 for (unit
= 0; unit
< R200_MAX_TEXTURE_UNITS
; unit
++) {
2256 R200_STATECHANGE( rmesa
, pix
[unit
] );
2257 R200_STATECHANGE( rmesa
, tex
[unit
] );
2258 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] &=
2259 ~(R200_TXFORMAT_ST_ROUTE_MASK
| R200_TXFORMAT_LOOKUP_DISABLE
);
2260 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] |= unit
<< R200_TXFORMAT_ST_ROUTE_SHIFT
;
2261 /* need to guard this with drmSupportsFragmentShader? Should never get here if
2262 we don't announce ATI_fs, right? */
2263 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXMULTI_CTL
] = 0;
2265 R200_STATECHANGE( rmesa
, cst
);
2266 R200_STATECHANGE( rmesa
, tf
);
2267 rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] = 0;
2271 /* picked up later */
2273 /* call functions which change hw state based on ARB_vp enabled or not. */
2274 r200PointParameter( ctx
, GL_POINT_DISTANCE_ATTENUATION
, NULL
);
2275 r200Fogfv( ctx
, GL_FOG_COORD_SRC
, NULL
);
2278 case GL_VERTEX_PROGRAM_POINT_SIZE_ARB
:
2279 r200PointParameter( ctx
, GL_POINT_DISTANCE_ATTENUATION
, NULL
);
2282 case GL_FRAGMENT_SHADER_ATI
:
2284 /* restore normal tex env colors and make sure tex env combine will get updated
2285 mark env atoms dirty (as their data was overwritten by afs even
2286 if they didn't change) and restore tex coord routing */
2288 for (unit
= 0; unit
< R200_MAX_TEXTURE_UNITS
; unit
++) {
2289 R200_STATECHANGE( rmesa
, pix
[unit
] );
2290 R200_STATECHANGE( rmesa
, tex
[unit
] );
2291 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] &=
2292 ~(R200_TXFORMAT_ST_ROUTE_MASK
| R200_TXFORMAT_LOOKUP_DISABLE
);
2293 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] |= unit
<< R200_TXFORMAT_ST_ROUTE_SHIFT
;
2294 /* need to guard this with drmSupportsFragmentShader? Should never get here if
2295 we don't announce ATI_fs, right? */
2296 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXMULTI_CTL
] = 0;
2298 R200_STATECHANGE( rmesa
, cst
);
2299 R200_STATECHANGE( rmesa
, tf
);
2300 rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] = 0;
2303 /* need to mark this dirty as pix/tf atoms have overwritten the data
2304 even if the data in the atoms didn't change */
2305 R200_STATECHANGE( rmesa
, atf
);
2306 R200_STATECHANGE( rmesa
, afs
[1] );
2307 /* everything else picked up in r200UpdateTextureState hopefully */
2316 void r200LightingSpaceChange( GLcontext
*ctx
)
2318 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2321 if (R200_DEBUG
& DEBUG_STATE
)
2322 fprintf(stderr
, "%s %d BEFORE %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
2323 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
2325 if (ctx
->_NeedEyeCoords
)
2326 tmp
= ctx
->Transform
.RescaleNormals
;
2328 tmp
= !ctx
->Transform
.RescaleNormals
;
2330 R200_STATECHANGE( rmesa
, tcl
);
2332 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
2334 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
2337 if (R200_DEBUG
& DEBUG_STATE
)
2338 fprintf(stderr
, "%s %d AFTER %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
2339 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
2342 /* =============================================================
2343 * Deferred state management - matrices, textures, other?
2349 static void upload_matrix( r200ContextPtr rmesa
, GLfloat
*src
, int idx
)
2351 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
2355 for (i
= 0 ; i
< 4 ; i
++) {
2359 *dest
++ = src
[i
+12];
2362 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
2365 static void upload_matrix_t( r200ContextPtr rmesa
, const GLfloat
*src
, int idx
)
2367 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
2368 memcpy(dest
, src
, 16*sizeof(float));
2369 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
2373 static void update_texturematrix( GLcontext
*ctx
)
2375 r200ContextPtr rmesa
= R200_CONTEXT( ctx
);
2376 GLuint tpc
= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
];
2377 GLuint compsel
= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
];
2380 if (R200_DEBUG
& DEBUG_STATE
)
2381 fprintf(stderr
, "%s before COMPSEL: %x\n", __FUNCTION__
,
2382 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]);
2384 rmesa
->TexMatEnabled
= 0;
2385 rmesa
->TexMatCompSel
= 0;
2387 for (unit
= 0 ; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
2388 if (!ctx
->Texture
.Unit
[unit
]._ReallyEnabled
)
2391 if (ctx
->TextureMatrixStack
[unit
].Top
->type
!= MATRIX_IDENTITY
) {
2392 rmesa
->TexMatEnabled
|= (R200_TEXGEN_TEXMAT_0_ENABLE
|
2393 R200_TEXMAT_0_ENABLE
) << unit
;
2395 rmesa
->TexMatCompSel
|= R200_OUTPUT_TEX_0
<< unit
;
2397 if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2398 /* Need to preconcatenate any active texgen
2399 * obj/eyeplane matrices:
2401 _math_matrix_mul_matrix( &rmesa
->tmpmat
,
2402 ctx
->TextureMatrixStack
[unit
].Top
,
2403 &rmesa
->TexGenMatrix
[unit
] );
2404 upload_matrix( rmesa
, rmesa
->tmpmat
.m
, R200_MTX_TEX0
+unit
);
2407 upload_matrix( rmesa
, ctx
->TextureMatrixStack
[unit
].Top
->m
,
2408 R200_MTX_TEX0
+unit
);
2411 else if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2412 upload_matrix( rmesa
, rmesa
->TexGenMatrix
[unit
].m
,
2413 R200_MTX_TEX0
+unit
);
2417 tpc
= (rmesa
->TexMatEnabled
| rmesa
->TexGenEnabled
);
2418 if (tpc
!= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
]) {
2419 R200_STATECHANGE(rmesa
, tcg
);
2420 rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
] = tpc
;
2423 compsel
&= ~R200_OUTPUT_TEX_MASK
;
2424 compsel
|= rmesa
->TexMatCompSel
| rmesa
->TexGenCompSel
;
2425 if (compsel
!= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]) {
2426 R200_STATECHANGE(rmesa
, vtx
);
2427 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] = compsel
;
2434 * Tell the card where to render (offset, pitch).
2435 * Effected by glDrawBuffer, etc
2438 r200UpdateDrawBuffer(GLcontext
*ctx
)
2440 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2441 struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
2442 driRenderbuffer
*drb
;
2444 if (fb
->_ColorDrawBufferMask
[0] == BUFFER_BIT_FRONT_LEFT
) {
2446 drb
= (driRenderbuffer
*) fb
->Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
;
2448 else if (fb
->_ColorDrawBufferMask
[0] == BUFFER_BIT_BACK_LEFT
) {
2450 drb
= (driRenderbuffer
*) fb
->Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
;
2453 /* drawing to multiple buffers, or none */
2458 assert(drb
->flippedPitch
);
2460 R200_STATECHANGE( rmesa
, ctx
);
2462 /* Note: we used the (possibly) page-flipped values */
2463 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLOROFFSET
]
2464 = ((drb
->flippedOffset
+ rmesa
->r200Screen
->fbLocation
)
2465 & R200_COLOROFFSET_MASK
);
2466 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLORPITCH
] = drb
->flippedPitch
;
2467 if (rmesa
->sarea
->tiling_enabled
) {
2468 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLORPITCH
] |= R200_COLOR_TILE_ENABLE
;
2474 void r200ValidateState( GLcontext
*ctx
)
2476 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2477 GLuint new_state
= rmesa
->NewGLState
;
2479 if (new_state
& (_NEW_BUFFERS
| _NEW_COLOR
| _NEW_PIXEL
)) {
2480 r200UpdateDrawBuffer(ctx
);
2483 if (new_state
& (_NEW_TEXTURE
| _NEW_PROGRAM
)) {
2484 r200UpdateTextureState( ctx
);
2485 new_state
|= rmesa
->NewGLState
; /* may add TEXTURE_MATRIX */
2486 r200UpdateLocalViewer( ctx
);
2489 /* FIXME: don't really need most of these when vertex progs are enabled */
2491 /* Need an event driven matrix update?
2493 if (new_state
& (_NEW_MODELVIEW
|_NEW_PROJECTION
))
2494 upload_matrix( rmesa
, ctx
->_ModelProjectMatrix
.m
, R200_MTX_MVP
);
2496 /* Need these for lighting (shouldn't upload otherwise)
2498 if (new_state
& (_NEW_MODELVIEW
)) {
2499 upload_matrix( rmesa
, ctx
->ModelviewMatrixStack
.Top
->m
, R200_MTX_MV
);
2500 upload_matrix_t( rmesa
, ctx
->ModelviewMatrixStack
.Top
->inv
, R200_MTX_IMV
);
2503 /* Does this need to be triggered on eg. modelview for
2504 * texgen-derived objplane/eyeplane matrices?
2506 if (new_state
& (_NEW_TEXTURE
|_NEW_TEXTURE_MATRIX
)) {
2507 update_texturematrix( ctx
);
2510 if (new_state
& (_NEW_LIGHT
|_NEW_MODELVIEW
|_MESA_NEW_NEED_EYE_COORDS
)) {
2511 update_light( ctx
);
2514 /* emit all active clip planes if projection matrix changes.
2516 if (new_state
& (_NEW_PROJECTION
)) {
2517 if (ctx
->Transform
.ClipPlanesEnabled
)
2518 r200UpdateClipPlanes( ctx
);
2521 if (new_state
& (_NEW_PROGRAM
|
2522 /* need to test for pretty much anything due to possible parameter bindings */
2523 _NEW_MODELVIEW
|_NEW_PROJECTION
|_NEW_TRANSFORM
|
2524 _NEW_LIGHT
|_NEW_TEXTURE
|_NEW_TEXTURE_MATRIX
|
2525 _NEW_FOG
|_NEW_POINT
|_NEW_TRACK_MATRIX
)) {
2526 if (ctx
->VertexProgram
._Enabled
) {
2527 r200SetupVertexProg( ctx
);
2529 else TCL_FALLBACK(ctx
, R200_TCL_FALLBACK_VERTEX_PROGRAM
, 0);
2532 rmesa
->NewGLState
= 0;
2536 static void r200InvalidateState( GLcontext
*ctx
, GLuint new_state
)
2538 _swrast_InvalidateState( ctx
, new_state
);
2539 _swsetup_InvalidateState( ctx
, new_state
);
2540 _vbo_InvalidateState( ctx
, new_state
);
2541 _tnl_InvalidateState( ctx
, new_state
);
2542 _ae_invalidate_state( ctx
, new_state
);
2543 R200_CONTEXT(ctx
)->NewGLState
|= new_state
;
2546 /* A hack. The r200 can actually cope just fine with materials
2547 * between begin/ends, so fix this.
2548 * Should map to inputs just like the generic vertex arrays for vertex progs.
2549 * In theory there could still be too many and we'd still need a fallback.
2551 static GLboolean
check_material( GLcontext
*ctx
)
2553 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
2556 for (i
= _TNL_ATTRIB_MAT_FRONT_AMBIENT
;
2557 i
< _TNL_ATTRIB_MAT_BACK_INDEXES
;
2559 if (tnl
->vb
.AttribPtr
[i
] &&
2560 tnl
->vb
.AttribPtr
[i
]->stride
)
2566 static void r200WrapRunPipeline( GLcontext
*ctx
)
2568 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2569 GLboolean has_material
;
2572 fprintf(stderr
, "%s, newstate: %x\n", __FUNCTION__
, rmesa
->NewGLState
);
2576 if (rmesa
->NewGLState
)
2577 r200ValidateState( ctx
);
2579 has_material
= !ctx
->VertexProgram
._Enabled
&& ctx
->Light
.Enabled
&& check_material( ctx
);
2582 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_TRUE
);
2585 /* Run the pipeline.
2587 _tnl_run_pipeline( ctx
);
2590 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_FALSE
);
2595 /* Initialize the driver's state functions.
2597 void r200InitStateFuncs( struct dd_function_table
*functions
)
2599 functions
->UpdateState
= r200InvalidateState
;
2600 functions
->LightingSpaceChange
= r200LightingSpaceChange
;
2602 functions
->DrawBuffer
= r200DrawBuffer
;
2603 functions
->ReadBuffer
= r200ReadBuffer
;
2605 functions
->AlphaFunc
= r200AlphaFunc
;
2606 functions
->BlendColor
= r200BlendColor
;
2607 functions
->BlendEquationSeparate
= r200BlendEquationSeparate
;
2608 functions
->BlendFuncSeparate
= r200BlendFuncSeparate
;
2609 functions
->ClearColor
= r200ClearColor
;
2610 functions
->ClearDepth
= r200ClearDepth
;
2611 functions
->ClearIndex
= NULL
;
2612 functions
->ClearStencil
= r200ClearStencil
;
2613 functions
->ClipPlane
= r200ClipPlane
;
2614 functions
->ColorMask
= r200ColorMask
;
2615 functions
->CullFace
= r200CullFace
;
2616 functions
->DepthFunc
= r200DepthFunc
;
2617 functions
->DepthMask
= r200DepthMask
;
2618 functions
->DepthRange
= r200DepthRange
;
2619 functions
->Enable
= r200Enable
;
2620 functions
->Fogfv
= r200Fogfv
;
2621 functions
->FrontFace
= r200FrontFace
;
2622 functions
->Hint
= NULL
;
2623 functions
->IndexMask
= NULL
;
2624 functions
->LightModelfv
= r200LightModelfv
;
2625 functions
->Lightfv
= r200Lightfv
;
2626 functions
->LineStipple
= r200LineStipple
;
2627 functions
->LineWidth
= r200LineWidth
;
2628 functions
->LogicOpcode
= r200LogicOpCode
;
2629 functions
->PolygonMode
= r200PolygonMode
;
2630 functions
->PolygonOffset
= r200PolygonOffset
;
2631 functions
->PolygonStipple
= r200PolygonStipple
;
2632 functions
->PointParameterfv
= r200PointParameter
;
2633 functions
->PointSize
= r200PointSize
;
2634 functions
->RenderMode
= r200RenderMode
;
2635 functions
->Scissor
= r200Scissor
;
2636 functions
->ShadeModel
= r200ShadeModel
;
2637 functions
->StencilFuncSeparate
= r200StencilFuncSeparate
;
2638 functions
->StencilMaskSeparate
= r200StencilMaskSeparate
;
2639 functions
->StencilOpSeparate
= r200StencilOpSeparate
;
2640 functions
->Viewport
= r200Viewport
;
2644 void r200InitTnlFuncs( GLcontext
*ctx
)
2646 TNL_CONTEXT(ctx
)->Driver
.NotifyMaterialChange
= r200UpdateMaterial
;
2647 TNL_CONTEXT(ctx
)->Driver
.RunPipeline
= r200WrapRunPipeline
;