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"
45 #include "swrast/swrast.h"
46 #include "array_cache/acache.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_vtxfmt.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
._LogicOpEnabled
) {
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
._LogicOpEnabled
) {
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 fmt_0
= rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_0
];
490 GLuint out_0
= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
];
491 GLuint fog
= rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
];
493 fog
&= ~R200_FOG_USE_MASK
;
494 if ( ctx
->Fog
.FogCoordinateSource
== GL_FOG_COORD
) {
495 fog
|= R200_FOG_USE_VTX_FOG
;
496 fmt_0
|= R200_VTX_DISCRETE_FOG
;
497 out_0
|= R200_VTX_DISCRETE_FOG
;
500 fog
|= R200_FOG_USE_SPEC_ALPHA
;
501 fmt_0
&= ~R200_VTX_DISCRETE_FOG
;
502 out_0
&= ~R200_VTX_DISCRETE_FOG
;
505 if ( fog
!= rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] ) {
506 R200_STATECHANGE( rmesa
, ctx
);
507 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] = fog
;
510 if ( (fmt_0
!= rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_0
])
511 || (out_0
!= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
])) {
512 R200_STATECHANGE( rmesa
, vtx
);
513 rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_0
] = fmt_0
;
514 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] = out_0
;
523 if (c
.i
!= rmesa
->hw
.fog
.cmd
[FOG_C
] || d
.i
!= rmesa
->hw
.fog
.cmd
[FOG_D
]) {
524 R200_STATECHANGE( rmesa
, fog
);
525 rmesa
->hw
.fog
.cmd
[FOG_C
] = c
.i
;
526 rmesa
->hw
.fog
.cmd
[FOG_D
] = d
.i
;
531 /* =============================================================
536 static GLboolean
intersect_rect( drm_clip_rect_t
*out
,
541 if ( b
->x1
> out
->x1
) out
->x1
= b
->x1
;
542 if ( b
->y1
> out
->y1
) out
->y1
= b
->y1
;
543 if ( b
->x2
< out
->x2
) out
->x2
= b
->x2
;
544 if ( b
->y2
< out
->y2
) out
->y2
= b
->y2
;
545 if ( out
->x1
>= out
->x2
) return GL_FALSE
;
546 if ( out
->y1
>= out
->y2
) return GL_FALSE
;
551 void r200RecalcScissorRects( r200ContextPtr rmesa
)
553 drm_clip_rect_t
*out
;
556 /* Grow cliprect store?
558 if (rmesa
->state
.scissor
.numAllocedClipRects
< rmesa
->numClipRects
) {
559 while (rmesa
->state
.scissor
.numAllocedClipRects
< rmesa
->numClipRects
) {
560 rmesa
->state
.scissor
.numAllocedClipRects
+= 1; /* zero case */
561 rmesa
->state
.scissor
.numAllocedClipRects
*= 2;
564 if (rmesa
->state
.scissor
.pClipRects
)
565 FREE(rmesa
->state
.scissor
.pClipRects
);
567 rmesa
->state
.scissor
.pClipRects
=
568 MALLOC( rmesa
->state
.scissor
.numAllocedClipRects
*
569 sizeof(drm_clip_rect_t
) );
571 if ( rmesa
->state
.scissor
.pClipRects
== NULL
) {
572 rmesa
->state
.scissor
.numAllocedClipRects
= 0;
577 out
= rmesa
->state
.scissor
.pClipRects
;
578 rmesa
->state
.scissor
.numClipRects
= 0;
580 for ( i
= 0 ; i
< rmesa
->numClipRects
; i
++ ) {
581 if ( intersect_rect( out
,
582 &rmesa
->pClipRects
[i
],
583 &rmesa
->state
.scissor
.rect
) ) {
584 rmesa
->state
.scissor
.numClipRects
++;
591 static void r200UpdateScissor( GLcontext
*ctx
)
593 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
595 if ( rmesa
->dri
.drawable
) {
596 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
598 int x
= ctx
->Scissor
.X
;
599 int y
= dPriv
->h
- ctx
->Scissor
.Y
- ctx
->Scissor
.Height
;
600 int w
= ctx
->Scissor
.X
+ ctx
->Scissor
.Width
- 1;
601 int h
= dPriv
->h
- ctx
->Scissor
.Y
- 1;
603 rmesa
->state
.scissor
.rect
.x1
= x
+ dPriv
->x
;
604 rmesa
->state
.scissor
.rect
.y1
= y
+ dPriv
->y
;
605 rmesa
->state
.scissor
.rect
.x2
= w
+ dPriv
->x
+ 1;
606 rmesa
->state
.scissor
.rect
.y2
= h
+ dPriv
->y
+ 1;
608 r200RecalcScissorRects( rmesa
);
613 static void r200Scissor( GLcontext
*ctx
,
614 GLint x
, GLint y
, GLsizei w
, GLsizei h
)
616 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
618 if ( ctx
->Scissor
.Enabled
) {
619 R200_FIREVERTICES( rmesa
); /* don't pipeline cliprect changes */
620 r200UpdateScissor( ctx
);
626 /* =============================================================
630 static void r200CullFace( GLcontext
*ctx
, GLenum unused
)
632 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
633 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
634 GLuint t
= rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
];
636 s
|= R200_FFACE_SOLID
| R200_BFACE_SOLID
;
637 t
&= ~(R200_CULL_FRONT
| R200_CULL_BACK
);
639 if ( ctx
->Polygon
.CullFlag
) {
640 switch ( ctx
->Polygon
.CullFaceMode
) {
642 s
&= ~R200_FFACE_SOLID
;
643 t
|= R200_CULL_FRONT
;
646 s
&= ~R200_BFACE_SOLID
;
649 case GL_FRONT_AND_BACK
:
650 s
&= ~(R200_FFACE_SOLID
| R200_BFACE_SOLID
);
651 t
|= (R200_CULL_FRONT
| R200_CULL_BACK
);
656 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
657 R200_STATECHANGE(rmesa
, set
);
658 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
661 if ( rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] != t
) {
662 R200_STATECHANGE(rmesa
, tcl
);
663 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] = t
;
667 static void r200FrontFace( GLcontext
*ctx
, GLenum mode
)
669 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
671 R200_STATECHANGE( rmesa
, set
);
672 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_FFACE_CULL_DIR_MASK
;
674 R200_STATECHANGE( rmesa
, tcl
);
675 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_CULL_FRONT_IS_CCW
;
679 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_FFACE_CULL_CW
;
682 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_FFACE_CULL_CCW
;
683 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_CULL_FRONT_IS_CCW
;
688 /* =============================================================
691 static void r200PointSize( GLcontext
*ctx
, GLfloat size
)
693 if (0) fprintf(stderr
, "%s: %f\n", __FUNCTION__
, size
);
696 /* =============================================================
699 static void r200LineWidth( GLcontext
*ctx
, GLfloat widthf
)
701 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
703 R200_STATECHANGE( rmesa
, lin
);
704 R200_STATECHANGE( rmesa
, set
);
706 /* Line width is stored in U6.4 format.
708 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] &= ~0xffff;
709 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] |= (GLuint
)(ctx
->Line
._Width
* 16.0);
711 if ( widthf
> 1.0 ) {
712 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_WIDELINE_ENABLE
;
714 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_WIDELINE_ENABLE
;
718 static void r200LineStipple( GLcontext
*ctx
, GLint factor
, GLushort pattern
)
720 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
722 R200_STATECHANGE( rmesa
, lin
);
723 rmesa
->hw
.lin
.cmd
[LIN_RE_LINE_PATTERN
] =
724 ((((GLuint
)factor
& 0xff) << 16) | ((GLuint
)pattern
));
728 /* =============================================================
731 static void r200ColorMask( GLcontext
*ctx
,
732 GLboolean r
, GLboolean g
,
733 GLboolean b
, GLboolean a
)
735 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
736 GLuint mask
= r200PackColor( rmesa
->r200Screen
->cpp
,
737 ctx
->Color
.ColorMask
[RCOMP
],
738 ctx
->Color
.ColorMask
[GCOMP
],
739 ctx
->Color
.ColorMask
[BCOMP
],
740 ctx
->Color
.ColorMask
[ACOMP
] );
742 GLuint flag
= rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] & ~R200_PLANE_MASK_ENABLE
;
744 if (!(r
&& g
&& b
&& a
))
745 flag
|= R200_PLANE_MASK_ENABLE
;
747 if ( rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] != flag
) {
748 R200_STATECHANGE( rmesa
, ctx
);
749 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = flag
;
752 if ( rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
] != mask
) {
753 R200_STATECHANGE( rmesa
, msk
);
754 rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
] = mask
;
759 /* =============================================================
763 static void r200PolygonOffset( GLcontext
*ctx
,
764 GLfloat factor
, GLfloat units
)
766 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
767 GLfloat constant
= units
* rmesa
->state
.depth
.scale
;
772 /* fprintf(stderr, "%s f:%f u:%f\n", __FUNCTION__, factor, constant); */
774 R200_STATECHANGE( rmesa
, zbs
);
775 rmesa
->hw
.zbs
.cmd
[ZBS_SE_ZBIAS_FACTOR
] = *(GLuint
*)&factor
;
776 rmesa
->hw
.zbs
.cmd
[ZBS_SE_ZBIAS_CONSTANT
] = *(GLuint
*)&constant
;
779 static void r200PolygonStipple( GLcontext
*ctx
, const GLubyte
*mask
)
781 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
783 drm_radeon_stipple_t stipple
;
785 /* Must flip pattern upside down.
787 for ( i
= 0 ; i
< 32 ; i
++ ) {
788 rmesa
->state
.stipple
.mask
[31 - i
] = ((GLuint
*) mask
)[i
];
791 /* TODO: push this into cmd mechanism
793 R200_FIREVERTICES( rmesa
);
794 LOCK_HARDWARE( rmesa
);
796 /* FIXME: Use window x,y offsets into stipple RAM.
798 stipple
.mask
= rmesa
->state
.stipple
.mask
;
799 drmCommandWrite( rmesa
->dri
.fd
, DRM_RADEON_STIPPLE
,
800 &stipple
, sizeof(stipple
) );
801 UNLOCK_HARDWARE( rmesa
);
804 static void r200PolygonMode( GLcontext
*ctx
, GLenum face
, GLenum mode
)
806 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
807 GLboolean flag
= (ctx
->_TriangleCaps
& DD_TRI_UNFILLED
) != 0;
809 /* Can't generally do unfilled via tcl, but some good special
812 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_UNFILLED
, flag
);
813 if (rmesa
->TclFallback
) {
814 r200ChooseRenderState( ctx
);
815 r200ChooseVertexState( ctx
);
820 /* =============================================================
821 * Rendering attributes
823 * We really don't want to recalculate all this every time we bind a
824 * texture. These things shouldn't change all that often, so it makes
825 * sense to break them out of the core texture state update routines.
828 /* Examine lighting and texture state to determine if separate specular
831 static void r200UpdateSpecular( GLcontext
*ctx
)
833 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
834 u_int32_t p
= rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
];
836 R200_STATECHANGE( rmesa
, tcl
);
837 R200_STATECHANGE( rmesa
, vtx
);
839 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~(3<<R200_VTX_COLOR_0_SHIFT
);
840 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~(3<<R200_VTX_COLOR_1_SHIFT
);
841 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_COLOR_0
;
842 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_COLOR_1
;
843 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LIGHTING_ENABLE
;
845 p
&= ~R200_SPECULAR_ENABLE
;
847 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_DIFFUSE_SPECULAR_COMBINE
;
850 if (ctx
->Light
.Enabled
&&
851 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
) {
852 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
853 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
) |
854 (R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
855 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_0
;
856 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_1
;
857 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHTING_ENABLE
;
858 p
|= R200_SPECULAR_ENABLE
;
859 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &=
860 ~R200_DIFFUSE_SPECULAR_COMBINE
;
862 else if (ctx
->Light
.Enabled
) {
863 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
864 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
));
865 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_0
;
866 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHTING_ENABLE
;
867 } else if (ctx
->Fog
.ColorSumEnabled
) {
868 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
869 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
) |
870 (R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
871 p
|= R200_SPECULAR_ENABLE
;
873 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
874 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
));
877 if (ctx
->Fog
.Enabled
) {
878 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
879 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
880 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_1
;
883 if ( rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] != p
) {
884 R200_STATECHANGE( rmesa
, ctx
);
885 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] = p
;
888 /* Update vertex/render formats
890 if (rmesa
->TclFallback
) {
891 r200ChooseRenderState( ctx
);
892 r200ChooseVertexState( ctx
);
897 /* =============================================================
902 /* Update on colormaterial, material emmissive/ambient,
903 * lightmodel.globalambient
905 static void update_global_ambient( GLcontext
*ctx
)
907 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
908 float *fcmd
= (float *)R200_DB_STATE( glt
);
910 /* Need to do more if both emmissive & ambient are PREMULT:
911 * I believe this is not nessary when using source_material. This condition thus
912 * will never happen currently, and the function has no dependencies on materials now
914 if ((rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
] &
915 ((3 << R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
916 (3 << R200_FRONT_AMBIENT_SOURCE_SHIFT
))) == 0)
918 COPY_3V( &fcmd
[GLT_RED
],
919 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_EMISSION
]);
920 ACC_SCALE_3V( &fcmd
[GLT_RED
],
921 ctx
->Light
.Model
.Ambient
,
922 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_AMBIENT
]);
926 COPY_3V( &fcmd
[GLT_RED
], ctx
->Light
.Model
.Ambient
);
929 R200_DB_STATECHANGE(rmesa
, &rmesa
->hw
.glt
);
932 /* Update on change to
936 static void update_light_colors( GLcontext
*ctx
, GLuint p
)
938 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
940 /* fprintf(stderr, "%s\n", __FUNCTION__); */
943 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
944 float *fcmd
= (float *)R200_DB_STATE( lit
[p
] );
946 COPY_4V( &fcmd
[LIT_AMBIENT_RED
], l
->Ambient
);
947 COPY_4V( &fcmd
[LIT_DIFFUSE_RED
], l
->Diffuse
);
948 COPY_4V( &fcmd
[LIT_SPECULAR_RED
], l
->Specular
);
950 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
954 static void r200ColorMaterial( GLcontext
*ctx
, GLenum face
, GLenum mode
)
956 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
957 GLuint light_model_ctl1
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
];
958 light_model_ctl1
&= ~((0xf << R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
959 (0xf << R200_FRONT_AMBIENT_SOURCE_SHIFT
) |
960 (0xf << R200_FRONT_DIFFUSE_SOURCE_SHIFT
) |
961 (0xf << R200_FRONT_SPECULAR_SOURCE_SHIFT
) |
962 (0xf << R200_BACK_EMISSIVE_SOURCE_SHIFT
) |
963 (0xf << R200_BACK_AMBIENT_SOURCE_SHIFT
) |
964 (0xf << R200_BACK_DIFFUSE_SOURCE_SHIFT
) |
965 (0xf << R200_BACK_SPECULAR_SOURCE_SHIFT
));
967 if (ctx
->Light
.ColorMaterialEnabled
) {
968 GLuint mask
= ctx
->Light
.ColorMaterialBitmask
;
970 if (mask
& MAT_BIT_FRONT_EMISSION
) {
971 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
972 R200_FRONT_EMISSIVE_SOURCE_SHIFT
);
975 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
976 R200_FRONT_EMISSIVE_SOURCE_SHIFT
);
978 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
979 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
980 R200_FRONT_AMBIENT_SOURCE_SHIFT
);
983 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
984 R200_FRONT_AMBIENT_SOURCE_SHIFT
);
986 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
987 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
988 R200_FRONT_DIFFUSE_SOURCE_SHIFT
);
991 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
992 R200_FRONT_DIFFUSE_SOURCE_SHIFT
);
994 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
995 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
996 R200_FRONT_SPECULAR_SOURCE_SHIFT
);
999 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
1000 R200_FRONT_SPECULAR_SOURCE_SHIFT
);
1003 if (mask
& MAT_BIT_BACK_EMISSION
) {
1004 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
1005 R200_BACK_EMISSIVE_SOURCE_SHIFT
);
1008 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
1009 R200_BACK_EMISSIVE_SOURCE_SHIFT
);
1011 if (mask
& MAT_BIT_BACK_AMBIENT
) {
1012 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
1013 R200_BACK_AMBIENT_SOURCE_SHIFT
);
1015 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
1016 R200_BACK_AMBIENT_SOURCE_SHIFT
);
1018 if (mask
& MAT_BIT_BACK_DIFFUSE
) {
1019 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
1020 R200_BACK_DIFFUSE_SOURCE_SHIFT
);
1022 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
1023 R200_BACK_DIFFUSE_SOURCE_SHIFT
);
1025 if (mask
& MAT_BIT_BACK_SPECULAR
) {
1026 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
1027 R200_BACK_SPECULAR_SOURCE_SHIFT
);
1030 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
1031 R200_BACK_SPECULAR_SOURCE_SHIFT
);
1035 /* Default to SOURCE_MATERIAL:
1038 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
1039 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_AMBIENT_SOURCE_SHIFT
) |
1040 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_DIFFUSE_SOURCE_SHIFT
) |
1041 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_SPECULAR_SOURCE_SHIFT
) |
1042 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_EMISSIVE_SOURCE_SHIFT
) |
1043 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_AMBIENT_SOURCE_SHIFT
) |
1044 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_DIFFUSE_SOURCE_SHIFT
) |
1045 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_SPECULAR_SOURCE_SHIFT
);
1048 if (light_model_ctl1
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
]) {
1049 R200_STATECHANGE( rmesa
, tcl
);
1050 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
] = light_model_ctl1
;
1056 void r200UpdateMaterial( GLcontext
*ctx
)
1058 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1059 GLfloat (*mat
)[4] = ctx
->Light
.Material
.Attrib
;
1060 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( mtl
[0] );
1061 GLfloat
*fcmd2
= (GLfloat
*)R200_DB_STATE( mtl
[1] );
1064 /* Might be possible and faster to update everything unconditionally? */
1065 if (ctx
->Light
.ColorMaterialEnabled
)
1066 mask
&= ~ctx
->Light
.ColorMaterialBitmask
;
1068 if (R200_DEBUG
& DEBUG_STATE
)
1069 fprintf(stderr
, "%s\n", __FUNCTION__
);
1071 if (mask
& MAT_BIT_FRONT_EMISSION
) {
1072 fcmd
[MTL_EMMISSIVE_RED
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][0];
1073 fcmd
[MTL_EMMISSIVE_GREEN
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][1];
1074 fcmd
[MTL_EMMISSIVE_BLUE
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][2];
1075 fcmd
[MTL_EMMISSIVE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][3];
1077 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
1078 fcmd
[MTL_AMBIENT_RED
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][0];
1079 fcmd
[MTL_AMBIENT_GREEN
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][1];
1080 fcmd
[MTL_AMBIENT_BLUE
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][2];
1081 fcmd
[MTL_AMBIENT_ALPHA
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][3];
1083 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
1084 fcmd
[MTL_DIFFUSE_RED
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][0];
1085 fcmd
[MTL_DIFFUSE_GREEN
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][1];
1086 fcmd
[MTL_DIFFUSE_BLUE
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][2];
1087 fcmd
[MTL_DIFFUSE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][3];
1089 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
1090 fcmd
[MTL_SPECULAR_RED
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][0];
1091 fcmd
[MTL_SPECULAR_GREEN
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][1];
1092 fcmd
[MTL_SPECULAR_BLUE
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][2];
1093 fcmd
[MTL_SPECULAR_ALPHA
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][3];
1095 if (mask
& MAT_BIT_FRONT_SHININESS
) {
1096 fcmd
[MTL_SHININESS
] = mat
[MAT_ATTRIB_FRONT_SHININESS
][0];
1099 if (mask
& MAT_BIT_BACK_EMISSION
) {
1100 fcmd2
[MTL_EMMISSIVE_RED
] = mat
[MAT_ATTRIB_BACK_EMISSION
][0];
1101 fcmd2
[MTL_EMMISSIVE_GREEN
] = mat
[MAT_ATTRIB_BACK_EMISSION
][1];
1102 fcmd2
[MTL_EMMISSIVE_BLUE
] = mat
[MAT_ATTRIB_BACK_EMISSION
][2];
1103 fcmd2
[MTL_EMMISSIVE_ALPHA
] = mat
[MAT_ATTRIB_BACK_EMISSION
][3];
1105 if (mask
& MAT_BIT_BACK_AMBIENT
) {
1106 fcmd2
[MTL_AMBIENT_RED
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][0];
1107 fcmd2
[MTL_AMBIENT_GREEN
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][1];
1108 fcmd2
[MTL_AMBIENT_BLUE
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][2];
1109 fcmd2
[MTL_AMBIENT_ALPHA
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][3];
1111 if (mask
& MAT_BIT_BACK_DIFFUSE
) {
1112 fcmd2
[MTL_DIFFUSE_RED
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][0];
1113 fcmd2
[MTL_DIFFUSE_GREEN
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][1];
1114 fcmd2
[MTL_DIFFUSE_BLUE
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][2];
1115 fcmd2
[MTL_DIFFUSE_ALPHA
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][3];
1117 if (mask
& MAT_BIT_BACK_SPECULAR
) {
1118 fcmd2
[MTL_SPECULAR_RED
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][0];
1119 fcmd2
[MTL_SPECULAR_GREEN
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][1];
1120 fcmd2
[MTL_SPECULAR_BLUE
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][2];
1121 fcmd2
[MTL_SPECULAR_ALPHA
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][3];
1123 if (mask
& MAT_BIT_BACK_SHININESS
) {
1124 fcmd2
[MTL_SHININESS
] = mat
[MAT_ATTRIB_BACK_SHININESS
][0];
1127 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mtl
[0] );
1128 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mtl
[1] );
1130 /* currently material changes cannot trigger a global ambient change, I believe this is correct
1131 update_global_ambient( ctx ); */
1136 * _MESA_NEW_NEED_EYE_COORDS
1138 * Uses derived state from mesa:
1143 * _ModelViewInvScale
1147 * which are calculated in light.c and are correct for the current
1148 * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
1149 * and _MESA_NEW_NEED_EYE_COORDS.
1151 static void update_light( GLcontext
*ctx
)
1153 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1155 /* Have to check these, or have an automatic shortcircuit mechanism
1156 * to remove noop statechanges. (Or just do a better job on the
1160 GLuint tmp
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
];
1162 if (ctx
->_NeedEyeCoords
)
1163 tmp
&= ~R200_LIGHT_IN_MODELSPACE
;
1165 tmp
|= R200_LIGHT_IN_MODELSPACE
;
1167 if (tmp
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
])
1169 R200_STATECHANGE( rmesa
, tcl
);
1170 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] = tmp
;
1175 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( eye
);
1176 fcmd
[EYE_X
] = ctx
->_EyeZDir
[0];
1177 fcmd
[EYE_Y
] = ctx
->_EyeZDir
[1];
1178 fcmd
[EYE_Z
] = - ctx
->_EyeZDir
[2];
1179 fcmd
[EYE_RESCALE_FACTOR
] = ctx
->_ModelViewInvScale
;
1180 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.eye
);
1185 if (ctx
->Light
.Enabled
) {
1187 for (p
= 0 ; p
< MAX_LIGHTS
; p
++) {
1188 if (ctx
->Light
.Light
[p
].Enabled
) {
1189 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1190 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( lit
[p
] );
1192 if (l
->EyePosition
[3] == 0.0) {
1193 COPY_3FV( &fcmd
[LIT_POSITION_X
], l
->_VP_inf_norm
);
1194 COPY_3FV( &fcmd
[LIT_DIRECTION_X
], l
->_h_inf_norm
);
1195 fcmd
[LIT_POSITION_W
] = 0;
1196 fcmd
[LIT_DIRECTION_W
] = 0;
1198 COPY_4V( &fcmd
[LIT_POSITION_X
], l
->_Position
);
1199 fcmd
[LIT_DIRECTION_X
] = -l
->_NormDirection
[0];
1200 fcmd
[LIT_DIRECTION_Y
] = -l
->_NormDirection
[1];
1201 fcmd
[LIT_DIRECTION_Z
] = -l
->_NormDirection
[2];
1202 fcmd
[LIT_DIRECTION_W
] = 0;
1205 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
1211 static void r200Lightfv( GLcontext
*ctx
, GLenum light
,
1212 GLenum pname
, const GLfloat
*params
)
1214 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1215 GLint p
= light
- GL_LIGHT0
;
1216 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1217 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.lit
[p
].cmd
;
1224 update_light_colors( ctx
, p
);
1227 case GL_SPOT_DIRECTION
:
1228 /* picked up in update_light */
1232 /* positions picked up in update_light, but can do flag here */
1233 GLuint flag
= (p
&1)? R200_LIGHT_1_IS_LOCAL
: R200_LIGHT_0_IS_LOCAL
;
1234 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1236 R200_STATECHANGE(rmesa
, tcl
);
1237 if (l
->EyePosition
[3] != 0.0F
)
1238 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1240 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1244 case GL_SPOT_EXPONENT
:
1245 R200_STATECHANGE(rmesa
, lit
[p
]);
1246 fcmd
[LIT_SPOT_EXPONENT
] = params
[0];
1249 case GL_SPOT_CUTOFF
: {
1250 GLuint flag
= (p
&1) ? R200_LIGHT_1_IS_SPOT
: R200_LIGHT_0_IS_SPOT
;
1251 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1253 R200_STATECHANGE(rmesa
, lit
[p
]);
1254 fcmd
[LIT_SPOT_CUTOFF
] = l
->_CosCutoff
;
1256 R200_STATECHANGE(rmesa
, tcl
);
1257 if (l
->SpotCutoff
!= 180.0F
)
1258 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1260 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1265 case GL_CONSTANT_ATTENUATION
:
1266 R200_STATECHANGE(rmesa
, lit
[p
]);
1267 fcmd
[LIT_ATTEN_CONST
] = params
[0];
1268 if ( params
[0] == 0.0 )
1269 fcmd
[LIT_ATTEN_CONST_INV
] = FLT_MAX
;
1271 fcmd
[LIT_ATTEN_CONST_INV
] = 1.0 / params
[0];
1273 case GL_LINEAR_ATTENUATION
:
1274 R200_STATECHANGE(rmesa
, lit
[p
]);
1275 fcmd
[LIT_ATTEN_LINEAR
] = params
[0];
1277 case GL_QUADRATIC_ATTENUATION
:
1278 R200_STATECHANGE(rmesa
, lit
[p
]);
1279 fcmd
[LIT_ATTEN_QUADRATIC
] = params
[0];
1285 /* Set RANGE_ATTEN only when needed */
1288 case GL_CONSTANT_ATTENUATION
:
1289 case GL_LINEAR_ATTENUATION
:
1290 case GL_QUADRATIC_ATTENUATION
: {
1291 GLuint
*icmd
= (GLuint
*)R200_DB_STATE( tcl
);
1292 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1293 GLuint atten_flag
= ( p
&1 ) ? R200_LIGHT_1_ENABLE_RANGE_ATTEN
1294 : R200_LIGHT_0_ENABLE_RANGE_ATTEN
;
1295 GLuint atten_const_flag
= ( p
&1 ) ? R200_LIGHT_1_CONSTANT_RANGE_ATTEN
1296 : R200_LIGHT_0_CONSTANT_RANGE_ATTEN
;
1298 if ( l
->EyePosition
[3] == 0.0F
||
1299 ( ( fcmd
[LIT_ATTEN_CONST
] == 0.0 || fcmd
[LIT_ATTEN_CONST
] == 1.0 ) &&
1300 fcmd
[LIT_ATTEN_QUADRATIC
] == 0.0 && fcmd
[LIT_ATTEN_LINEAR
] == 0.0 ) ) {
1301 /* Disable attenuation */
1302 icmd
[idx
] &= ~atten_flag
;
1304 if ( fcmd
[LIT_ATTEN_QUADRATIC
] == 0.0 && fcmd
[LIT_ATTEN_LINEAR
] == 0.0 ) {
1305 /* Enable only constant portion of attenuation calculation */
1306 icmd
[idx
] |= ( atten_flag
| atten_const_flag
);
1308 /* Enable full attenuation calculation */
1309 icmd
[idx
] &= ~atten_const_flag
;
1310 icmd
[idx
] |= atten_flag
;
1314 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.tcl
);
1325 static void r200LightModelfv( GLcontext
*ctx
, GLenum pname
,
1326 const GLfloat
*param
)
1328 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1331 case GL_LIGHT_MODEL_AMBIENT
:
1332 update_global_ambient( ctx
);
1335 case GL_LIGHT_MODEL_LOCAL_VIEWER
:
1336 R200_STATECHANGE( rmesa
, tcl
);
1337 if (ctx
->Light
.Model
.LocalViewer
)
1338 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LOCAL_VIEWER
;
1340 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LOCAL_VIEWER
;
1343 case GL_LIGHT_MODEL_TWO_SIDE
:
1344 R200_STATECHANGE( rmesa
, tcl
);
1345 if (ctx
->Light
.Model
.TwoSide
)
1346 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHT_TWOSIDE
;
1348 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~(R200_LIGHT_TWOSIDE
);
1349 if (rmesa
->TclFallback
) {
1350 r200ChooseRenderState( ctx
);
1351 r200ChooseVertexState( ctx
);
1355 case GL_LIGHT_MODEL_COLOR_CONTROL
:
1356 r200UpdateSpecular(ctx
);
1364 static void r200ShadeModel( GLcontext
*ctx
, GLenum mode
)
1366 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1367 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
1369 s
&= ~(R200_DIFFUSE_SHADE_MASK
|
1370 R200_ALPHA_SHADE_MASK
|
1371 R200_SPECULAR_SHADE_MASK
|
1372 R200_FOG_SHADE_MASK
);
1376 s
|= (R200_DIFFUSE_SHADE_FLAT
|
1377 R200_ALPHA_SHADE_FLAT
|
1378 R200_SPECULAR_SHADE_FLAT
|
1379 R200_FOG_SHADE_FLAT
);
1382 s
|= (R200_DIFFUSE_SHADE_GOURAUD
|
1383 R200_ALPHA_SHADE_GOURAUD
|
1384 R200_SPECULAR_SHADE_GOURAUD
|
1385 R200_FOG_SHADE_GOURAUD
);
1391 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
1392 R200_STATECHANGE( rmesa
, set
);
1393 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
1398 /* =============================================================
1402 static void r200ClipPlane( GLcontext
*ctx
, GLenum plane
, const GLfloat
*eq
)
1404 GLint p
= (GLint
) plane
- (GLint
) GL_CLIP_PLANE0
;
1405 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1406 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1408 R200_STATECHANGE( rmesa
, ucp
[p
] );
1409 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1410 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1411 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1412 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1415 static void r200UpdateClipPlanes( GLcontext
*ctx
)
1417 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1420 for (p
= 0; p
< ctx
->Const
.MaxClipPlanes
; p
++) {
1421 if (ctx
->Transform
.ClipPlanesEnabled
& (1 << p
)) {
1422 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1424 R200_STATECHANGE( rmesa
, ucp
[p
] );
1425 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1426 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1427 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1428 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1434 /* =============================================================
1438 static void r200StencilFunc( GLcontext
*ctx
, GLenum func
,
1439 GLint ref
, GLuint mask
)
1441 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1442 GLuint refmask
= ((ctx
->Stencil
.Ref
[0] << R200_STENCIL_REF_SHIFT
) |
1443 (ctx
->Stencil
.ValueMask
[0] << R200_STENCIL_MASK_SHIFT
));
1445 R200_STATECHANGE( rmesa
, ctx
);
1446 R200_STATECHANGE( rmesa
, msk
);
1448 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_STENCIL_TEST_MASK
;
1449 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~(R200_STENCIL_REF_MASK
|
1450 R200_STENCIL_VALUE_MASK
);
1452 switch ( ctx
->Stencil
.Function
[0] ) {
1454 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEVER
;
1457 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LESS
;
1460 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_EQUAL
;
1463 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LEQUAL
;
1466 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GREATER
;
1469 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEQUAL
;
1472 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GEQUAL
;
1475 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_ALWAYS
;
1479 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |= refmask
;
1482 static void r200StencilMask( GLcontext
*ctx
, GLuint mask
)
1484 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1486 R200_STATECHANGE( rmesa
, msk
);
1487 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~R200_STENCIL_WRITE_MASK
;
1488 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |=
1489 (ctx
->Stencil
.WriteMask
[0] << R200_STENCIL_WRITEMASK_SHIFT
);
1492 static void r200StencilOp( GLcontext
*ctx
, GLenum fail
,
1493 GLenum zfail
, GLenum zpass
)
1495 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1497 R200_STATECHANGE( rmesa
, ctx
);
1498 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~(R200_STENCIL_FAIL_MASK
|
1499 R200_STENCIL_ZFAIL_MASK
|
1500 R200_STENCIL_ZPASS_MASK
);
1502 switch ( ctx
->Stencil
.FailFunc
[0] ) {
1504 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_KEEP
;
1507 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_ZERO
;
1510 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_REPLACE
;
1513 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC
;
1516 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC
;
1518 case GL_INCR_WRAP_EXT
:
1519 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC_WRAP
;
1521 case GL_DECR_WRAP_EXT
:
1522 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC_WRAP
;
1525 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INVERT
;
1529 switch ( ctx
->Stencil
.ZFailFunc
[0] ) {
1531 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_KEEP
;
1534 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_ZERO
;
1537 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_REPLACE
;
1540 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC
;
1543 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC
;
1545 case GL_INCR_WRAP_EXT
:
1546 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC_WRAP
;
1548 case GL_DECR_WRAP_EXT
:
1549 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC_WRAP
;
1552 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INVERT
;
1556 switch ( ctx
->Stencil
.ZPassFunc
[0] ) {
1558 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_KEEP
;
1561 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_ZERO
;
1564 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_REPLACE
;
1567 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC
;
1570 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC
;
1572 case GL_INCR_WRAP_EXT
:
1573 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC_WRAP
;
1575 case GL_DECR_WRAP_EXT
:
1576 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC_WRAP
;
1579 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INVERT
;
1584 static void r200ClearStencil( GLcontext
*ctx
, GLint s
)
1586 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1588 rmesa
->state
.stencil
.clear
=
1589 ((GLuint
) ctx
->Stencil
.Clear
|
1590 (0xff << R200_STENCIL_MASK_SHIFT
) |
1591 (ctx
->Stencil
.WriteMask
[0] << R200_STENCIL_WRITEMASK_SHIFT
));
1595 /* =============================================================
1596 * Window position and viewport transformation
1600 * To correctly position primitives:
1602 #define SUBPIXEL_X 0.125
1603 #define SUBPIXEL_Y 0.125
1605 void r200UpdateWindow( GLcontext
*ctx
)
1607 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1608 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
1609 GLfloat xoffset
= (GLfloat
)dPriv
->x
;
1610 GLfloat yoffset
= (GLfloat
)dPriv
->y
+ dPriv
->h
;
1611 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1613 GLfloat sx
= v
[MAT_SX
];
1614 GLfloat tx
= v
[MAT_TX
] + xoffset
+ SUBPIXEL_X
;
1615 GLfloat sy
= - v
[MAT_SY
];
1616 GLfloat ty
= (- v
[MAT_TY
]) + yoffset
+ SUBPIXEL_Y
;
1617 GLfloat sz
= v
[MAT_SZ
] * rmesa
->state
.depth
.scale
;
1618 GLfloat tz
= v
[MAT_TZ
] * rmesa
->state
.depth
.scale
;
1620 R200_FIREVERTICES( rmesa
);
1621 R200_STATECHANGE( rmesa
, vpt
);
1623 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XSCALE
] = *(GLuint
*)&sx
;
1624 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = *(GLuint
*)&tx
;
1625 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YSCALE
] = *(GLuint
*)&sy
;
1626 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = *(GLuint
*)&ty
;
1627 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZSCALE
] = *(GLuint
*)&sz
;
1628 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZOFFSET
] = *(GLuint
*)&tz
;
1633 static void r200Viewport( GLcontext
*ctx
, GLint x
, GLint y
,
1634 GLsizei width
, GLsizei height
)
1636 /* update size of Mesa/software ancillary buffers */
1637 _mesa_ResizeBuffersMESA();
1638 /* Don't pipeline viewport changes, conflict with window offset
1639 * setting below. Could apply deltas to rescue pipelined viewport
1640 * values, or keep the originals hanging around.
1642 R200_FIREVERTICES( R200_CONTEXT(ctx
) );
1643 r200UpdateWindow( ctx
);
1646 static void r200DepthRange( GLcontext
*ctx
, GLclampd nearval
,
1649 r200UpdateWindow( ctx
);
1652 void r200UpdateViewportOffset( GLcontext
*ctx
)
1654 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1655 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
1656 GLfloat xoffset
= (GLfloat
)dPriv
->x
;
1657 GLfloat yoffset
= (GLfloat
)dPriv
->y
+ dPriv
->h
;
1658 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1660 GLfloat tx
= v
[MAT_TX
] + xoffset
+ SUBPIXEL_X
;
1661 GLfloat ty
= (- v
[MAT_TY
]) + yoffset
+ SUBPIXEL_Y
;
1663 if ( rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] != *(GLuint
*)&tx
||
1664 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] != *(GLuint
*)&ty
)
1666 /* Note: this should also modify whatever data the context reset
1669 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = *(GLuint
*)&tx
;
1670 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = *(GLuint
*)&ty
;
1672 /* update polygon stipple x/y screen offset */
1675 GLuint m
= rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
];
1677 m
&= ~(R200_STIPPLE_X_OFFSET_MASK
|
1678 R200_STIPPLE_Y_OFFSET_MASK
);
1680 /* add magic offsets, then invert */
1681 stx
= 31 - ((rmesa
->dri
.drawable
->x
- 1) & R200_STIPPLE_COORD_MASK
);
1682 sty
= 31 - ((rmesa
->dri
.drawable
->y
+ rmesa
->dri
.drawable
->h
- 1)
1683 & R200_STIPPLE_COORD_MASK
);
1685 m
|= ((stx
<< R200_STIPPLE_X_OFFSET_SHIFT
) |
1686 (sty
<< R200_STIPPLE_Y_OFFSET_SHIFT
));
1688 if ( rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] != m
) {
1689 R200_STATECHANGE( rmesa
, msc
);
1690 rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] = m
;
1695 r200UpdateScissor( ctx
);
1700 /* =============================================================
1704 static void r200ClearColor( GLcontext
*ctx
, const GLfloat c
[4] )
1706 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1708 CLAMPED_FLOAT_TO_UBYTE(color
[0], c
[0]);
1709 CLAMPED_FLOAT_TO_UBYTE(color
[1], c
[1]);
1710 CLAMPED_FLOAT_TO_UBYTE(color
[2], c
[2]);
1711 CLAMPED_FLOAT_TO_UBYTE(color
[3], c
[3]);
1712 rmesa
->state
.color
.clear
= r200PackColor( rmesa
->r200Screen
->cpp
,
1714 color
[2], color
[3] );
1718 static void r200RenderMode( GLcontext
*ctx
, GLenum mode
)
1720 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1721 FALLBACK( rmesa
, R200_FALLBACK_RENDER_MODE
, (mode
!= GL_RENDER
) );
1725 static GLuint r200_rop_tab
[] = {
1728 R200_ROP_AND_REVERSE
,
1730 R200_ROP_AND_INVERTED
,
1737 R200_ROP_OR_REVERSE
,
1738 R200_ROP_COPY_INVERTED
,
1739 R200_ROP_OR_INVERTED
,
1744 static void r200LogicOpCode( GLcontext
*ctx
, GLenum opcode
)
1746 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1747 GLuint rop
= (GLuint
)opcode
- GL_CLEAR
;
1751 R200_STATECHANGE( rmesa
, msk
);
1752 rmesa
->hw
.msk
.cmd
[MSK_RB3D_ROPCNTL
] = r200_rop_tab
[rop
];
1756 void r200SetCliprects( r200ContextPtr rmesa
, GLenum mode
)
1758 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
1762 rmesa
->numClipRects
= dPriv
->numClipRects
;
1763 rmesa
->pClipRects
= dPriv
->pClipRects
;
1766 /* Can't ignore 2d windows if we are page flipping.
1768 if ( dPriv
->numBackClipRects
== 0 || rmesa
->doPageFlip
) {
1769 rmesa
->numClipRects
= dPriv
->numClipRects
;
1770 rmesa
->pClipRects
= dPriv
->pClipRects
;
1773 rmesa
->numClipRects
= dPriv
->numBackClipRects
;
1774 rmesa
->pClipRects
= dPriv
->pBackClipRects
;
1778 fprintf(stderr
, "bad mode in r200SetCliprects\n");
1782 if (rmesa
->state
.scissor
.enabled
)
1783 r200RecalcScissorRects( rmesa
);
1787 static void r200DrawBuffer( GLcontext
*ctx
, GLenum mode
)
1789 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1791 if (R200_DEBUG
& DEBUG_DRI
)
1792 fprintf(stderr
, "%s %s\n", __FUNCTION__
,
1793 _mesa_lookup_enum_by_nr( mode
));
1795 R200_FIREVERTICES(rmesa
); /* don't pipeline cliprect changes */
1798 * _ColorDrawBufferMask is easier to cope with than <mode>.
1799 * Check for software fallback, update cliprects.
1801 switch ( ctx
->DrawBuffer
->_ColorDrawBufferMask
[0] ) {
1802 case BUFFER_BIT_FRONT_LEFT
:
1803 FALLBACK( rmesa
, R200_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
1804 r200SetCliprects( rmesa
, GL_FRONT_LEFT
);
1806 case BUFFER_BIT_BACK_LEFT
:
1807 FALLBACK( rmesa
, R200_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
1808 r200SetCliprects( rmesa
, GL_BACK_LEFT
);
1811 /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */
1812 FALLBACK( rmesa
, R200_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
1816 /* We'll set the drawing engine's offset/pitch parameters later
1817 * when we update other state.
1822 static void r200ReadBuffer( GLcontext
*ctx
, GLenum mode
)
1824 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
1827 /* =============================================================
1828 * State enable/disable
1831 static void r200Enable( GLcontext
*ctx
, GLenum cap
, GLboolean state
)
1833 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1836 if ( R200_DEBUG
& DEBUG_STATE
)
1837 fprintf( stderr
, "%s( %s = %s )\n", __FUNCTION__
,
1838 _mesa_lookup_enum_by_nr( cap
),
1839 state
? "GL_TRUE" : "GL_FALSE" );
1842 /* Fast track this one...
1850 R200_STATECHANGE( rmesa
, ctx
);
1852 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ALPHA_TEST_ENABLE
;
1854 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ALPHA_TEST_ENABLE
;
1859 case GL_COLOR_LOGIC_OP
:
1860 r200_set_blend_state( ctx
);
1863 case GL_CLIP_PLANE0
:
1864 case GL_CLIP_PLANE1
:
1865 case GL_CLIP_PLANE2
:
1866 case GL_CLIP_PLANE3
:
1867 case GL_CLIP_PLANE4
:
1868 case GL_CLIP_PLANE5
:
1869 p
= cap
-GL_CLIP_PLANE0
;
1870 R200_STATECHANGE( rmesa
, tcl
);
1872 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= (R200_UCP_ENABLE_0
<<p
);
1873 r200ClipPlane( ctx
, cap
, NULL
);
1876 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~(R200_UCP_ENABLE_0
<<p
);
1880 case GL_COLOR_MATERIAL
:
1881 r200ColorMaterial( ctx
, 0, 0 );
1882 r200UpdateMaterial( ctx
);
1886 r200CullFace( ctx
, 0 );
1890 R200_STATECHANGE(rmesa
, ctx
);
1892 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_Z_ENABLE
;
1894 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_Z_ENABLE
;
1899 R200_STATECHANGE(rmesa
, ctx
);
1901 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_DITHER_ENABLE
;
1902 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~rmesa
->state
.color
.roundEnable
;
1904 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_DITHER_ENABLE
;
1905 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= rmesa
->state
.color
.roundEnable
;
1910 R200_STATECHANGE(rmesa
, ctx
);
1912 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_FOG_ENABLE
;
1913 r200Fogfv( ctx
, GL_FOG_MODE
, NULL
);
1915 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_FOG_ENABLE
;
1916 R200_STATECHANGE(rmesa
, tcl
);
1917 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_TCL_FOG_MASK
;
1919 r200UpdateSpecular( ctx
); /* for PK_SPEC */
1920 if (rmesa
->TclFallback
)
1921 r200ChooseVertexState( ctx
);
1922 _mesa_allow_light_in_model( ctx
, !state
);
1933 R200_STATECHANGE(rmesa
, tcl
);
1934 p
= cap
- GL_LIGHT0
;
1936 flag
= (R200_LIGHT_1_ENABLE
|
1937 R200_LIGHT_1_ENABLE_AMBIENT
|
1938 R200_LIGHT_1_ENABLE_SPECULAR
);
1940 flag
= (R200_LIGHT_0_ENABLE
|
1941 R200_LIGHT_0_ENABLE_AMBIENT
|
1942 R200_LIGHT_0_ENABLE_SPECULAR
);
1945 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] |= flag
;
1947 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] &= ~flag
;
1951 update_light_colors( ctx
, p
);
1955 r200UpdateSpecular(ctx
);
1958 case GL_LINE_SMOOTH
:
1959 R200_STATECHANGE( rmesa
, ctx
);
1961 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_LINE
;
1963 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_LINE
;
1967 case GL_LINE_STIPPLE
:
1968 R200_STATECHANGE( rmesa
, set
);
1970 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_PATTERN_ENABLE
;
1972 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_PATTERN_ENABLE
;
1977 R200_STATECHANGE( rmesa
, tcl
);
1979 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_NORMALIZE_NORMALS
;
1981 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_NORMALIZE_NORMALS
;
1985 /* Pointsize registers on r200 don't seem to do anything. Maybe
1986 * have to pass pointsizes as vertex parameters? In any case,
1987 * setting pointmin == pointsizemax == 1.0, and doing nothing
1988 * for aa is enough to satisfy conform.
1990 case GL_POINT_SMOOTH
:
1993 /* These don't really do anything, as we don't use the 3vtx
1997 case GL_POLYGON_OFFSET_POINT
:
1998 R200_STATECHANGE( rmesa
, set
);
2000 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_POINT
;
2002 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_POINT
;
2006 case GL_POLYGON_OFFSET_LINE
:
2007 R200_STATECHANGE( rmesa
, set
);
2009 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_LINE
;
2011 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_LINE
;
2016 case GL_POLYGON_OFFSET_FILL
:
2017 R200_STATECHANGE( rmesa
, set
);
2019 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_TRI
;
2021 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_TRI
;
2025 case GL_POLYGON_SMOOTH
:
2026 R200_STATECHANGE( rmesa
, ctx
);
2028 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_POLY
;
2030 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_POLY
;
2034 case GL_POLYGON_STIPPLE
:
2035 R200_STATECHANGE(rmesa
, set
);
2037 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_STIPPLE_ENABLE
;
2039 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_STIPPLE_ENABLE
;
2043 case GL_RESCALE_NORMAL_EXT
: {
2044 GLboolean tmp
= ctx
->_NeedEyeCoords
? state
: !state
;
2045 R200_STATECHANGE( rmesa
, tcl
);
2047 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
2049 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
2054 case GL_SCISSOR_TEST
:
2055 R200_FIREVERTICES( rmesa
);
2056 rmesa
->state
.scissor
.enabled
= state
;
2057 r200UpdateScissor( ctx
);
2060 case GL_STENCIL_TEST
:
2061 if ( rmesa
->state
.stencil
.hwBuffer
) {
2062 R200_STATECHANGE( rmesa
, ctx
);
2064 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_STENCIL_ENABLE
;
2066 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_STENCIL_ENABLE
;
2069 FALLBACK( rmesa
, R200_FALLBACK_STENCIL
, state
);
2073 case GL_TEXTURE_GEN_Q
:
2074 case GL_TEXTURE_GEN_R
:
2075 case GL_TEXTURE_GEN_S
:
2076 case GL_TEXTURE_GEN_T
:
2077 /* Picked up in r200UpdateTextureState.
2079 rmesa
->recheck_texgen
[ctx
->Texture
.CurrentUnit
] = GL_TRUE
;
2082 case GL_COLOR_SUM_EXT
:
2083 r200UpdateSpecular ( ctx
);
2086 case GL_VERTEX_PROGRAM_ARB
:
2087 TCL_FALLBACK(rmesa
->glCtx
, R200_TCL_FALLBACK_TCL_DISABLE
, state
);
2096 void r200LightingSpaceChange( GLcontext
*ctx
)
2098 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2101 if (R200_DEBUG
& DEBUG_STATE
)
2102 fprintf(stderr
, "%s %d BEFORE %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
2103 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
2105 if (ctx
->_NeedEyeCoords
)
2106 tmp
= ctx
->Transform
.RescaleNormals
;
2108 tmp
= !ctx
->Transform
.RescaleNormals
;
2110 R200_STATECHANGE( rmesa
, tcl
);
2112 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
2114 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
2117 if (R200_DEBUG
& DEBUG_STATE
)
2118 fprintf(stderr
, "%s %d AFTER %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
2119 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
2122 /* =============================================================
2123 * Deferred state management - matrices, textures, other?
2129 static void upload_matrix( r200ContextPtr rmesa
, GLfloat
*src
, int idx
)
2131 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
2135 for (i
= 0 ; i
< 4 ; i
++) {
2139 *dest
++ = src
[i
+12];
2142 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
2145 static void upload_matrix_t( r200ContextPtr rmesa
, const GLfloat
*src
, int idx
)
2147 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
2148 memcpy(dest
, src
, 16*sizeof(float));
2149 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
2153 static void update_texturematrix( GLcontext
*ctx
)
2155 r200ContextPtr rmesa
= R200_CONTEXT( ctx
);
2156 GLuint tpc
= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
];
2157 GLuint compsel
= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
];
2160 if (R200_DEBUG
& DEBUG_STATE
)
2161 fprintf(stderr
, "%s before COMPSEL: %x\n", __FUNCTION__
,
2162 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]);
2164 rmesa
->TexMatEnabled
= 0;
2165 rmesa
->TexMatCompSel
= 0;
2167 for (unit
= 0 ; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
2168 if (!ctx
->Texture
.Unit
[unit
]._ReallyEnabled
)
2171 if (ctx
->TextureMatrixStack
[unit
].Top
->type
!= MATRIX_IDENTITY
) {
2172 rmesa
->TexMatEnabled
|= (R200_TEXGEN_TEXMAT_0_ENABLE
|
2173 R200_TEXMAT_0_ENABLE
) << unit
;
2175 rmesa
->TexMatCompSel
|= R200_OUTPUT_TEX_0
<< unit
;
2177 if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2178 /* Need to preconcatenate any active texgen
2179 * obj/eyeplane matrices:
2181 _math_matrix_mul_matrix( &rmesa
->tmpmat
,
2182 ctx
->TextureMatrixStack
[unit
].Top
,
2183 &rmesa
->TexGenMatrix
[unit
] );
2184 upload_matrix( rmesa
, rmesa
->tmpmat
.m
, R200_MTX_TEX0
+unit
);
2187 upload_matrix( rmesa
, ctx
->TextureMatrixStack
[unit
].Top
->m
,
2188 R200_MTX_TEX0
+unit
);
2191 else if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2192 upload_matrix( rmesa
, rmesa
->TexGenMatrix
[unit
].m
,
2193 R200_MTX_TEX0
+unit
);
2197 tpc
= (rmesa
->TexMatEnabled
| rmesa
->TexGenEnabled
);
2198 if (tpc
!= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
]) {
2199 R200_STATECHANGE(rmesa
, tcg
);
2200 rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
] = tpc
;
2203 compsel
&= ~R200_OUTPUT_TEX_MASK
;
2204 compsel
|= rmesa
->TexMatCompSel
| rmesa
->TexGenCompSel
;
2205 if (compsel
!= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]) {
2206 R200_STATECHANGE(rmesa
, vtx
);
2207 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] = compsel
;
2214 * Tell the card where to render (offset, pitch).
2215 * Effected by glDrawBuffer, etc
2218 r200UpdateDrawBuffer(GLcontext
*ctx
)
2220 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2221 struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
2222 driRenderbuffer
*drb
;
2224 if (fb
->_ColorDrawBufferMask
[0] == BUFFER_BIT_FRONT_LEFT
) {
2226 drb
= (driRenderbuffer
*) fb
->Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
;
2228 else if (fb
->_ColorDrawBufferMask
[0] == BUFFER_BIT_BACK_LEFT
) {
2230 drb
= (driRenderbuffer
*) fb
->Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
;
2233 /* drawing to multiple buffers, or none */
2238 assert(drb
->flippedPitch
);
2240 R200_STATECHANGE( rmesa
, ctx
);
2242 /* Note: we used the (possibly) page-flipped values */
2243 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLOROFFSET
]
2244 = ((drb
->flippedOffset
+ rmesa
->r200Screen
->fbLocation
)
2245 & R200_COLOROFFSET_MASK
);
2246 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLORPITCH
] = drb
->flippedPitch
;
2247 if (rmesa
->sarea
->tiling_enabled
) {
2248 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLORPITCH
] |= R200_COLOR_TILE_ENABLE
;
2254 void r200ValidateState( GLcontext
*ctx
)
2256 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2257 GLuint new_state
= rmesa
->NewGLState
;
2259 if (new_state
& (_NEW_BUFFERS
| _NEW_COLOR
| _NEW_PIXEL
)) {
2260 r200UpdateDrawBuffer(ctx
);
2263 if (new_state
& _NEW_TEXTURE
) {
2264 r200UpdateTextureState( ctx
);
2265 new_state
|= rmesa
->NewGLState
; /* may add TEXTURE_MATRIX */
2268 /* Need an event driven matrix update?
2270 if (new_state
& (_NEW_MODELVIEW
|_NEW_PROJECTION
))
2271 upload_matrix( rmesa
, ctx
->_ModelProjectMatrix
.m
, R200_MTX_MVP
);
2273 /* Need these for lighting (shouldn't upload otherwise)
2275 if (new_state
& (_NEW_MODELVIEW
)) {
2276 upload_matrix( rmesa
, ctx
->ModelviewMatrixStack
.Top
->m
, R200_MTX_MV
);
2277 upload_matrix_t( rmesa
, ctx
->ModelviewMatrixStack
.Top
->inv
, R200_MTX_IMV
);
2280 /* Does this need to be triggered on eg. modelview for
2281 * texgen-derived objplane/eyeplane matrices?
2283 if (new_state
& (_NEW_TEXTURE
|_NEW_TEXTURE_MATRIX
)) {
2284 update_texturematrix( ctx
);
2287 if (new_state
& (_NEW_LIGHT
|_NEW_MODELVIEW
|_MESA_NEW_NEED_EYE_COORDS
)) {
2288 update_light( ctx
);
2291 /* emit all active clip planes if projection matrix changes.
2293 if (new_state
& (_NEW_PROJECTION
)) {
2294 if (ctx
->Transform
.ClipPlanesEnabled
)
2295 r200UpdateClipPlanes( ctx
);
2299 rmesa
->NewGLState
= 0;
2303 static void r200InvalidateState( GLcontext
*ctx
, GLuint new_state
)
2305 _swrast_InvalidateState( ctx
, new_state
);
2306 _swsetup_InvalidateState( ctx
, new_state
);
2307 _ac_InvalidateState( ctx
, new_state
);
2308 _tnl_InvalidateState( ctx
, new_state
);
2309 _ae_invalidate_state( ctx
, new_state
);
2310 R200_CONTEXT(ctx
)->NewGLState
|= new_state
;
2311 r200VtxfmtInvalidate( ctx
);
2314 /* A hack. The r200 can actually cope just fine with materials
2315 * between begin/ends, so fix this. But how ?
2317 static GLboolean
check_material( GLcontext
*ctx
)
2319 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
2322 for (i
= _TNL_ATTRIB_MAT_FRONT_AMBIENT
;
2323 i
< _TNL_ATTRIB_MAT_BACK_INDEXES
;
2325 if (tnl
->vb
.AttribPtr
[i
] &&
2326 tnl
->vb
.AttribPtr
[i
]->stride
)
2332 static void r200WrapRunPipeline( GLcontext
*ctx
)
2334 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2335 GLboolean has_material
;
2338 fprintf(stderr
, "%s, newstate: %x\n", __FUNCTION__
, rmesa
->NewGLState
);
2342 if (rmesa
->NewGLState
)
2343 r200ValidateState( ctx
);
2345 has_material
= (ctx
->Light
.Enabled
&& check_material( ctx
));
2348 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_TRUE
);
2351 /* Run the pipeline.
2353 _tnl_run_pipeline( ctx
);
2356 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_FALSE
);
2361 /* Initialize the driver's state functions.
2363 void r200InitStateFuncs( struct dd_function_table
*functions
)
2365 functions
->UpdateState
= r200InvalidateState
;
2366 functions
->LightingSpaceChange
= r200LightingSpaceChange
;
2368 functions
->DrawBuffer
= r200DrawBuffer
;
2369 functions
->ReadBuffer
= r200ReadBuffer
;
2371 functions
->AlphaFunc
= r200AlphaFunc
;
2372 functions
->BlendColor
= r200BlendColor
;
2373 functions
->BlendEquationSeparate
= r200BlendEquationSeparate
;
2374 functions
->BlendFuncSeparate
= r200BlendFuncSeparate
;
2375 functions
->ClearColor
= r200ClearColor
;
2376 functions
->ClearDepth
= r200ClearDepth
;
2377 functions
->ClearIndex
= NULL
;
2378 functions
->ClearStencil
= r200ClearStencil
;
2379 functions
->ClipPlane
= r200ClipPlane
;
2380 functions
->ColorMask
= r200ColorMask
;
2381 functions
->CullFace
= r200CullFace
;
2382 functions
->DepthFunc
= r200DepthFunc
;
2383 functions
->DepthMask
= r200DepthMask
;
2384 functions
->DepthRange
= r200DepthRange
;
2385 functions
->Enable
= r200Enable
;
2386 functions
->Fogfv
= r200Fogfv
;
2387 functions
->FrontFace
= r200FrontFace
;
2388 functions
->Hint
= NULL
;
2389 functions
->IndexMask
= NULL
;
2390 functions
->LightModelfv
= r200LightModelfv
;
2391 functions
->Lightfv
= r200Lightfv
;
2392 functions
->LineStipple
= r200LineStipple
;
2393 functions
->LineWidth
= r200LineWidth
;
2394 functions
->LogicOpcode
= r200LogicOpCode
;
2395 functions
->PolygonMode
= r200PolygonMode
;
2396 functions
->PolygonOffset
= r200PolygonOffset
;
2397 functions
->PolygonStipple
= r200PolygonStipple
;
2398 functions
->PointSize
= r200PointSize
;
2399 functions
->RenderMode
= r200RenderMode
;
2400 functions
->Scissor
= r200Scissor
;
2401 functions
->ShadeModel
= r200ShadeModel
;
2402 functions
->StencilFunc
= r200StencilFunc
;
2403 functions
->StencilMask
= r200StencilMask
;
2404 functions
->StencilOp
= r200StencilOp
;
2405 functions
->Viewport
= r200Viewport
;
2407 /* Swrast hooks for imaging extensions:
2409 functions
->CopyColorTable
= _swrast_CopyColorTable
;
2410 functions
->CopyColorSubTable
= _swrast_CopyColorSubTable
;
2411 functions
->CopyConvolutionFilter1D
= _swrast_CopyConvolutionFilter1D
;
2412 functions
->CopyConvolutionFilter2D
= _swrast_CopyConvolutionFilter2D
;
2416 void r200InitTnlFuncs( GLcontext
*ctx
)
2418 TNL_CONTEXT(ctx
)->Driver
.NotifyMaterialChange
= r200UpdateMaterial
;
2419 TNL_CONTEXT(ctx
)->Driver
.RunPipeline
= r200WrapRunPipeline
;