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"
44 #include "swrast/swrast.h"
45 #include "array_cache/acache.h"
47 #include "tnl/t_pipeline.h"
48 #include "swrast_setup/swrast_setup.h"
50 #include "r200_context.h"
51 #include "r200_ioctl.h"
52 #include "r200_state.h"
55 #include "r200_swtcl.h"
56 #include "r200_vtxfmt.h"
58 #include "drirenderbuffer.h"
61 /* =============================================================
65 static void r200AlphaFunc( GLcontext
*ctx
, GLenum func
, GLfloat ref
)
67 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
68 int pp_misc
= rmesa
->hw
.ctx
.cmd
[CTX_PP_MISC
];
71 CLAMPED_FLOAT_TO_UBYTE(refByte
, ref
);
73 R200_STATECHANGE( rmesa
, ctx
);
75 pp_misc
&= ~(R200_ALPHA_TEST_OP_MASK
| R200_REF_ALPHA_MASK
);
76 pp_misc
|= (refByte
& R200_REF_ALPHA_MASK
);
80 pp_misc
|= R200_ALPHA_TEST_FAIL
;
83 pp_misc
|= R200_ALPHA_TEST_LESS
;
86 pp_misc
|= R200_ALPHA_TEST_EQUAL
;
89 pp_misc
|= R200_ALPHA_TEST_LEQUAL
;
92 pp_misc
|= R200_ALPHA_TEST_GREATER
;
95 pp_misc
|= R200_ALPHA_TEST_NEQUAL
;
98 pp_misc
|= R200_ALPHA_TEST_GEQUAL
;
101 pp_misc
|= R200_ALPHA_TEST_PASS
;
105 rmesa
->hw
.ctx
.cmd
[CTX_PP_MISC
] = pp_misc
;
108 static void r200BlendColor( GLcontext
*ctx
, const GLfloat cf
[4] )
111 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
112 R200_STATECHANGE( rmesa
, ctx
);
113 CLAMPED_FLOAT_TO_UBYTE(color
[0], cf
[0]);
114 CLAMPED_FLOAT_TO_UBYTE(color
[1], cf
[1]);
115 CLAMPED_FLOAT_TO_UBYTE(color
[2], cf
[2]);
116 CLAMPED_FLOAT_TO_UBYTE(color
[3], cf
[3]);
117 if (rmesa
->r200Screen
->drmSupportsBlendColor
)
118 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCOLOR
] = r200PackColor( 4, color
[0], color
[1], color
[2], color
[3] );
122 * Calculate the hardware blend factor setting. This same function is used
123 * for source and destination of both alpha and RGB.
126 * The hardware register value for the specified blend factor. This value
127 * will need to be shifted into the correct position for either source or
128 * destination factor.
131 * Since the two cases where source and destination are handled differently
132 * are essentially error cases, they should never happen. Determine if these
133 * cases can be removed.
135 static int blend_factor( GLenum factor
, GLboolean is_src
)
141 func
= R200_BLEND_GL_ZERO
;
144 func
= R200_BLEND_GL_ONE
;
147 func
= R200_BLEND_GL_DST_COLOR
;
149 case GL_ONE_MINUS_DST_COLOR
:
150 func
= R200_BLEND_GL_ONE_MINUS_DST_COLOR
;
153 func
= R200_BLEND_GL_SRC_COLOR
;
155 case GL_ONE_MINUS_SRC_COLOR
:
156 func
= R200_BLEND_GL_ONE_MINUS_SRC_COLOR
;
159 func
= R200_BLEND_GL_SRC_ALPHA
;
161 case GL_ONE_MINUS_SRC_ALPHA
:
162 func
= R200_BLEND_GL_ONE_MINUS_SRC_ALPHA
;
165 func
= R200_BLEND_GL_DST_ALPHA
;
167 case GL_ONE_MINUS_DST_ALPHA
:
168 func
= R200_BLEND_GL_ONE_MINUS_DST_ALPHA
;
170 case GL_SRC_ALPHA_SATURATE
:
171 func
= (is_src
) ? R200_BLEND_GL_SRC_ALPHA_SATURATE
: R200_BLEND_GL_ZERO
;
173 case GL_CONSTANT_COLOR
:
174 func
= R200_BLEND_GL_CONST_COLOR
;
176 case GL_ONE_MINUS_CONSTANT_COLOR
:
177 func
= R200_BLEND_GL_ONE_MINUS_CONST_COLOR
;
179 case GL_CONSTANT_ALPHA
:
180 func
= R200_BLEND_GL_CONST_ALPHA
;
182 case GL_ONE_MINUS_CONSTANT_ALPHA
:
183 func
= R200_BLEND_GL_ONE_MINUS_CONST_ALPHA
;
186 func
= (is_src
) ? R200_BLEND_GL_ONE
: R200_BLEND_GL_ZERO
;
192 * Sets both the blend equation and the blend function.
193 * This is done in a single
194 * function because some blend equations (i.e., \c GL_MIN and \c GL_MAX)
195 * change the interpretation of the blend function.
196 * Also, make sure that blend function and blend equation are set to their default
197 * value if color blending is not enabled, since at least blend equations GL_MIN
198 * and GL_FUNC_REVERSE_SUBTRACT will cause wrong results otherwise for
201 static void r200_set_blend_state( GLcontext
* ctx
)
203 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
204 GLuint cntl
= rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &
205 ~(R200_ROP_ENABLE
| R200_ALPHA_BLEND_ENABLE
| R200_SEPARATE_ALPHA_ENABLE
);
207 int func
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
208 (R200_BLEND_GL_ZERO
<< R200_DST_BLEND_SHIFT
);
209 int eqn
= R200_COMB_FCN_ADD_CLAMP
;
210 int funcA
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
211 (R200_BLEND_GL_ZERO
<< R200_DST_BLEND_SHIFT
);
212 int eqnA
= R200_COMB_FCN_ADD_CLAMP
;
214 R200_STATECHANGE( rmesa
, ctx
);
216 if (rmesa
->r200Screen
->drmSupportsBlendColor
) {
217 if (ctx
->Color
._LogicOpEnabled
) {
218 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
| R200_ROP_ENABLE
;
219 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ABLENDCNTL
] = eqn
| func
;
220 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CBLENDCNTL
] = eqn
| func
;
222 } else if (ctx
->Color
.BlendEnabled
) {
223 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
| R200_ALPHA_BLEND_ENABLE
| R200_SEPARATE_ALPHA_ENABLE
;
226 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
;
227 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ABLENDCNTL
] = eqn
| func
;
228 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CBLENDCNTL
] = eqn
| func
;
233 if (ctx
->Color
._LogicOpEnabled
) {
234 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
| R200_ROP_ENABLE
;
235 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] = eqn
| func
;
237 } else if (ctx
->Color
.BlendEnabled
) {
238 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
| R200_ALPHA_BLEND_ENABLE
;
241 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
;
242 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] = eqn
| func
;
247 func
= (blend_factor( ctx
->Color
.BlendSrcRGB
, GL_TRUE
) << R200_SRC_BLEND_SHIFT
) |
248 (blend_factor( ctx
->Color
.BlendDstRGB
, GL_FALSE
) << R200_DST_BLEND_SHIFT
);
250 switch(ctx
->Color
.BlendEquationRGB
) {
252 eqn
= R200_COMB_FCN_ADD_CLAMP
;
255 case GL_FUNC_SUBTRACT
:
256 eqn
= R200_COMB_FCN_SUB_CLAMP
;
259 case GL_FUNC_REVERSE_SUBTRACT
:
260 eqn
= R200_COMB_FCN_RSUB_CLAMP
;
264 eqn
= R200_COMB_FCN_MIN
;
265 func
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
266 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
270 eqn
= R200_COMB_FCN_MAX
;
271 func
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
272 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
276 fprintf( stderr
, "[%s:%u] Invalid RGB blend equation (0x%04x).\n",
277 __FUNCTION__
, __LINE__
, ctx
->Color
.BlendEquationRGB
);
281 if (!rmesa
->r200Screen
->drmSupportsBlendColor
) {
282 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] = eqn
| func
;
286 funcA
= (blend_factor( ctx
->Color
.BlendSrcA
, GL_TRUE
) << R200_SRC_BLEND_SHIFT
) |
287 (blend_factor( ctx
->Color
.BlendDstA
, GL_FALSE
) << R200_DST_BLEND_SHIFT
);
289 switch(ctx
->Color
.BlendEquationA
) {
291 eqnA
= R200_COMB_FCN_ADD_CLAMP
;
294 case GL_FUNC_SUBTRACT
:
295 eqnA
= R200_COMB_FCN_SUB_CLAMP
;
298 case GL_FUNC_REVERSE_SUBTRACT
:
299 eqnA
= R200_COMB_FCN_RSUB_CLAMP
;
303 eqnA
= R200_COMB_FCN_MIN
;
304 funcA
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
305 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
309 eqnA
= R200_COMB_FCN_MAX
;
310 funcA
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
311 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
315 fprintf( stderr
, "[%s:%u] Invalid A blend equation (0x%04x).\n",
316 __FUNCTION__
, __LINE__
, ctx
->Color
.BlendEquationA
);
320 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ABLENDCNTL
] = eqnA
| funcA
;
321 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CBLENDCNTL
] = eqn
| func
;
325 static void r200BlendEquationSeparate( GLcontext
*ctx
,
326 GLenum modeRGB
, GLenum modeA
)
328 r200_set_blend_state( ctx
);
331 static void r200BlendFuncSeparate( GLcontext
*ctx
,
332 GLenum sfactorRGB
, GLenum dfactorRGB
,
333 GLenum sfactorA
, GLenum dfactorA
)
335 r200_set_blend_state( ctx
);
339 /* =============================================================
343 static void r200DepthFunc( GLcontext
*ctx
, GLenum func
)
345 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
347 R200_STATECHANGE( rmesa
, ctx
);
348 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_Z_TEST_MASK
;
350 switch ( ctx
->Depth
.Func
) {
352 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_NEVER
;
355 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_LESS
;
358 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_EQUAL
;
361 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_LEQUAL
;
364 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_GREATER
;
367 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_NEQUAL
;
370 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_GEQUAL
;
373 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_ALWAYS
;
378 static void r200ClearDepth( GLcontext
*ctx
, GLclampd d
)
380 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
381 GLuint format
= (rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &
382 R200_DEPTH_FORMAT_MASK
);
385 case R200_DEPTH_FORMAT_16BIT_INT_Z
:
386 rmesa
->state
.depth
.clear
= d
* 0x0000ffff;
388 case R200_DEPTH_FORMAT_24BIT_INT_Z
:
389 rmesa
->state
.depth
.clear
= d
* 0x00ffffff;
394 static void r200DepthMask( GLcontext
*ctx
, GLboolean flag
)
396 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
397 R200_STATECHANGE( rmesa
, ctx
);
399 if ( ctx
->Depth
.Mask
) {
400 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_WRITE_ENABLE
;
402 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_Z_WRITE_ENABLE
;
407 /* =============================================================
412 static void r200Fogfv( GLcontext
*ctx
, GLenum pname
, const GLfloat
*param
)
414 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
415 union { int i
; float f
; } c
, d
;
419 c
.i
= rmesa
->hw
.fog
.cmd
[FOG_C
];
420 d
.i
= rmesa
->hw
.fog
.cmd
[FOG_D
];
424 if (!ctx
->Fog
.Enabled
)
426 R200_STATECHANGE(rmesa
, tcl
);
427 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_TCL_FOG_MASK
;
428 switch (ctx
->Fog
.Mode
) {
430 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_LINEAR
;
431 if (ctx
->Fog
.Start
== ctx
->Fog
.End
) {
436 c
.f
= ctx
->Fog
.End
/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
437 d
.f
= -1.0/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
441 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_EXP
;
443 d
.f
= -ctx
->Fog
.Density
;
446 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_EXP2
;
448 d
.f
= -(ctx
->Fog
.Density
* ctx
->Fog
.Density
);
455 switch (ctx
->Fog
.Mode
) {
458 d
.f
= -ctx
->Fog
.Density
;
462 d
.f
= -(ctx
->Fog
.Density
* ctx
->Fog
.Density
);
470 if (ctx
->Fog
.Mode
== GL_LINEAR
) {
471 if (ctx
->Fog
.Start
== ctx
->Fog
.End
) {
475 c
.f
= ctx
->Fog
.End
/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
476 d
.f
= -1.0/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
481 R200_STATECHANGE( rmesa
, ctx
);
482 UNCLAMPED_FLOAT_TO_RGB_CHAN( col
, ctx
->Fog
.Color
);
483 i
= r200PackColor( 4, col
[0], col
[1], col
[2], 0 );
484 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] &= ~R200_FOG_COLOR_MASK
;
485 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] |= i
;
487 case GL_FOG_COORD_SRC
: {
488 GLuint fmt_0
= rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_0
];
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
) {
494 fog
|= R200_FOG_USE_VTX_FOG
;
495 fmt_0
|= R200_VTX_DISCRETE_FOG
;
496 out_0
|= R200_VTX_DISCRETE_FOG
;
499 fog
|= R200_FOG_USE_SPEC_ALPHA
;
500 fmt_0
&= ~R200_VTX_DISCRETE_FOG
;
501 out_0
&= ~R200_VTX_DISCRETE_FOG
;
504 if ( fog
!= rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] ) {
505 R200_STATECHANGE( rmesa
, ctx
);
506 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] = fog
;
509 if ( (fmt_0
!= rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_0
])
510 || (out_0
!= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
])) {
511 R200_STATECHANGE( rmesa
, vtx
);
512 rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_0
] = fmt_0
;
513 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] = out_0
;
522 if (c
.i
!= rmesa
->hw
.fog
.cmd
[FOG_C
] || d
.i
!= rmesa
->hw
.fog
.cmd
[FOG_D
]) {
523 R200_STATECHANGE( rmesa
, fog
);
524 rmesa
->hw
.fog
.cmd
[FOG_C
] = c
.i
;
525 rmesa
->hw
.fog
.cmd
[FOG_D
] = d
.i
;
530 /* =============================================================
535 static GLboolean
intersect_rect( drm_clip_rect_t
*out
,
540 if ( b
->x1
> out
->x1
) out
->x1
= b
->x1
;
541 if ( b
->y1
> out
->y1
) out
->y1
= b
->y1
;
542 if ( b
->x2
< out
->x2
) out
->x2
= b
->x2
;
543 if ( b
->y2
< out
->y2
) out
->y2
= b
->y2
;
544 if ( out
->x1
>= out
->x2
) return GL_FALSE
;
545 if ( out
->y1
>= out
->y2
) return GL_FALSE
;
550 void r200RecalcScissorRects( r200ContextPtr rmesa
)
552 drm_clip_rect_t
*out
;
555 /* Grow cliprect store?
557 if (rmesa
->state
.scissor
.numAllocedClipRects
< rmesa
->numClipRects
) {
558 while (rmesa
->state
.scissor
.numAllocedClipRects
< rmesa
->numClipRects
) {
559 rmesa
->state
.scissor
.numAllocedClipRects
+= 1; /* zero case */
560 rmesa
->state
.scissor
.numAllocedClipRects
*= 2;
563 if (rmesa
->state
.scissor
.pClipRects
)
564 FREE(rmesa
->state
.scissor
.pClipRects
);
566 rmesa
->state
.scissor
.pClipRects
=
567 MALLOC( rmesa
->state
.scissor
.numAllocedClipRects
*
568 sizeof(drm_clip_rect_t
) );
570 if ( rmesa
->state
.scissor
.pClipRects
== NULL
) {
571 rmesa
->state
.scissor
.numAllocedClipRects
= 0;
576 out
= rmesa
->state
.scissor
.pClipRects
;
577 rmesa
->state
.scissor
.numClipRects
= 0;
579 for ( i
= 0 ; i
< rmesa
->numClipRects
; i
++ ) {
580 if ( intersect_rect( out
,
581 &rmesa
->pClipRects
[i
],
582 &rmesa
->state
.scissor
.rect
) ) {
583 rmesa
->state
.scissor
.numClipRects
++;
590 static void r200UpdateScissor( GLcontext
*ctx
)
592 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
594 if ( rmesa
->dri
.drawable
) {
595 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
597 int x
= ctx
->Scissor
.X
;
598 int y
= dPriv
->h
- ctx
->Scissor
.Y
- ctx
->Scissor
.Height
;
599 int w
= ctx
->Scissor
.X
+ ctx
->Scissor
.Width
- 1;
600 int h
= dPriv
->h
- ctx
->Scissor
.Y
- 1;
602 rmesa
->state
.scissor
.rect
.x1
= x
+ dPriv
->x
;
603 rmesa
->state
.scissor
.rect
.y1
= y
+ dPriv
->y
;
604 rmesa
->state
.scissor
.rect
.x2
= w
+ dPriv
->x
+ 1;
605 rmesa
->state
.scissor
.rect
.y2
= h
+ dPriv
->y
+ 1;
607 r200RecalcScissorRects( rmesa
);
612 static void r200Scissor( GLcontext
*ctx
,
613 GLint x
, GLint y
, GLsizei w
, GLsizei h
)
615 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
617 if ( ctx
->Scissor
.Enabled
) {
618 R200_FIREVERTICES( rmesa
); /* don't pipeline cliprect changes */
619 r200UpdateScissor( ctx
);
625 /* =============================================================
629 static void r200CullFace( GLcontext
*ctx
, GLenum unused
)
631 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
632 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
633 GLuint t
= rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
];
635 s
|= R200_FFACE_SOLID
| R200_BFACE_SOLID
;
636 t
&= ~(R200_CULL_FRONT
| R200_CULL_BACK
);
638 if ( ctx
->Polygon
.CullFlag
) {
639 switch ( ctx
->Polygon
.CullFaceMode
) {
641 s
&= ~R200_FFACE_SOLID
;
642 t
|= R200_CULL_FRONT
;
645 s
&= ~R200_BFACE_SOLID
;
648 case GL_FRONT_AND_BACK
:
649 s
&= ~(R200_FFACE_SOLID
| R200_BFACE_SOLID
);
650 t
|= (R200_CULL_FRONT
| R200_CULL_BACK
);
655 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
656 R200_STATECHANGE(rmesa
, set
);
657 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
660 if ( rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] != t
) {
661 R200_STATECHANGE(rmesa
, tcl
);
662 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] = t
;
666 static void r200FrontFace( GLcontext
*ctx
, GLenum mode
)
668 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
670 R200_STATECHANGE( rmesa
, set
);
671 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_FFACE_CULL_DIR_MASK
;
673 R200_STATECHANGE( rmesa
, tcl
);
674 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_CULL_FRONT_IS_CCW
;
678 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_FFACE_CULL_CW
;
681 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_FFACE_CULL_CCW
;
682 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_CULL_FRONT_IS_CCW
;
687 /* =============================================================
690 static void r200PointSize( GLcontext
*ctx
, GLfloat size
)
692 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
694 R200_STATECHANGE( rmesa
, cst
);
695 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] &= ~0xffff;
696 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] |= ((GLuint
)(ctx
->Point
.Size
* 16.0));
699 /* =============================================================
702 static void r200LineWidth( GLcontext
*ctx
, GLfloat widthf
)
704 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
706 R200_STATECHANGE( rmesa
, lin
);
707 R200_STATECHANGE( rmesa
, set
);
709 /* Line width is stored in U6.4 format.
711 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] &= ~0xffff;
712 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] |= (GLuint
)(ctx
->Line
._Width
* 16.0);
714 if ( widthf
> 1.0 ) {
715 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_WIDELINE_ENABLE
;
717 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_WIDELINE_ENABLE
;
721 static void r200LineStipple( GLcontext
*ctx
, GLint factor
, GLushort pattern
)
723 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
725 R200_STATECHANGE( rmesa
, lin
);
726 rmesa
->hw
.lin
.cmd
[LIN_RE_LINE_PATTERN
] =
727 ((((GLuint
)factor
& 0xff) << 16) | ((GLuint
)pattern
));
731 /* =============================================================
734 static void r200ColorMask( GLcontext
*ctx
,
735 GLboolean r
, GLboolean g
,
736 GLboolean b
, GLboolean a
)
738 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
739 GLuint mask
= r200PackColor( rmesa
->r200Screen
->cpp
,
740 ctx
->Color
.ColorMask
[RCOMP
],
741 ctx
->Color
.ColorMask
[GCOMP
],
742 ctx
->Color
.ColorMask
[BCOMP
],
743 ctx
->Color
.ColorMask
[ACOMP
] );
745 GLuint flag
= rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] & ~R200_PLANE_MASK_ENABLE
;
747 if (!(r
&& g
&& b
&& a
))
748 flag
|= R200_PLANE_MASK_ENABLE
;
750 if ( rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] != flag
) {
751 R200_STATECHANGE( rmesa
, ctx
);
752 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = flag
;
755 if ( rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
] != mask
) {
756 R200_STATECHANGE( rmesa
, msk
);
757 rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
] = mask
;
762 /* =============================================================
766 static void r200PolygonOffset( GLcontext
*ctx
,
767 GLfloat factor
, GLfloat units
)
769 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
770 GLfloat constant
= units
* rmesa
->state
.depth
.scale
;
775 /* fprintf(stderr, "%s f:%f u:%f\n", __FUNCTION__, factor, constant); */
777 R200_STATECHANGE( rmesa
, zbs
);
778 rmesa
->hw
.zbs
.cmd
[ZBS_SE_ZBIAS_FACTOR
] = *(GLuint
*)&factor
;
779 rmesa
->hw
.zbs
.cmd
[ZBS_SE_ZBIAS_CONSTANT
] = *(GLuint
*)&constant
;
782 static void r200PolygonStipple( GLcontext
*ctx
, const GLubyte
*mask
)
784 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
786 drm_radeon_stipple_t stipple
;
788 /* Must flip pattern upside down.
790 for ( i
= 0 ; i
< 32 ; i
++ ) {
791 rmesa
->state
.stipple
.mask
[31 - i
] = ((GLuint
*) mask
)[i
];
794 /* TODO: push this into cmd mechanism
796 R200_FIREVERTICES( rmesa
);
797 LOCK_HARDWARE( rmesa
);
799 /* FIXME: Use window x,y offsets into stipple RAM.
801 stipple
.mask
= rmesa
->state
.stipple
.mask
;
802 drmCommandWrite( rmesa
->dri
.fd
, DRM_RADEON_STIPPLE
,
803 &stipple
, sizeof(stipple
) );
804 UNLOCK_HARDWARE( rmesa
);
807 static void r200PolygonMode( GLcontext
*ctx
, GLenum face
, GLenum mode
)
809 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
810 GLboolean flag
= (ctx
->_TriangleCaps
& DD_TRI_UNFILLED
) != 0;
812 /* Can't generally do unfilled via tcl, but some good special
815 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_UNFILLED
, flag
);
816 if (rmesa
->TclFallback
) {
817 r200ChooseRenderState( ctx
);
818 r200ChooseVertexState( ctx
);
823 /* =============================================================
824 * Rendering attributes
826 * We really don't want to recalculate all this every time we bind a
827 * texture. These things shouldn't change all that often, so it makes
828 * sense to break them out of the core texture state update routines.
831 /* Examine lighting and texture state to determine if separate specular
834 static void r200UpdateSpecular( GLcontext
*ctx
)
836 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
837 u_int32_t p
= rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
];
839 R200_STATECHANGE( rmesa
, tcl
);
840 R200_STATECHANGE( rmesa
, vtx
);
842 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~(3<<R200_VTX_COLOR_0_SHIFT
);
843 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~(3<<R200_VTX_COLOR_1_SHIFT
);
844 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_COLOR_0
;
845 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_COLOR_1
;
846 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LIGHTING_ENABLE
;
848 p
&= ~R200_SPECULAR_ENABLE
;
850 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_DIFFUSE_SPECULAR_COMBINE
;
853 if (ctx
->Light
.Enabled
&&
854 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
) {
855 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
856 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
) |
857 (R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
858 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_0
;
859 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_1
;
860 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHTING_ENABLE
;
861 p
|= R200_SPECULAR_ENABLE
;
862 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &=
863 ~R200_DIFFUSE_SPECULAR_COMBINE
;
865 else if (ctx
->Light
.Enabled
) {
866 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
867 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
));
868 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_0
;
869 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHTING_ENABLE
;
870 } else if (ctx
->Fog
.ColorSumEnabled
) {
871 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
872 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
) |
873 (R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
874 p
|= R200_SPECULAR_ENABLE
;
876 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
877 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
));
880 if (ctx
->Fog
.Enabled
) {
881 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
882 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
883 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_1
;
886 if ( rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] != p
) {
887 R200_STATECHANGE( rmesa
, ctx
);
888 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] = p
;
891 /* Update vertex/render formats
893 if (rmesa
->TclFallback
) {
894 r200ChooseRenderState( ctx
);
895 r200ChooseVertexState( ctx
);
900 /* =============================================================
905 /* Update on colormaterial, material emmissive/ambient,
906 * lightmodel.globalambient
908 static void update_global_ambient( GLcontext
*ctx
)
910 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
911 float *fcmd
= (float *)R200_DB_STATE( glt
);
913 /* Need to do more if both emmissive & ambient are PREMULT:
914 * I believe this is not nessary when using source_material. This condition thus
915 * will never happen currently, and the function has no dependencies on materials now
917 if ((rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
] &
918 ((3 << R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
919 (3 << R200_FRONT_AMBIENT_SOURCE_SHIFT
))) == 0)
921 COPY_3V( &fcmd
[GLT_RED
],
922 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_EMISSION
]);
923 ACC_SCALE_3V( &fcmd
[GLT_RED
],
924 ctx
->Light
.Model
.Ambient
,
925 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_AMBIENT
]);
929 COPY_3V( &fcmd
[GLT_RED
], ctx
->Light
.Model
.Ambient
);
932 R200_DB_STATECHANGE(rmesa
, &rmesa
->hw
.glt
);
935 /* Update on change to
939 static void update_light_colors( GLcontext
*ctx
, GLuint p
)
941 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
943 /* fprintf(stderr, "%s\n", __FUNCTION__); */
946 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
947 float *fcmd
= (float *)R200_DB_STATE( lit
[p
] );
949 COPY_4V( &fcmd
[LIT_AMBIENT_RED
], l
->Ambient
);
950 COPY_4V( &fcmd
[LIT_DIFFUSE_RED
], l
->Diffuse
);
951 COPY_4V( &fcmd
[LIT_SPECULAR_RED
], l
->Specular
);
953 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
957 static void r200ColorMaterial( GLcontext
*ctx
, GLenum face
, GLenum mode
)
959 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
960 GLuint light_model_ctl1
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
];
961 light_model_ctl1
&= ~((0xf << R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
962 (0xf << R200_FRONT_AMBIENT_SOURCE_SHIFT
) |
963 (0xf << R200_FRONT_DIFFUSE_SOURCE_SHIFT
) |
964 (0xf << R200_FRONT_SPECULAR_SOURCE_SHIFT
) |
965 (0xf << R200_BACK_EMISSIVE_SOURCE_SHIFT
) |
966 (0xf << R200_BACK_AMBIENT_SOURCE_SHIFT
) |
967 (0xf << R200_BACK_DIFFUSE_SOURCE_SHIFT
) |
968 (0xf << R200_BACK_SPECULAR_SOURCE_SHIFT
));
970 if (ctx
->Light
.ColorMaterialEnabled
) {
971 GLuint mask
= ctx
->Light
.ColorMaterialBitmask
;
973 if (mask
& MAT_BIT_FRONT_EMISSION
) {
974 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
975 R200_FRONT_EMISSIVE_SOURCE_SHIFT
);
978 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
979 R200_FRONT_EMISSIVE_SOURCE_SHIFT
);
981 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
982 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
983 R200_FRONT_AMBIENT_SOURCE_SHIFT
);
986 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
987 R200_FRONT_AMBIENT_SOURCE_SHIFT
);
989 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
990 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
991 R200_FRONT_DIFFUSE_SOURCE_SHIFT
);
994 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
995 R200_FRONT_DIFFUSE_SOURCE_SHIFT
);
997 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
998 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
999 R200_FRONT_SPECULAR_SOURCE_SHIFT
);
1002 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
1003 R200_FRONT_SPECULAR_SOURCE_SHIFT
);
1006 if (mask
& MAT_BIT_BACK_EMISSION
) {
1007 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
1008 R200_BACK_EMISSIVE_SOURCE_SHIFT
);
1011 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
1012 R200_BACK_EMISSIVE_SOURCE_SHIFT
);
1014 if (mask
& MAT_BIT_BACK_AMBIENT
) {
1015 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
1016 R200_BACK_AMBIENT_SOURCE_SHIFT
);
1018 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
1019 R200_BACK_AMBIENT_SOURCE_SHIFT
);
1021 if (mask
& MAT_BIT_BACK_DIFFUSE
) {
1022 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
1023 R200_BACK_DIFFUSE_SOURCE_SHIFT
);
1025 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
1026 R200_BACK_DIFFUSE_SOURCE_SHIFT
);
1028 if (mask
& MAT_BIT_BACK_SPECULAR
) {
1029 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
1030 R200_BACK_SPECULAR_SOURCE_SHIFT
);
1033 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
1034 R200_BACK_SPECULAR_SOURCE_SHIFT
);
1038 /* Default to SOURCE_MATERIAL:
1041 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
1042 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_AMBIENT_SOURCE_SHIFT
) |
1043 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_DIFFUSE_SOURCE_SHIFT
) |
1044 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_SPECULAR_SOURCE_SHIFT
) |
1045 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_EMISSIVE_SOURCE_SHIFT
) |
1046 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_AMBIENT_SOURCE_SHIFT
) |
1047 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_DIFFUSE_SOURCE_SHIFT
) |
1048 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_SPECULAR_SOURCE_SHIFT
);
1051 if (light_model_ctl1
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
]) {
1052 R200_STATECHANGE( rmesa
, tcl
);
1053 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
] = light_model_ctl1
;
1059 void r200UpdateMaterial( GLcontext
*ctx
)
1061 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1062 GLfloat (*mat
)[4] = ctx
->Light
.Material
.Attrib
;
1063 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( mtl
[0] );
1064 GLfloat
*fcmd2
= (GLfloat
*)R200_DB_STATE( mtl
[1] );
1067 /* Might be possible and faster to update everything unconditionally? */
1068 if (ctx
->Light
.ColorMaterialEnabled
)
1069 mask
&= ~ctx
->Light
.ColorMaterialBitmask
;
1071 if (R200_DEBUG
& DEBUG_STATE
)
1072 fprintf(stderr
, "%s\n", __FUNCTION__
);
1074 if (mask
& MAT_BIT_FRONT_EMISSION
) {
1075 fcmd
[MTL_EMMISSIVE_RED
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][0];
1076 fcmd
[MTL_EMMISSIVE_GREEN
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][1];
1077 fcmd
[MTL_EMMISSIVE_BLUE
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][2];
1078 fcmd
[MTL_EMMISSIVE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][3];
1080 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
1081 fcmd
[MTL_AMBIENT_RED
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][0];
1082 fcmd
[MTL_AMBIENT_GREEN
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][1];
1083 fcmd
[MTL_AMBIENT_BLUE
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][2];
1084 fcmd
[MTL_AMBIENT_ALPHA
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][3];
1086 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
1087 fcmd
[MTL_DIFFUSE_RED
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][0];
1088 fcmd
[MTL_DIFFUSE_GREEN
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][1];
1089 fcmd
[MTL_DIFFUSE_BLUE
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][2];
1090 fcmd
[MTL_DIFFUSE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][3];
1092 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
1093 fcmd
[MTL_SPECULAR_RED
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][0];
1094 fcmd
[MTL_SPECULAR_GREEN
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][1];
1095 fcmd
[MTL_SPECULAR_BLUE
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][2];
1096 fcmd
[MTL_SPECULAR_ALPHA
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][3];
1098 if (mask
& MAT_BIT_FRONT_SHININESS
) {
1099 fcmd
[MTL_SHININESS
] = mat
[MAT_ATTRIB_FRONT_SHININESS
][0];
1102 if (mask
& MAT_BIT_BACK_EMISSION
) {
1103 fcmd2
[MTL_EMMISSIVE_RED
] = mat
[MAT_ATTRIB_BACK_EMISSION
][0];
1104 fcmd2
[MTL_EMMISSIVE_GREEN
] = mat
[MAT_ATTRIB_BACK_EMISSION
][1];
1105 fcmd2
[MTL_EMMISSIVE_BLUE
] = mat
[MAT_ATTRIB_BACK_EMISSION
][2];
1106 fcmd2
[MTL_EMMISSIVE_ALPHA
] = mat
[MAT_ATTRIB_BACK_EMISSION
][3];
1108 if (mask
& MAT_BIT_BACK_AMBIENT
) {
1109 fcmd2
[MTL_AMBIENT_RED
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][0];
1110 fcmd2
[MTL_AMBIENT_GREEN
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][1];
1111 fcmd2
[MTL_AMBIENT_BLUE
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][2];
1112 fcmd2
[MTL_AMBIENT_ALPHA
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][3];
1114 if (mask
& MAT_BIT_BACK_DIFFUSE
) {
1115 fcmd2
[MTL_DIFFUSE_RED
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][0];
1116 fcmd2
[MTL_DIFFUSE_GREEN
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][1];
1117 fcmd2
[MTL_DIFFUSE_BLUE
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][2];
1118 fcmd2
[MTL_DIFFUSE_ALPHA
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][3];
1120 if (mask
& MAT_BIT_BACK_SPECULAR
) {
1121 fcmd2
[MTL_SPECULAR_RED
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][0];
1122 fcmd2
[MTL_SPECULAR_GREEN
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][1];
1123 fcmd2
[MTL_SPECULAR_BLUE
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][2];
1124 fcmd2
[MTL_SPECULAR_ALPHA
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][3];
1126 if (mask
& MAT_BIT_BACK_SHININESS
) {
1127 fcmd2
[MTL_SHININESS
] = mat
[MAT_ATTRIB_BACK_SHININESS
][0];
1130 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mtl
[0] );
1131 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mtl
[1] );
1133 /* currently material changes cannot trigger a global ambient change, I believe this is correct
1134 update_global_ambient( ctx ); */
1139 * _MESA_NEW_NEED_EYE_COORDS
1141 * Uses derived state from mesa:
1146 * _ModelViewInvScale
1150 * which are calculated in light.c and are correct for the current
1151 * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
1152 * and _MESA_NEW_NEED_EYE_COORDS.
1154 static void update_light( GLcontext
*ctx
)
1156 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1158 /* Have to check these, or have an automatic shortcircuit mechanism
1159 * to remove noop statechanges. (Or just do a better job on the
1163 GLuint tmp
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
];
1165 if (ctx
->_NeedEyeCoords
)
1166 tmp
&= ~R200_LIGHT_IN_MODELSPACE
;
1168 tmp
|= R200_LIGHT_IN_MODELSPACE
;
1170 if (tmp
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
])
1172 R200_STATECHANGE( rmesa
, tcl
);
1173 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] = tmp
;
1178 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( eye
);
1179 fcmd
[EYE_X
] = ctx
->_EyeZDir
[0];
1180 fcmd
[EYE_Y
] = ctx
->_EyeZDir
[1];
1181 fcmd
[EYE_Z
] = - ctx
->_EyeZDir
[2];
1182 fcmd
[EYE_RESCALE_FACTOR
] = ctx
->_ModelViewInvScale
;
1183 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.eye
);
1188 if (ctx
->Light
.Enabled
) {
1190 for (p
= 0 ; p
< MAX_LIGHTS
; p
++) {
1191 if (ctx
->Light
.Light
[p
].Enabled
) {
1192 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1193 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( lit
[p
] );
1195 if (l
->EyePosition
[3] == 0.0) {
1196 COPY_3FV( &fcmd
[LIT_POSITION_X
], l
->_VP_inf_norm
);
1197 COPY_3FV( &fcmd
[LIT_DIRECTION_X
], l
->_h_inf_norm
);
1198 fcmd
[LIT_POSITION_W
] = 0;
1199 fcmd
[LIT_DIRECTION_W
] = 0;
1201 COPY_4V( &fcmd
[LIT_POSITION_X
], l
->_Position
);
1202 fcmd
[LIT_DIRECTION_X
] = -l
->_NormDirection
[0];
1203 fcmd
[LIT_DIRECTION_Y
] = -l
->_NormDirection
[1];
1204 fcmd
[LIT_DIRECTION_Z
] = -l
->_NormDirection
[2];
1205 fcmd
[LIT_DIRECTION_W
] = 0;
1208 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
1214 static void r200Lightfv( GLcontext
*ctx
, GLenum light
,
1215 GLenum pname
, const GLfloat
*params
)
1217 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1218 GLint p
= light
- GL_LIGHT0
;
1219 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1220 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.lit
[p
].cmd
;
1227 update_light_colors( ctx
, p
);
1230 case GL_SPOT_DIRECTION
:
1231 /* picked up in update_light */
1235 /* positions picked up in update_light, but can do flag here */
1236 GLuint flag
= (p
&1)? R200_LIGHT_1_IS_LOCAL
: R200_LIGHT_0_IS_LOCAL
;
1237 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1239 R200_STATECHANGE(rmesa
, tcl
);
1240 if (l
->EyePosition
[3] != 0.0F
)
1241 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1243 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1247 case GL_SPOT_EXPONENT
:
1248 R200_STATECHANGE(rmesa
, lit
[p
]);
1249 fcmd
[LIT_SPOT_EXPONENT
] = params
[0];
1252 case GL_SPOT_CUTOFF
: {
1253 GLuint flag
= (p
&1) ? R200_LIGHT_1_IS_SPOT
: R200_LIGHT_0_IS_SPOT
;
1254 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1256 R200_STATECHANGE(rmesa
, lit
[p
]);
1257 fcmd
[LIT_SPOT_CUTOFF
] = l
->_CosCutoff
;
1259 R200_STATECHANGE(rmesa
, tcl
);
1260 if (l
->SpotCutoff
!= 180.0F
)
1261 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1263 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1268 case GL_CONSTANT_ATTENUATION
:
1269 R200_STATECHANGE(rmesa
, lit
[p
]);
1270 fcmd
[LIT_ATTEN_CONST
] = params
[0];
1271 if ( params
[0] == 0.0 )
1272 fcmd
[LIT_ATTEN_CONST_INV
] = FLT_MAX
;
1274 fcmd
[LIT_ATTEN_CONST_INV
] = 1.0 / params
[0];
1276 case GL_LINEAR_ATTENUATION
:
1277 R200_STATECHANGE(rmesa
, lit
[p
]);
1278 fcmd
[LIT_ATTEN_LINEAR
] = params
[0];
1280 case GL_QUADRATIC_ATTENUATION
:
1281 R200_STATECHANGE(rmesa
, lit
[p
]);
1282 fcmd
[LIT_ATTEN_QUADRATIC
] = params
[0];
1288 /* Set RANGE_ATTEN only when needed */
1291 case GL_CONSTANT_ATTENUATION
:
1292 case GL_LINEAR_ATTENUATION
:
1293 case GL_QUADRATIC_ATTENUATION
: {
1294 GLuint
*icmd
= (GLuint
*)R200_DB_STATE( tcl
);
1295 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1296 GLuint atten_flag
= ( p
&1 ) ? R200_LIGHT_1_ENABLE_RANGE_ATTEN
1297 : R200_LIGHT_0_ENABLE_RANGE_ATTEN
;
1298 GLuint atten_const_flag
= ( p
&1 ) ? R200_LIGHT_1_CONSTANT_RANGE_ATTEN
1299 : R200_LIGHT_0_CONSTANT_RANGE_ATTEN
;
1301 if ( l
->EyePosition
[3] == 0.0F
||
1302 ( ( fcmd
[LIT_ATTEN_CONST
] == 0.0 || fcmd
[LIT_ATTEN_CONST
] == 1.0 ) &&
1303 fcmd
[LIT_ATTEN_QUADRATIC
] == 0.0 && fcmd
[LIT_ATTEN_LINEAR
] == 0.0 ) ) {
1304 /* Disable attenuation */
1305 icmd
[idx
] &= ~atten_flag
;
1307 if ( fcmd
[LIT_ATTEN_QUADRATIC
] == 0.0 && fcmd
[LIT_ATTEN_LINEAR
] == 0.0 ) {
1308 /* Enable only constant portion of attenuation calculation */
1309 icmd
[idx
] |= ( atten_flag
| atten_const_flag
);
1311 /* Enable full attenuation calculation */
1312 icmd
[idx
] &= ~atten_const_flag
;
1313 icmd
[idx
] |= atten_flag
;
1317 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.tcl
);
1328 static void r200LightModelfv( GLcontext
*ctx
, GLenum pname
,
1329 const GLfloat
*param
)
1331 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1334 case GL_LIGHT_MODEL_AMBIENT
:
1335 update_global_ambient( ctx
);
1338 case GL_LIGHT_MODEL_LOCAL_VIEWER
:
1339 R200_STATECHANGE( rmesa
, tcl
);
1340 if (ctx
->Light
.Model
.LocalViewer
)
1341 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LOCAL_VIEWER
;
1343 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LOCAL_VIEWER
;
1346 case GL_LIGHT_MODEL_TWO_SIDE
:
1347 R200_STATECHANGE( rmesa
, tcl
);
1348 if (ctx
->Light
.Model
.TwoSide
)
1349 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHT_TWOSIDE
;
1351 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~(R200_LIGHT_TWOSIDE
);
1352 if (rmesa
->TclFallback
) {
1353 r200ChooseRenderState( ctx
);
1354 r200ChooseVertexState( ctx
);
1358 case GL_LIGHT_MODEL_COLOR_CONTROL
:
1359 r200UpdateSpecular(ctx
);
1367 static void r200ShadeModel( GLcontext
*ctx
, GLenum mode
)
1369 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1370 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
1372 s
&= ~(R200_DIFFUSE_SHADE_MASK
|
1373 R200_ALPHA_SHADE_MASK
|
1374 R200_SPECULAR_SHADE_MASK
|
1375 R200_FOG_SHADE_MASK
);
1379 s
|= (R200_DIFFUSE_SHADE_FLAT
|
1380 R200_ALPHA_SHADE_FLAT
|
1381 R200_SPECULAR_SHADE_FLAT
|
1382 R200_FOG_SHADE_FLAT
);
1385 s
|= (R200_DIFFUSE_SHADE_GOURAUD
|
1386 R200_ALPHA_SHADE_GOURAUD
|
1387 R200_SPECULAR_SHADE_GOURAUD
|
1388 R200_FOG_SHADE_GOURAUD
);
1394 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
1395 R200_STATECHANGE( rmesa
, set
);
1396 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
1401 /* =============================================================
1405 static void r200ClipPlane( GLcontext
*ctx
, GLenum plane
, const GLfloat
*eq
)
1407 GLint p
= (GLint
) plane
- (GLint
) GL_CLIP_PLANE0
;
1408 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1409 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1411 R200_STATECHANGE( rmesa
, ucp
[p
] );
1412 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1413 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1414 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1415 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1418 static void r200UpdateClipPlanes( GLcontext
*ctx
)
1420 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1423 for (p
= 0; p
< ctx
->Const
.MaxClipPlanes
; p
++) {
1424 if (ctx
->Transform
.ClipPlanesEnabled
& (1 << p
)) {
1425 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1427 R200_STATECHANGE( rmesa
, ucp
[p
] );
1428 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1429 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1430 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1431 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1437 /* =============================================================
1442 r200StencilFuncSeparate( GLcontext
*ctx
, GLenum face
, GLenum func
,
1443 GLint ref
, GLuint mask
)
1445 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1446 GLuint refmask
= ((ctx
->Stencil
.Ref
[0] << R200_STENCIL_REF_SHIFT
) |
1447 (ctx
->Stencil
.ValueMask
[0] << R200_STENCIL_MASK_SHIFT
));
1449 R200_STATECHANGE( rmesa
, ctx
);
1450 R200_STATECHANGE( rmesa
, msk
);
1452 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_STENCIL_TEST_MASK
;
1453 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~(R200_STENCIL_REF_MASK
|
1454 R200_STENCIL_VALUE_MASK
);
1456 switch ( ctx
->Stencil
.Function
[0] ) {
1458 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEVER
;
1461 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LESS
;
1464 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_EQUAL
;
1467 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LEQUAL
;
1470 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GREATER
;
1473 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEQUAL
;
1476 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GEQUAL
;
1479 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_ALWAYS
;
1483 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |= refmask
;
1487 r200StencilMaskSeparate( GLcontext
*ctx
, GLenum face
, GLuint mask
)
1489 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1491 R200_STATECHANGE( rmesa
, msk
);
1492 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~R200_STENCIL_WRITE_MASK
;
1493 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |=
1494 (ctx
->Stencil
.WriteMask
[0] << R200_STENCIL_WRITEMASK_SHIFT
);
1498 r200StencilOpSeparate( GLcontext
*ctx
, GLenum face
, GLenum fail
,
1499 GLenum zfail
, GLenum zpass
)
1501 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1503 R200_STATECHANGE( rmesa
, ctx
);
1504 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~(R200_STENCIL_FAIL_MASK
|
1505 R200_STENCIL_ZFAIL_MASK
|
1506 R200_STENCIL_ZPASS_MASK
);
1508 switch ( ctx
->Stencil
.FailFunc
[0] ) {
1510 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_KEEP
;
1513 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_ZERO
;
1516 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_REPLACE
;
1519 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC
;
1522 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC
;
1524 case GL_INCR_WRAP_EXT
:
1525 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC_WRAP
;
1527 case GL_DECR_WRAP_EXT
:
1528 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC_WRAP
;
1531 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INVERT
;
1535 switch ( ctx
->Stencil
.ZFailFunc
[0] ) {
1537 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_KEEP
;
1540 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_ZERO
;
1543 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_REPLACE
;
1546 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC
;
1549 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC
;
1551 case GL_INCR_WRAP_EXT
:
1552 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC_WRAP
;
1554 case GL_DECR_WRAP_EXT
:
1555 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC_WRAP
;
1558 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INVERT
;
1562 switch ( ctx
->Stencil
.ZPassFunc
[0] ) {
1564 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_KEEP
;
1567 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_ZERO
;
1570 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_REPLACE
;
1573 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC
;
1576 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC
;
1578 case GL_INCR_WRAP_EXT
:
1579 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC_WRAP
;
1581 case GL_DECR_WRAP_EXT
:
1582 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC_WRAP
;
1585 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INVERT
;
1590 static void r200ClearStencil( GLcontext
*ctx
, GLint s
)
1592 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1594 rmesa
->state
.stencil
.clear
=
1595 ((GLuint
) ctx
->Stencil
.Clear
|
1596 (0xff << R200_STENCIL_MASK_SHIFT
) |
1597 (ctx
->Stencil
.WriteMask
[0] << R200_STENCIL_WRITEMASK_SHIFT
));
1601 /* =============================================================
1602 * Window position and viewport transformation
1606 * To correctly position primitives:
1608 #define SUBPIXEL_X 0.125
1609 #define SUBPIXEL_Y 0.125
1611 void r200UpdateWindow( GLcontext
*ctx
)
1613 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1614 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
1615 GLfloat xoffset
= (GLfloat
)dPriv
->x
;
1616 GLfloat yoffset
= (GLfloat
)dPriv
->y
+ dPriv
->h
;
1617 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1619 GLfloat sx
= v
[MAT_SX
];
1620 GLfloat tx
= v
[MAT_TX
] + xoffset
+ SUBPIXEL_X
;
1621 GLfloat sy
= - v
[MAT_SY
];
1622 GLfloat ty
= (- v
[MAT_TY
]) + yoffset
+ SUBPIXEL_Y
;
1623 GLfloat sz
= v
[MAT_SZ
] * rmesa
->state
.depth
.scale
;
1624 GLfloat tz
= v
[MAT_TZ
] * rmesa
->state
.depth
.scale
;
1626 R200_FIREVERTICES( rmesa
);
1627 R200_STATECHANGE( rmesa
, vpt
);
1629 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XSCALE
] = *(GLuint
*)&sx
;
1630 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = *(GLuint
*)&tx
;
1631 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YSCALE
] = *(GLuint
*)&sy
;
1632 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = *(GLuint
*)&ty
;
1633 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZSCALE
] = *(GLuint
*)&sz
;
1634 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZOFFSET
] = *(GLuint
*)&tz
;
1639 static void r200Viewport( GLcontext
*ctx
, GLint x
, GLint y
,
1640 GLsizei width
, GLsizei height
)
1642 /* Don't pipeline viewport changes, conflict with window offset
1643 * setting below. Could apply deltas to rescue pipelined viewport
1644 * values, or keep the originals hanging around.
1646 R200_FIREVERTICES( R200_CONTEXT(ctx
) );
1647 r200UpdateWindow( ctx
);
1650 static void r200DepthRange( GLcontext
*ctx
, GLclampd nearval
,
1653 r200UpdateWindow( ctx
);
1656 void r200UpdateViewportOffset( GLcontext
*ctx
)
1658 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1659 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
1660 GLfloat xoffset
= (GLfloat
)dPriv
->x
;
1661 GLfloat yoffset
= (GLfloat
)dPriv
->y
+ dPriv
->h
;
1662 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1664 GLfloat tx
= v
[MAT_TX
] + xoffset
+ SUBPIXEL_X
;
1665 GLfloat ty
= (- v
[MAT_TY
]) + yoffset
+ SUBPIXEL_Y
;
1667 if ( rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] != *(GLuint
*)&tx
||
1668 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] != *(GLuint
*)&ty
)
1670 /* Note: this should also modify whatever data the context reset
1673 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = *(GLuint
*)&tx
;
1674 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = *(GLuint
*)&ty
;
1676 /* update polygon stipple x/y screen offset */
1679 GLuint m
= rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
];
1681 m
&= ~(R200_STIPPLE_X_OFFSET_MASK
|
1682 R200_STIPPLE_Y_OFFSET_MASK
);
1684 /* add magic offsets, then invert */
1685 stx
= 31 - ((rmesa
->dri
.drawable
->x
- 1) & R200_STIPPLE_COORD_MASK
);
1686 sty
= 31 - ((rmesa
->dri
.drawable
->y
+ rmesa
->dri
.drawable
->h
- 1)
1687 & R200_STIPPLE_COORD_MASK
);
1689 m
|= ((stx
<< R200_STIPPLE_X_OFFSET_SHIFT
) |
1690 (sty
<< R200_STIPPLE_Y_OFFSET_SHIFT
));
1692 if ( rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] != m
) {
1693 R200_STATECHANGE( rmesa
, msc
);
1694 rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] = m
;
1699 r200UpdateScissor( ctx
);
1704 /* =============================================================
1708 static void r200ClearColor( GLcontext
*ctx
, const GLfloat c
[4] )
1710 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1712 CLAMPED_FLOAT_TO_UBYTE(color
[0], c
[0]);
1713 CLAMPED_FLOAT_TO_UBYTE(color
[1], c
[1]);
1714 CLAMPED_FLOAT_TO_UBYTE(color
[2], c
[2]);
1715 CLAMPED_FLOAT_TO_UBYTE(color
[3], c
[3]);
1716 rmesa
->state
.color
.clear
= r200PackColor( rmesa
->r200Screen
->cpp
,
1718 color
[2], color
[3] );
1722 static void r200RenderMode( GLcontext
*ctx
, GLenum mode
)
1724 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1725 FALLBACK( rmesa
, R200_FALLBACK_RENDER_MODE
, (mode
!= GL_RENDER
) );
1729 static GLuint r200_rop_tab
[] = {
1732 R200_ROP_AND_REVERSE
,
1734 R200_ROP_AND_INVERTED
,
1741 R200_ROP_OR_REVERSE
,
1742 R200_ROP_COPY_INVERTED
,
1743 R200_ROP_OR_INVERTED
,
1748 static void r200LogicOpCode( GLcontext
*ctx
, GLenum opcode
)
1750 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1751 GLuint rop
= (GLuint
)opcode
- GL_CLEAR
;
1755 R200_STATECHANGE( rmesa
, msk
);
1756 rmesa
->hw
.msk
.cmd
[MSK_RB3D_ROPCNTL
] = r200_rop_tab
[rop
];
1760 void r200SetCliprects( r200ContextPtr rmesa
, GLenum mode
)
1762 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
1766 rmesa
->numClipRects
= dPriv
->numClipRects
;
1767 rmesa
->pClipRects
= dPriv
->pClipRects
;
1770 /* Can't ignore 2d windows if we are page flipping.
1772 if ( dPriv
->numBackClipRects
== 0 || rmesa
->doPageFlip
) {
1773 rmesa
->numClipRects
= dPriv
->numClipRects
;
1774 rmesa
->pClipRects
= dPriv
->pClipRects
;
1777 rmesa
->numClipRects
= dPriv
->numBackClipRects
;
1778 rmesa
->pClipRects
= dPriv
->pBackClipRects
;
1782 fprintf(stderr
, "bad mode in r200SetCliprects\n");
1786 if (rmesa
->state
.scissor
.enabled
)
1787 r200RecalcScissorRects( rmesa
);
1791 static void r200DrawBuffer( GLcontext
*ctx
, GLenum mode
)
1793 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1795 if (R200_DEBUG
& DEBUG_DRI
)
1796 fprintf(stderr
, "%s %s\n", __FUNCTION__
,
1797 _mesa_lookup_enum_by_nr( mode
));
1799 R200_FIREVERTICES(rmesa
); /* don't pipeline cliprect changes */
1802 * _ColorDrawBufferMask is easier to cope with than <mode>.
1803 * Check for software fallback, update cliprects.
1805 switch ( ctx
->DrawBuffer
->_ColorDrawBufferMask
[0] ) {
1806 case BUFFER_BIT_FRONT_LEFT
:
1807 FALLBACK( rmesa
, R200_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
1808 r200SetCliprects( rmesa
, GL_FRONT_LEFT
);
1810 case BUFFER_BIT_BACK_LEFT
:
1811 FALLBACK( rmesa
, R200_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
1812 r200SetCliprects( rmesa
, GL_BACK_LEFT
);
1815 /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */
1816 FALLBACK( rmesa
, R200_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
1820 /* We'll set the drawing engine's offset/pitch parameters later
1821 * when we update other state.
1826 static void r200ReadBuffer( GLcontext
*ctx
, GLenum mode
)
1828 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
1831 /* =============================================================
1832 * State enable/disable
1835 static void r200Enable( GLcontext
*ctx
, GLenum cap
, GLboolean state
)
1837 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1840 if ( R200_DEBUG
& DEBUG_STATE
)
1841 fprintf( stderr
, "%s( %s = %s )\n", __FUNCTION__
,
1842 _mesa_lookup_enum_by_nr( cap
),
1843 state
? "GL_TRUE" : "GL_FALSE" );
1846 /* Fast track this one...
1854 R200_STATECHANGE( rmesa
, ctx
);
1856 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ALPHA_TEST_ENABLE
;
1858 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ALPHA_TEST_ENABLE
;
1863 case GL_COLOR_LOGIC_OP
:
1864 r200_set_blend_state( ctx
);
1867 case GL_CLIP_PLANE0
:
1868 case GL_CLIP_PLANE1
:
1869 case GL_CLIP_PLANE2
:
1870 case GL_CLIP_PLANE3
:
1871 case GL_CLIP_PLANE4
:
1872 case GL_CLIP_PLANE5
:
1873 p
= cap
-GL_CLIP_PLANE0
;
1874 R200_STATECHANGE( rmesa
, tcl
);
1876 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= (R200_UCP_ENABLE_0
<<p
);
1877 r200ClipPlane( ctx
, cap
, NULL
);
1880 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~(R200_UCP_ENABLE_0
<<p
);
1884 case GL_COLOR_MATERIAL
:
1885 r200ColorMaterial( ctx
, 0, 0 );
1886 r200UpdateMaterial( ctx
);
1890 r200CullFace( ctx
, 0 );
1894 R200_STATECHANGE(rmesa
, ctx
);
1896 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_Z_ENABLE
;
1898 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_Z_ENABLE
;
1903 R200_STATECHANGE(rmesa
, ctx
);
1905 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_DITHER_ENABLE
;
1906 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~rmesa
->state
.color
.roundEnable
;
1908 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_DITHER_ENABLE
;
1909 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= rmesa
->state
.color
.roundEnable
;
1914 R200_STATECHANGE(rmesa
, ctx
);
1916 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_FOG_ENABLE
;
1917 r200Fogfv( ctx
, GL_FOG_MODE
, NULL
);
1919 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_FOG_ENABLE
;
1920 R200_STATECHANGE(rmesa
, tcl
);
1921 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_TCL_FOG_MASK
;
1923 r200UpdateSpecular( ctx
); /* for PK_SPEC */
1924 if (rmesa
->TclFallback
)
1925 r200ChooseVertexState( ctx
);
1926 _mesa_allow_light_in_model( ctx
, !state
);
1937 R200_STATECHANGE(rmesa
, tcl
);
1938 p
= cap
- GL_LIGHT0
;
1940 flag
= (R200_LIGHT_1_ENABLE
|
1941 R200_LIGHT_1_ENABLE_AMBIENT
|
1942 R200_LIGHT_1_ENABLE_SPECULAR
);
1944 flag
= (R200_LIGHT_0_ENABLE
|
1945 R200_LIGHT_0_ENABLE_AMBIENT
|
1946 R200_LIGHT_0_ENABLE_SPECULAR
);
1949 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] |= flag
;
1951 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] &= ~flag
;
1955 update_light_colors( ctx
, p
);
1959 r200UpdateSpecular(ctx
);
1962 case GL_LINE_SMOOTH
:
1963 R200_STATECHANGE( rmesa
, ctx
);
1965 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_LINE
;
1967 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_LINE
;
1971 case GL_LINE_STIPPLE
:
1972 R200_STATECHANGE( rmesa
, set
);
1974 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_PATTERN_ENABLE
;
1976 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_PATTERN_ENABLE
;
1981 R200_STATECHANGE( rmesa
, tcl
);
1983 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_NORMALIZE_NORMALS
;
1985 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_NORMALIZE_NORMALS
;
1989 /* Pointsize registers on r200 only work for point sprites, and point smooth
1990 * doesn't work for point sprites (and isn't needed for 1.0 sized aa points).
1991 * In any case, setting pointmin == pointsizemax == 1.0 for aa points
1992 * is enough to satisfy conform.
1994 case GL_POINT_SMOOTH
:
1997 /* These don't really do anything, as we don't use the 3vtx
2001 case GL_POLYGON_OFFSET_POINT
:
2002 R200_STATECHANGE( rmesa
, set
);
2004 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_POINT
;
2006 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_POINT
;
2010 case GL_POLYGON_OFFSET_LINE
:
2011 R200_STATECHANGE( rmesa
, set
);
2013 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_LINE
;
2015 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_LINE
;
2020 case GL_POLYGON_OFFSET_FILL
:
2021 R200_STATECHANGE( rmesa
, set
);
2023 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_TRI
;
2025 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_TRI
;
2029 case GL_POLYGON_SMOOTH
:
2030 R200_STATECHANGE( rmesa
, ctx
);
2032 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_POLY
;
2034 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_POLY
;
2038 case GL_POLYGON_STIPPLE
:
2039 R200_STATECHANGE(rmesa
, set
);
2041 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_STIPPLE_ENABLE
;
2043 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_STIPPLE_ENABLE
;
2047 case GL_RESCALE_NORMAL_EXT
: {
2048 GLboolean tmp
= ctx
->_NeedEyeCoords
? state
: !state
;
2049 R200_STATECHANGE( rmesa
, tcl
);
2051 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
2053 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
2058 case GL_SCISSOR_TEST
:
2059 R200_FIREVERTICES( rmesa
);
2060 rmesa
->state
.scissor
.enabled
= state
;
2061 r200UpdateScissor( ctx
);
2064 case GL_STENCIL_TEST
:
2065 if ( rmesa
->state
.stencil
.hwBuffer
) {
2066 R200_STATECHANGE( rmesa
, ctx
);
2068 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_STENCIL_ENABLE
;
2070 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_STENCIL_ENABLE
;
2073 FALLBACK( rmesa
, R200_FALLBACK_STENCIL
, state
);
2077 case GL_TEXTURE_GEN_Q
:
2078 case GL_TEXTURE_GEN_R
:
2079 case GL_TEXTURE_GEN_S
:
2080 case GL_TEXTURE_GEN_T
:
2081 /* Picked up in r200UpdateTextureState.
2083 rmesa
->recheck_texgen
[ctx
->Texture
.CurrentUnit
] = GL_TRUE
;
2086 case GL_COLOR_SUM_EXT
:
2087 r200UpdateSpecular ( ctx
);
2090 case GL_VERTEX_PROGRAM_ARB
:
2091 TCL_FALLBACK(rmesa
->glCtx
, R200_TCL_FALLBACK_VERTEX_PROGRAM
, state
);
2094 case GL_FRAGMENT_SHADER_ATI
:
2096 /* restore normal tex env colors and make sure tex env combine will get updated
2097 mark env atoms dirty (as their data was overwritten by afs even
2098 if they didn't change) and restore tex coord routing */
2100 for (unit
= 0; unit
< R200_MAX_TEXTURE_UNITS
; unit
++) {
2101 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] &=
2102 ~(R200_TXFORMAT_ST_ROUTE_MASK
| R200_TXFORMAT_LOOKUP_DISABLE
);
2103 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] |= unit
<< R200_TXFORMAT_ST_ROUTE_SHIFT
;
2104 /* need to guard this with drmSupportsFragmentShader? Should never get here if
2105 we don't announce ATI_fs, right? */
2106 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXMULTI_CTL
] = 0;
2107 R200_STATECHANGE( rmesa
, pix
[unit
] );
2108 R200_STATECHANGE( rmesa
, tex
[unit
] );
2110 rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] = 0;
2111 R200_STATECHANGE( rmesa
, cst
);
2112 R200_STATECHANGE( rmesa
, tf
);
2115 /* need to mark this dirty as pix/tf atoms have overwritten the data
2116 even if the data in the atoms didn't change */
2117 R200_STATECHANGE( rmesa
, atf
);
2118 R200_STATECHANGE( rmesa
, afs
[1] );
2119 /* everything else picked up in r200UpdateTextureState hopefully */
2128 void r200LightingSpaceChange( GLcontext
*ctx
)
2130 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2133 if (R200_DEBUG
& DEBUG_STATE
)
2134 fprintf(stderr
, "%s %d BEFORE %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
2135 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
2137 if (ctx
->_NeedEyeCoords
)
2138 tmp
= ctx
->Transform
.RescaleNormals
;
2140 tmp
= !ctx
->Transform
.RescaleNormals
;
2142 R200_STATECHANGE( rmesa
, tcl
);
2144 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
2146 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
2149 if (R200_DEBUG
& DEBUG_STATE
)
2150 fprintf(stderr
, "%s %d AFTER %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
2151 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
2154 /* =============================================================
2155 * Deferred state management - matrices, textures, other?
2161 static void upload_matrix( r200ContextPtr rmesa
, GLfloat
*src
, int idx
)
2163 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
2167 for (i
= 0 ; i
< 4 ; i
++) {
2171 *dest
++ = src
[i
+12];
2174 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
2177 static void upload_matrix_t( r200ContextPtr rmesa
, const GLfloat
*src
, int idx
)
2179 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
2180 memcpy(dest
, src
, 16*sizeof(float));
2181 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
2185 static void update_texturematrix( GLcontext
*ctx
)
2187 r200ContextPtr rmesa
= R200_CONTEXT( ctx
);
2188 GLuint tpc
= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
];
2189 GLuint compsel
= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
];
2192 if (R200_DEBUG
& DEBUG_STATE
)
2193 fprintf(stderr
, "%s before COMPSEL: %x\n", __FUNCTION__
,
2194 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]);
2196 rmesa
->TexMatEnabled
= 0;
2197 rmesa
->TexMatCompSel
= 0;
2199 for (unit
= 0 ; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
2200 if (!ctx
->Texture
.Unit
[unit
]._ReallyEnabled
)
2203 if (ctx
->TextureMatrixStack
[unit
].Top
->type
!= MATRIX_IDENTITY
) {
2204 rmesa
->TexMatEnabled
|= (R200_TEXGEN_TEXMAT_0_ENABLE
|
2205 R200_TEXMAT_0_ENABLE
) << unit
;
2207 rmesa
->TexMatCompSel
|= R200_OUTPUT_TEX_0
<< unit
;
2209 if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2210 /* Need to preconcatenate any active texgen
2211 * obj/eyeplane matrices:
2213 _math_matrix_mul_matrix( &rmesa
->tmpmat
,
2214 ctx
->TextureMatrixStack
[unit
].Top
,
2215 &rmesa
->TexGenMatrix
[unit
] );
2216 upload_matrix( rmesa
, rmesa
->tmpmat
.m
, R200_MTX_TEX0
+unit
);
2219 upload_matrix( rmesa
, ctx
->TextureMatrixStack
[unit
].Top
->m
,
2220 R200_MTX_TEX0
+unit
);
2223 else if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2224 upload_matrix( rmesa
, rmesa
->TexGenMatrix
[unit
].m
,
2225 R200_MTX_TEX0
+unit
);
2229 tpc
= (rmesa
->TexMatEnabled
| rmesa
->TexGenEnabled
);
2230 if (tpc
!= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
]) {
2231 R200_STATECHANGE(rmesa
, tcg
);
2232 rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
] = tpc
;
2235 compsel
&= ~R200_OUTPUT_TEX_MASK
;
2236 compsel
|= rmesa
->TexMatCompSel
| rmesa
->TexGenCompSel
;
2237 if (compsel
!= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]) {
2238 R200_STATECHANGE(rmesa
, vtx
);
2239 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] = compsel
;
2246 * Tell the card where to render (offset, pitch).
2247 * Effected by glDrawBuffer, etc
2250 r200UpdateDrawBuffer(GLcontext
*ctx
)
2252 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2253 struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
2254 driRenderbuffer
*drb
;
2256 if (fb
->_ColorDrawBufferMask
[0] == BUFFER_BIT_FRONT_LEFT
) {
2258 drb
= (driRenderbuffer
*) fb
->Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
;
2260 else if (fb
->_ColorDrawBufferMask
[0] == BUFFER_BIT_BACK_LEFT
) {
2262 drb
= (driRenderbuffer
*) fb
->Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
;
2265 /* drawing to multiple buffers, or none */
2270 assert(drb
->flippedPitch
);
2272 R200_STATECHANGE( rmesa
, ctx
);
2274 /* Note: we used the (possibly) page-flipped values */
2275 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLOROFFSET
]
2276 = ((drb
->flippedOffset
+ rmesa
->r200Screen
->fbLocation
)
2277 & R200_COLOROFFSET_MASK
);
2278 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLORPITCH
] = drb
->flippedPitch
;
2279 if (rmesa
->sarea
->tiling_enabled
) {
2280 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLORPITCH
] |= R200_COLOR_TILE_ENABLE
;
2286 void r200ValidateState( GLcontext
*ctx
)
2288 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2289 GLuint new_state
= rmesa
->NewGLState
;
2291 if (new_state
& (_NEW_BUFFERS
| _NEW_COLOR
| _NEW_PIXEL
)) {
2292 r200UpdateDrawBuffer(ctx
);
2295 if (new_state
& (_NEW_TEXTURE
| _NEW_PROGRAM
)) {
2296 r200UpdateTextureState( ctx
);
2297 new_state
|= rmesa
->NewGLState
; /* may add TEXTURE_MATRIX */
2300 /* Need an event driven matrix update?
2302 if (new_state
& (_NEW_MODELVIEW
|_NEW_PROJECTION
))
2303 upload_matrix( rmesa
, ctx
->_ModelProjectMatrix
.m
, R200_MTX_MVP
);
2305 /* Need these for lighting (shouldn't upload otherwise)
2307 if (new_state
& (_NEW_MODELVIEW
)) {
2308 upload_matrix( rmesa
, ctx
->ModelviewMatrixStack
.Top
->m
, R200_MTX_MV
);
2309 upload_matrix_t( rmesa
, ctx
->ModelviewMatrixStack
.Top
->inv
, R200_MTX_IMV
);
2312 /* Does this need to be triggered on eg. modelview for
2313 * texgen-derived objplane/eyeplane matrices?
2315 if (new_state
& (_NEW_TEXTURE
|_NEW_TEXTURE_MATRIX
)) {
2316 update_texturematrix( ctx
);
2319 if (new_state
& (_NEW_LIGHT
|_NEW_MODELVIEW
|_MESA_NEW_NEED_EYE_COORDS
)) {
2320 update_light( ctx
);
2323 /* emit all active clip planes if projection matrix changes.
2325 if (new_state
& (_NEW_PROJECTION
)) {
2326 if (ctx
->Transform
.ClipPlanesEnabled
)
2327 r200UpdateClipPlanes( ctx
);
2331 rmesa
->NewGLState
= 0;
2335 static void r200InvalidateState( GLcontext
*ctx
, GLuint new_state
)
2337 _swrast_InvalidateState( ctx
, new_state
);
2338 _swsetup_InvalidateState( ctx
, new_state
);
2339 _ac_InvalidateState( ctx
, new_state
);
2340 _tnl_InvalidateState( ctx
, new_state
);
2341 _ae_invalidate_state( ctx
, new_state
);
2342 R200_CONTEXT(ctx
)->NewGLState
|= new_state
;
2343 r200VtxfmtInvalidate( ctx
);
2346 /* A hack. The r200 can actually cope just fine with materials
2347 * between begin/ends, so fix this. But how ?
2349 static GLboolean
check_material( GLcontext
*ctx
)
2351 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
2354 for (i
= _TNL_ATTRIB_MAT_FRONT_AMBIENT
;
2355 i
< _TNL_ATTRIB_MAT_BACK_INDEXES
;
2357 if (tnl
->vb
.AttribPtr
[i
] &&
2358 tnl
->vb
.AttribPtr
[i
]->stride
)
2364 static void r200WrapRunPipeline( GLcontext
*ctx
)
2366 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2367 GLboolean has_material
;
2370 fprintf(stderr
, "%s, newstate: %x\n", __FUNCTION__
, rmesa
->NewGLState
);
2374 if (rmesa
->NewGLState
)
2375 r200ValidateState( ctx
);
2377 has_material
= (ctx
->Light
.Enabled
&& check_material( ctx
));
2380 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_TRUE
);
2383 /* Run the pipeline.
2385 _tnl_run_pipeline( ctx
);
2388 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_FALSE
);
2393 /* Initialize the driver's state functions.
2395 void r200InitStateFuncs( struct dd_function_table
*functions
)
2397 functions
->UpdateState
= r200InvalidateState
;
2398 functions
->LightingSpaceChange
= r200LightingSpaceChange
;
2400 functions
->DrawBuffer
= r200DrawBuffer
;
2401 functions
->ReadBuffer
= r200ReadBuffer
;
2403 functions
->AlphaFunc
= r200AlphaFunc
;
2404 functions
->BlendColor
= r200BlendColor
;
2405 functions
->BlendEquationSeparate
= r200BlendEquationSeparate
;
2406 functions
->BlendFuncSeparate
= r200BlendFuncSeparate
;
2407 functions
->ClearColor
= r200ClearColor
;
2408 functions
->ClearDepth
= r200ClearDepth
;
2409 functions
->ClearIndex
= NULL
;
2410 functions
->ClearStencil
= r200ClearStencil
;
2411 functions
->ClipPlane
= r200ClipPlane
;
2412 functions
->ColorMask
= r200ColorMask
;
2413 functions
->CullFace
= r200CullFace
;
2414 functions
->DepthFunc
= r200DepthFunc
;
2415 functions
->DepthMask
= r200DepthMask
;
2416 functions
->DepthRange
= r200DepthRange
;
2417 functions
->Enable
= r200Enable
;
2418 functions
->Fogfv
= r200Fogfv
;
2419 functions
->FrontFace
= r200FrontFace
;
2420 functions
->Hint
= NULL
;
2421 functions
->IndexMask
= NULL
;
2422 functions
->LightModelfv
= r200LightModelfv
;
2423 functions
->Lightfv
= r200Lightfv
;
2424 functions
->LineStipple
= r200LineStipple
;
2425 functions
->LineWidth
= r200LineWidth
;
2426 functions
->LogicOpcode
= r200LogicOpCode
;
2427 functions
->PolygonMode
= r200PolygonMode
;
2428 functions
->PolygonOffset
= r200PolygonOffset
;
2429 functions
->PolygonStipple
= r200PolygonStipple
;
2430 functions
->PointSize
= r200PointSize
;
2431 functions
->RenderMode
= r200RenderMode
;
2432 functions
->Scissor
= r200Scissor
;
2433 functions
->ShadeModel
= r200ShadeModel
;
2434 functions
->StencilFuncSeparate
= r200StencilFuncSeparate
;
2435 functions
->StencilMaskSeparate
= r200StencilMaskSeparate
;
2436 functions
->StencilOpSeparate
= r200StencilOpSeparate
;
2437 functions
->Viewport
= r200Viewport
;
2439 /* Swrast hooks for imaging extensions:
2441 functions
->CopyColorTable
= _swrast_CopyColorTable
;
2442 functions
->CopyColorSubTable
= _swrast_CopyColorSubTable
;
2443 functions
->CopyConvolutionFilter1D
= _swrast_CopyConvolutionFilter1D
;
2444 functions
->CopyConvolutionFilter2D
= _swrast_CopyConvolutionFilter2D
;
2448 void r200InitTnlFuncs( GLcontext
*ctx
)
2450 TNL_CONTEXT(ctx
)->Driver
.NotifyMaterialChange
= r200UpdateMaterial
;
2451 TNL_CONTEXT(ctx
)->Driver
.RunPipeline
= r200WrapRunPipeline
;