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"
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"
60 /* =============================================================
64 static void r200AlphaFunc( GLcontext
*ctx
, GLenum func
, GLfloat ref
)
66 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
67 int pp_misc
= rmesa
->hw
.ctx
.cmd
[CTX_PP_MISC
];
70 CLAMPED_FLOAT_TO_UBYTE(refByte
, ref
);
72 R200_STATECHANGE( rmesa
, ctx
);
74 pp_misc
&= ~(R200_ALPHA_TEST_OP_MASK
| R200_REF_ALPHA_MASK
);
75 pp_misc
|= (refByte
& R200_REF_ALPHA_MASK
);
79 pp_misc
|= R200_ALPHA_TEST_FAIL
;
82 pp_misc
|= R200_ALPHA_TEST_LESS
;
85 pp_misc
|= R200_ALPHA_TEST_EQUAL
;
88 pp_misc
|= R200_ALPHA_TEST_LEQUAL
;
91 pp_misc
|= R200_ALPHA_TEST_GREATER
;
94 pp_misc
|= R200_ALPHA_TEST_NEQUAL
;
97 pp_misc
|= R200_ALPHA_TEST_GEQUAL
;
100 pp_misc
|= R200_ALPHA_TEST_PASS
;
104 rmesa
->hw
.ctx
.cmd
[CTX_PP_MISC
] = pp_misc
;
107 static void r200BlendEquation( GLcontext
*ctx
, GLenum mode
)
109 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
110 GLuint b
= rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] & ~R200_COMB_FCN_MASK
;
115 b
|= R200_COMB_FCN_ADD_CLAMP
;
118 case GL_FUNC_SUBTRACT
:
119 b
|= R200_COMB_FCN_SUB_CLAMP
;
122 case GL_FUNC_REVERSE_SUBTRACT
:
123 b
|= R200_COMB_FCN_RSUB_CLAMP
;
127 b
|= R200_COMB_FCN_MIN
;
131 b
|= R200_COMB_FCN_MAX
;
138 R200_STATECHANGE( rmesa
, ctx
);
139 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] = b
;
140 if ( ctx
->Color
.ColorLogicOpEnabled
) {
141 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_ROP_ENABLE
;
143 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_ROP_ENABLE
;
147 static void r200BlendFunc( GLcontext
*ctx
, GLenum sfactor
, GLenum dfactor
)
149 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
150 GLuint b
= rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] &
151 ~(R200_SRC_BLEND_MASK
| R200_DST_BLEND_MASK
);
153 switch ( ctx
->Color
.BlendSrcRGB
) {
155 b
|= R200_SRC_BLEND_GL_ZERO
;
158 b
|= R200_SRC_BLEND_GL_ONE
;
161 b
|= R200_SRC_BLEND_GL_DST_COLOR
;
163 case GL_ONE_MINUS_DST_COLOR
:
164 b
|= R200_SRC_BLEND_GL_ONE_MINUS_DST_COLOR
;
167 b
|= R200_SRC_BLEND_GL_SRC_COLOR
;
169 case GL_ONE_MINUS_SRC_COLOR
:
170 b
|= R200_SRC_BLEND_GL_ONE_MINUS_SRC_COLOR
;
173 b
|= R200_SRC_BLEND_GL_SRC_ALPHA
;
175 case GL_ONE_MINUS_SRC_ALPHA
:
176 b
|= R200_SRC_BLEND_GL_ONE_MINUS_SRC_ALPHA
;
179 b
|= R200_SRC_BLEND_GL_DST_ALPHA
;
181 case GL_ONE_MINUS_DST_ALPHA
:
182 b
|= R200_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA
;
184 case GL_SRC_ALPHA_SATURATE
:
185 b
|= R200_SRC_BLEND_GL_SRC_ALPHA_SATURATE
;
187 case GL_CONSTANT_COLOR
:
188 b
|= R200_SRC_BLEND_GL_CONST_COLOR
;
190 case GL_ONE_MINUS_CONSTANT_COLOR
:
191 b
|= R200_SRC_BLEND_GL_ONE_MINUS_CONST_COLOR
;
193 case GL_CONSTANT_ALPHA
:
194 b
|= R200_SRC_BLEND_GL_CONST_ALPHA
;
196 case GL_ONE_MINUS_CONSTANT_ALPHA
:
197 b
|= R200_SRC_BLEND_GL_ONE_MINUS_CONST_ALPHA
;
203 switch ( ctx
->Color
.BlendDstRGB
) {
205 b
|= R200_DST_BLEND_GL_ZERO
;
208 b
|= R200_DST_BLEND_GL_ONE
;
211 b
|= R200_DST_BLEND_GL_SRC_COLOR
;
213 case GL_ONE_MINUS_SRC_COLOR
:
214 b
|= R200_DST_BLEND_GL_ONE_MINUS_SRC_COLOR
;
217 b
|= R200_DST_BLEND_GL_SRC_ALPHA
;
219 case GL_ONE_MINUS_SRC_ALPHA
:
220 b
|= R200_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA
;
223 b
|= R200_DST_BLEND_GL_DST_COLOR
;
225 case GL_ONE_MINUS_DST_COLOR
:
226 b
|= R200_DST_BLEND_GL_ONE_MINUS_DST_COLOR
;
229 b
|= R200_DST_BLEND_GL_DST_ALPHA
;
231 case GL_ONE_MINUS_DST_ALPHA
:
232 b
|= R200_DST_BLEND_GL_ONE_MINUS_DST_ALPHA
;
234 case GL_CONSTANT_COLOR
:
235 b
|= R200_DST_BLEND_GL_CONST_COLOR
;
237 case GL_ONE_MINUS_CONSTANT_COLOR
:
238 b
|= R200_DST_BLEND_GL_ONE_MINUS_CONST_COLOR
;
240 case GL_CONSTANT_ALPHA
:
241 b
|= R200_DST_BLEND_GL_CONST_ALPHA
;
243 case GL_ONE_MINUS_CONSTANT_ALPHA
:
244 b
|= R200_DST_BLEND_GL_ONE_MINUS_CONST_ALPHA
;
250 R200_STATECHANGE( rmesa
, ctx
);
251 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] = b
;
254 static void r200BlendFuncSeparate( GLcontext
*ctx
,
255 GLenum sfactorRGB
, GLenum dfactorRGB
,
256 GLenum sfactorA
, GLenum dfactorA
)
258 r200BlendFunc( ctx
, sfactorRGB
, dfactorRGB
);
262 /* =============================================================
266 static void r200DepthFunc( GLcontext
*ctx
, GLenum func
)
268 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
270 R200_STATECHANGE( rmesa
, ctx
);
271 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_Z_TEST_MASK
;
273 switch ( ctx
->Depth
.Func
) {
275 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_NEVER
;
278 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_LESS
;
281 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_EQUAL
;
284 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_LEQUAL
;
287 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_GREATER
;
290 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_NEQUAL
;
293 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_GEQUAL
;
296 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_ALWAYS
;
302 static void r200DepthMask( GLcontext
*ctx
, GLboolean flag
)
304 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
305 R200_STATECHANGE( rmesa
, ctx
);
307 if ( ctx
->Depth
.Mask
) {
308 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_WRITE_ENABLE
;
310 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_Z_WRITE_ENABLE
;
315 /* =============================================================
320 static void r200Fogfv( GLcontext
*ctx
, GLenum pname
, const GLfloat
*param
)
322 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
323 union { int i
; float f
; } c
, d
;
327 c
.i
= rmesa
->hw
.fog
.cmd
[FOG_C
];
328 d
.i
= rmesa
->hw
.fog
.cmd
[FOG_D
];
332 if (!ctx
->Fog
.Enabled
)
334 R200_STATECHANGE(rmesa
, tcl
);
335 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_TCL_FOG_MASK
;
336 switch (ctx
->Fog
.Mode
) {
338 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_LINEAR
;
339 if (ctx
->Fog
.Start
== ctx
->Fog
.End
) {
344 c
.f
= ctx
->Fog
.End
/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
345 d
.f
= -1.0/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
349 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_EXP
;
351 d
.f
= -ctx
->Fog
.Density
;
354 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_EXP2
;
356 d
.f
= -(ctx
->Fog
.Density
* ctx
->Fog
.Density
);
363 switch (ctx
->Fog
.Mode
) {
366 d
.f
= -ctx
->Fog
.Density
;
370 d
.f
= -(ctx
->Fog
.Density
* ctx
->Fog
.Density
);
378 if (ctx
->Fog
.Mode
== GL_LINEAR
) {
379 if (ctx
->Fog
.Start
== ctx
->Fog
.End
) {
383 c
.f
= ctx
->Fog
.End
/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
384 d
.f
= -1.0/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
389 R200_STATECHANGE( rmesa
, ctx
);
390 UNCLAMPED_FLOAT_TO_RGB_CHAN( col
, ctx
->Fog
.Color
);
391 i
= r200PackColor( 4, col
[0], col
[1], col
[2], 0 );
392 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] &= ~R200_FOG_COLOR_MASK
;
393 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] |= i
;
395 case GL_FOG_COORDINATE_SOURCE_EXT
:
403 if (c
.i
!= rmesa
->hw
.fog
.cmd
[FOG_C
] || d
.i
!= rmesa
->hw
.fog
.cmd
[FOG_D
]) {
404 R200_STATECHANGE( rmesa
, fog
);
405 rmesa
->hw
.fog
.cmd
[FOG_C
] = c
.i
;
406 rmesa
->hw
.fog
.cmd
[FOG_D
] = d
.i
;
411 /* =============================================================
416 static GLboolean
intersect_rect( XF86DRIClipRectPtr out
,
417 XF86DRIClipRectPtr a
,
418 XF86DRIClipRectPtr b
)
421 if ( b
->x1
> out
->x1
) out
->x1
= b
->x1
;
422 if ( b
->y1
> out
->y1
) out
->y1
= b
->y1
;
423 if ( b
->x2
< out
->x2
) out
->x2
= b
->x2
;
424 if ( b
->y2
< out
->y2
) out
->y2
= b
->y2
;
425 if ( out
->x1
>= out
->x2
) return GL_FALSE
;
426 if ( out
->y1
>= out
->y2
) return GL_FALSE
;
431 void r200RecalcScissorRects( r200ContextPtr rmesa
)
433 XF86DRIClipRectPtr out
;
436 /* Grow cliprect store?
438 if (rmesa
->state
.scissor
.numAllocedClipRects
< rmesa
->numClipRects
) {
439 while (rmesa
->state
.scissor
.numAllocedClipRects
< rmesa
->numClipRects
) {
440 rmesa
->state
.scissor
.numAllocedClipRects
+= 1; /* zero case */
441 rmesa
->state
.scissor
.numAllocedClipRects
*= 2;
444 if (rmesa
->state
.scissor
.pClipRects
)
445 FREE(rmesa
->state
.scissor
.pClipRects
);
447 rmesa
->state
.scissor
.pClipRects
=
448 MALLOC( rmesa
->state
.scissor
.numAllocedClipRects
*
449 sizeof(XF86DRIClipRectRec
) );
451 if ( rmesa
->state
.scissor
.pClipRects
== NULL
) {
452 rmesa
->state
.scissor
.numAllocedClipRects
= 0;
457 out
= rmesa
->state
.scissor
.pClipRects
;
458 rmesa
->state
.scissor
.numClipRects
= 0;
460 for ( i
= 0 ; i
< rmesa
->numClipRects
; i
++ ) {
461 if ( intersect_rect( out
,
462 &rmesa
->pClipRects
[i
],
463 &rmesa
->state
.scissor
.rect
) ) {
464 rmesa
->state
.scissor
.numClipRects
++;
471 static void r200UpdateScissor( GLcontext
*ctx
)
473 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
475 if ( rmesa
->dri
.drawable
) {
476 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
478 int x
= ctx
->Scissor
.X
;
479 int y
= dPriv
->h
- ctx
->Scissor
.Y
- ctx
->Scissor
.Height
;
480 int w
= ctx
->Scissor
.X
+ ctx
->Scissor
.Width
- 1;
481 int h
= dPriv
->h
- ctx
->Scissor
.Y
- 1;
483 rmesa
->state
.scissor
.rect
.x1
= x
+ dPriv
->x
;
484 rmesa
->state
.scissor
.rect
.y1
= y
+ dPriv
->y
;
485 rmesa
->state
.scissor
.rect
.x2
= w
+ dPriv
->x
+ 1;
486 rmesa
->state
.scissor
.rect
.y2
= h
+ dPriv
->y
+ 1;
488 r200RecalcScissorRects( rmesa
);
493 static void r200Scissor( GLcontext
*ctx
,
494 GLint x
, GLint y
, GLsizei w
, GLsizei h
)
496 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
498 if ( ctx
->Scissor
.Enabled
) {
499 R200_FIREVERTICES( rmesa
); /* don't pipeline cliprect changes */
500 r200UpdateScissor( ctx
);
506 /* =============================================================
510 static void r200CullFace( GLcontext
*ctx
, GLenum unused
)
512 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
513 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
514 GLuint t
= rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
];
516 s
|= R200_FFACE_SOLID
| R200_BFACE_SOLID
;
517 t
&= ~(R200_CULL_FRONT
| R200_CULL_BACK
);
519 if ( ctx
->Polygon
.CullFlag
) {
520 switch ( ctx
->Polygon
.CullFaceMode
) {
522 s
&= ~R200_FFACE_SOLID
;
523 t
|= R200_CULL_FRONT
;
526 s
&= ~R200_BFACE_SOLID
;
529 case GL_FRONT_AND_BACK
:
530 s
&= ~(R200_FFACE_SOLID
| R200_BFACE_SOLID
);
531 t
|= (R200_CULL_FRONT
| R200_CULL_BACK
);
536 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
537 R200_STATECHANGE(rmesa
, set
);
538 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
541 if ( rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] != t
) {
542 R200_STATECHANGE(rmesa
, tcl
);
543 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] = t
;
547 static void r200FrontFace( GLcontext
*ctx
, GLenum mode
)
549 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
551 R200_STATECHANGE( rmesa
, set
);
552 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_FFACE_CULL_DIR_MASK
;
554 R200_STATECHANGE( rmesa
, tcl
);
555 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_CULL_FRONT_IS_CCW
;
559 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_FFACE_CULL_CW
;
562 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_FFACE_CULL_CCW
;
563 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_CULL_FRONT_IS_CCW
;
568 /* =============================================================
571 static void r200PointSize( GLcontext
*ctx
, GLfloat size
)
573 if (0) fprintf(stderr
, "%s: %f\n", __FUNCTION__
, size
);
576 /* =============================================================
579 static void r200LineWidth( GLcontext
*ctx
, GLfloat widthf
)
581 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
583 R200_STATECHANGE( rmesa
, lin
);
584 R200_STATECHANGE( rmesa
, set
);
586 /* Line width is stored in U6.4 format.
588 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] &= ~0xffff;
589 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] |= (GLuint
)(ctx
->Line
._Width
* 16.0);
591 if ( widthf
> 1.0 ) {
592 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_WIDELINE_ENABLE
;
594 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_WIDELINE_ENABLE
;
598 static void r200LineStipple( GLcontext
*ctx
, GLint factor
, GLushort pattern
)
600 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
602 R200_STATECHANGE( rmesa
, lin
);
603 rmesa
->hw
.lin
.cmd
[LIN_RE_LINE_PATTERN
] =
604 ((((GLuint
)factor
& 0xff) << 16) | ((GLuint
)pattern
));
608 /* =============================================================
611 static void r200ColorMask( GLcontext
*ctx
,
612 GLboolean r
, GLboolean g
,
613 GLboolean b
, GLboolean a
)
615 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
616 GLuint mask
= r200PackColor( rmesa
->r200Screen
->cpp
,
617 ctx
->Color
.ColorMask
[RCOMP
],
618 ctx
->Color
.ColorMask
[GCOMP
],
619 ctx
->Color
.ColorMask
[BCOMP
],
620 ctx
->Color
.ColorMask
[ACOMP
] );
622 GLuint flag
= rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] & ~R200_PLANE_MASK_ENABLE
;
624 if (!(r
&& g
&& b
&& a
))
625 flag
|= R200_PLANE_MASK_ENABLE
;
627 if ( rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] != flag
) {
628 R200_STATECHANGE( rmesa
, ctx
);
629 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = flag
;
632 if ( rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
] != mask
) {
633 R200_STATECHANGE( rmesa
, msk
);
634 rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
] = mask
;
639 /* =============================================================
643 static void r200PolygonOffset( GLcontext
*ctx
,
644 GLfloat factor
, GLfloat units
)
646 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
647 GLfloat constant
= units
* rmesa
->state
.depth
.scale
;
652 /* fprintf(stderr, "%s f:%f u:%f\n", __FUNCTION__, factor, constant); */
654 R200_STATECHANGE( rmesa
, zbs
);
655 rmesa
->hw
.zbs
.cmd
[ZBS_SE_ZBIAS_FACTOR
] = *(GLuint
*)&factor
;
656 rmesa
->hw
.zbs
.cmd
[ZBS_SE_ZBIAS_CONSTANT
] = *(GLuint
*)&constant
;
659 static void r200PolygonStipple( GLcontext
*ctx
, const GLubyte
*mask
)
661 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
663 drmRadeonStipple stipple
;
665 /* Must flip pattern upside down.
667 for ( i
= 0 ; i
< 32 ; i
++ ) {
668 rmesa
->state
.stipple
.mask
[31 - i
] = ((GLuint
*) mask
)[i
];
671 /* TODO: push this into cmd mechanism
673 R200_FIREVERTICES( rmesa
);
674 LOCK_HARDWARE( rmesa
);
676 /* FIXME: Use window x,y offsets into stipple RAM.
678 stipple
.mask
= rmesa
->state
.stipple
.mask
;
679 drmCommandWrite( rmesa
->dri
.fd
, DRM_RADEON_STIPPLE
,
680 &stipple
, sizeof(drmRadeonStipple
) );
681 UNLOCK_HARDWARE( rmesa
);
684 static void r200PolygonMode( GLcontext
*ctx
, GLenum face
, GLenum mode
)
686 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
687 GLboolean flag
= (ctx
->_TriangleCaps
& DD_TRI_UNFILLED
) != 0;
689 /* Can't generally do unfilled via tcl, but some good special
692 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_UNFILLED
, flag
);
693 if (rmesa
->TclFallback
) {
694 r200ChooseRenderState( ctx
);
695 r200ChooseVertexState( ctx
);
700 /* =============================================================
701 * Rendering attributes
703 * We really don't want to recalculate all this every time we bind a
704 * texture. These things shouldn't change all that often, so it makes
705 * sense to break them out of the core texture state update routines.
708 /* Examine lighting and texture state to determine if separate specular
711 static void r200UpdateSpecular( GLcontext
*ctx
)
713 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
714 CARD32 p
= rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
];
716 R200_STATECHANGE( rmesa
, tcl
);
717 R200_STATECHANGE( rmesa
, vtx
);
719 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~(3<<R200_VTX_COLOR_0_SHIFT
);
720 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~(3<<R200_VTX_COLOR_1_SHIFT
);
721 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_COLOR_0
;
722 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_COLOR_1
;
723 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LIGHTING_ENABLE
;
725 p
&= ~R200_SPECULAR_ENABLE
;
727 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_DIFFUSE_SPECULAR_COMBINE
;
730 if (ctx
->Light
.Enabled
&&
731 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
) {
732 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
733 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
) |
734 (R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
735 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_0
;
736 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_1
;
737 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHTING_ENABLE
;
738 p
|= R200_SPECULAR_ENABLE
;
739 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &=
740 ~R200_DIFFUSE_SPECULAR_COMBINE
;
742 else if (ctx
->Light
.Enabled
) {
743 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
744 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
));
745 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_0
;
746 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHTING_ENABLE
;
747 } else if (ctx
->Fog
.ColorSumEnabled
) {
748 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
749 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
) |
750 (R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
751 p
|= R200_SPECULAR_ENABLE
;
753 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
754 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
));
757 if (ctx
->Fog
.Enabled
) {
758 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
759 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
760 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_1
;
763 if ( rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] != p
) {
764 R200_STATECHANGE( rmesa
, ctx
);
765 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] = p
;
768 /* Update vertex/render formats
770 if (rmesa
->TclFallback
) {
771 r200ChooseRenderState( ctx
);
772 r200ChooseVertexState( ctx
);
777 /* =============================================================
782 /* Update on colormaterial, material emmissive/ambient,
783 * lightmodel.globalambient
785 static void update_global_ambient( GLcontext
*ctx
)
787 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
788 float *fcmd
= (float *)R200_DB_STATE( glt
);
790 /* Need to do more if both emmissive & ambient are PREMULT:
792 if ((rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
] &
793 ((3 << R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
794 (3 << R200_FRONT_AMBIENT_SOURCE_SHIFT
))) == 0)
796 COPY_3V( &fcmd
[GLT_RED
],
797 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_EMISSION
]);
798 ACC_SCALE_3V( &fcmd
[GLT_RED
],
799 ctx
->Light
.Model
.Ambient
,
800 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_AMBIENT
]);
804 COPY_3V( &fcmd
[GLT_RED
], ctx
->Light
.Model
.Ambient
);
807 R200_DB_STATECHANGE(rmesa
, &rmesa
->hw
.glt
);
810 /* Update on change to
814 * - colormaterial enabled
815 * - colormaterial bitmask
817 static void update_light_colors( GLcontext
*ctx
, GLuint p
)
819 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
821 /* fprintf(stderr, "%s\n", __FUNCTION__); */
824 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
825 float *fcmd
= (float *)R200_DB_STATE( lit
[p
] );
826 GLuint bitmask
= ctx
->Light
.ColorMaterialBitmask
;
827 GLfloat (*mat
)[4] = ctx
->Light
.Material
.Attrib
;
829 COPY_4V( &fcmd
[LIT_AMBIENT_RED
], l
->Ambient
);
830 COPY_4V( &fcmd
[LIT_DIFFUSE_RED
], l
->Diffuse
);
831 COPY_4V( &fcmd
[LIT_SPECULAR_RED
], l
->Specular
);
833 if (!ctx
->Light
.ColorMaterialEnabled
)
836 if ((bitmask
& MAT_BIT_FRONT_AMBIENT
) == 0)
837 SELF_SCALE_3V( &fcmd
[LIT_AMBIENT_RED
], mat
[MAT_ATTRIB_FRONT_AMBIENT
] );
839 if ((bitmask
& MAT_BIT_FRONT_DIFFUSE
) == 0)
840 SELF_SCALE_3V( &fcmd
[LIT_DIFFUSE_RED
], mat
[MAT_ATTRIB_FRONT_DIFFUSE
] );
842 if ((bitmask
& MAT_BIT_FRONT_SPECULAR
) == 0)
843 SELF_SCALE_3V( &fcmd
[LIT_SPECULAR_RED
], mat
[MAT_ATTRIB_FRONT_SPECULAR
] );
845 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
849 /* Also fallback for asym colormaterial mode in twoside lighting...
851 static void check_twoside_fallback( GLcontext
*ctx
)
853 GLboolean fallback
= GL_FALSE
;
856 if (ctx
->Light
.Enabled
&& ctx
->Light
.Model
.TwoSide
) {
857 if (ctx
->Light
.ColorMaterialEnabled
&&
858 (ctx
->Light
.ColorMaterialBitmask
& BACK_MATERIAL_BITS
) !=
859 ((ctx
->Light
.ColorMaterialBitmask
& FRONT_MATERIAL_BITS
)<<1))
862 for (i
= MAT_ATTRIB_FRONT_AMBIENT
; i
< MAT_ATTRIB_FRONT_INDEXES
; i
+=2)
863 if (memcmp( ctx
->Light
.Material
.Attrib
[i
],
864 ctx
->Light
.Material
.Attrib
[i
+1],
865 sizeof(GLfloat
)*4) != 0) {
872 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_LIGHT_TWOSIDE
, fallback
);
875 static void r200ColorMaterial( GLcontext
*ctx
, GLenum face
, GLenum mode
)
877 if (ctx
->Light
.ColorMaterialEnabled
) {
878 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
879 GLuint light_model_ctl1
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
];
880 GLuint mask
= ctx
->Light
.ColorMaterialBitmask
;
882 /* Default to PREMULT:
884 light_model_ctl1
&= ~((0xf << R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
885 (0xf << R200_FRONT_AMBIENT_SOURCE_SHIFT
) |
886 (0xf << R200_FRONT_DIFFUSE_SOURCE_SHIFT
) |
887 (0xf << R200_FRONT_SPECULAR_SOURCE_SHIFT
));
889 if (mask
& MAT_BIT_FRONT_EMISSION
) {
890 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
891 R200_FRONT_EMISSIVE_SOURCE_SHIFT
);
894 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
895 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
896 R200_FRONT_AMBIENT_SOURCE_SHIFT
);
899 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
900 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
901 R200_FRONT_DIFFUSE_SOURCE_SHIFT
);
904 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
905 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
906 R200_FRONT_SPECULAR_SOURCE_SHIFT
);
909 if (light_model_ctl1
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
]) {
912 R200_STATECHANGE( rmesa
, tcl
);
913 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
] = light_model_ctl1
;
915 for (p
= 0 ; p
< MAX_LIGHTS
; p
++)
916 update_light_colors( ctx
, p
);
917 update_global_ambient( ctx
);
921 check_twoside_fallback( ctx
);
924 void r200UpdateMaterial( GLcontext
*ctx
)
926 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
927 GLfloat (*mat
)[4] = ctx
->Light
.Material
.Attrib
;
928 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( mtl
[0] );
932 if (ctx
->Light
.ColorMaterialEnabled
)
933 mask
&= ~ctx
->Light
.ColorMaterialBitmask
;
935 if (R200_DEBUG
& DEBUG_STATE
)
936 fprintf(stderr
, "%s\n", __FUNCTION__
);
939 if (mask
& MAT_BIT_FRONT_EMISSION
) {
940 fcmd
[MTL_EMMISSIVE_RED
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][0];
941 fcmd
[MTL_EMMISSIVE_GREEN
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][1];
942 fcmd
[MTL_EMMISSIVE_BLUE
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][2];
943 fcmd
[MTL_EMMISSIVE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][3];
945 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
946 fcmd
[MTL_AMBIENT_RED
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][0];
947 fcmd
[MTL_AMBIENT_GREEN
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][1];
948 fcmd
[MTL_AMBIENT_BLUE
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][2];
949 fcmd
[MTL_AMBIENT_ALPHA
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][3];
951 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
952 fcmd
[MTL_DIFFUSE_RED
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][0];
953 fcmd
[MTL_DIFFUSE_GREEN
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][1];
954 fcmd
[MTL_DIFFUSE_BLUE
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][2];
955 fcmd
[MTL_DIFFUSE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][3];
957 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
958 fcmd
[MTL_SPECULAR_RED
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][0];
959 fcmd
[MTL_SPECULAR_GREEN
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][1];
960 fcmd
[MTL_SPECULAR_BLUE
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][2];
961 fcmd
[MTL_SPECULAR_ALPHA
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][3];
963 if (mask
& MAT_BIT_FRONT_SHININESS
) {
964 fcmd
[MTL_SHININESS
] = mat
[MAT_ATTRIB_FRONT_SHININESS
][0];
967 if (R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mtl
[0] )) {
968 for (p
= 0 ; p
< MAX_LIGHTS
; p
++)
969 update_light_colors( ctx
, p
);
971 check_twoside_fallback( ctx
);
972 update_global_ambient( ctx
);
974 else if (R200_DEBUG
& (DEBUG_PRIMS
|DEBUG_STATE
))
975 fprintf(stderr
, "%s: Elided noop material call\n", __FUNCTION__
);
980 * _MESA_NEW_NEED_EYE_COORDS
982 * Uses derived state from mesa:
991 * which are calculated in light.c and are correct for the current
992 * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
993 * and _MESA_NEW_NEED_EYE_COORDS.
995 static void update_light( GLcontext
*ctx
)
997 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
999 /* Have to check these, or have an automatic shortcircuit mechanism
1000 * to remove noop statechanges. (Or just do a better job on the
1004 GLuint tmp
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
];
1006 if (ctx
->_NeedEyeCoords
)
1007 tmp
&= ~R200_LIGHT_IN_MODELSPACE
;
1009 tmp
|= R200_LIGHT_IN_MODELSPACE
;
1011 if (tmp
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
])
1013 R200_STATECHANGE( rmesa
, tcl
);
1014 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] = tmp
;
1019 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( eye
);
1020 fcmd
[EYE_X
] = ctx
->_EyeZDir
[0];
1021 fcmd
[EYE_Y
] = ctx
->_EyeZDir
[1];
1022 fcmd
[EYE_Z
] = - ctx
->_EyeZDir
[2];
1023 fcmd
[EYE_RESCALE_FACTOR
] = ctx
->_ModelViewInvScale
;
1024 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.eye
);
1029 if (ctx
->Light
.Enabled
) {
1031 for (p
= 0 ; p
< MAX_LIGHTS
; p
++) {
1032 if (ctx
->Light
.Light
[p
].Enabled
) {
1033 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1034 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( lit
[p
] );
1036 if (l
->EyePosition
[3] == 0.0) {
1037 COPY_3FV( &fcmd
[LIT_POSITION_X
], l
->_VP_inf_norm
);
1038 COPY_3FV( &fcmd
[LIT_DIRECTION_X
], l
->_h_inf_norm
);
1039 fcmd
[LIT_POSITION_W
] = 0;
1040 fcmd
[LIT_DIRECTION_W
] = 0;
1042 COPY_4V( &fcmd
[LIT_POSITION_X
], l
->_Position
);
1043 fcmd
[LIT_DIRECTION_X
] = -l
->_NormDirection
[0];
1044 fcmd
[LIT_DIRECTION_Y
] = -l
->_NormDirection
[1];
1045 fcmd
[LIT_DIRECTION_Z
] = -l
->_NormDirection
[2];
1046 fcmd
[LIT_DIRECTION_W
] = 0;
1049 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
1055 static void r200Lightfv( GLcontext
*ctx
, GLenum light
,
1056 GLenum pname
, const GLfloat
*params
)
1058 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1059 GLint p
= light
- GL_LIGHT0
;
1060 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1061 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.lit
[p
].cmd
;
1068 update_light_colors( ctx
, p
);
1071 case GL_SPOT_DIRECTION
:
1072 /* picked up in update_light */
1076 /* positions picked up in update_light, but can do flag here */
1077 GLuint flag
= (p
&1)? R200_LIGHT_1_IS_LOCAL
: R200_LIGHT_0_IS_LOCAL
;
1078 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1080 R200_STATECHANGE(rmesa
, tcl
);
1081 if (l
->EyePosition
[3] != 0.0F
)
1082 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1084 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1088 case GL_SPOT_EXPONENT
:
1089 R200_STATECHANGE(rmesa
, lit
[p
]);
1090 fcmd
[LIT_SPOT_EXPONENT
] = params
[0];
1093 case GL_SPOT_CUTOFF
: {
1094 GLuint flag
= (p
&1) ? R200_LIGHT_1_IS_SPOT
: R200_LIGHT_0_IS_SPOT
;
1095 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1097 R200_STATECHANGE(rmesa
, lit
[p
]);
1098 fcmd
[LIT_SPOT_CUTOFF
] = l
->_CosCutoff
;
1100 R200_STATECHANGE(rmesa
, tcl
);
1101 if (l
->SpotCutoff
!= 180.0F
)
1102 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1104 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1109 case GL_CONSTANT_ATTENUATION
:
1110 R200_STATECHANGE(rmesa
, lit
[p
]);
1111 fcmd
[LIT_ATTEN_CONST
] = params
[0];
1113 case GL_LINEAR_ATTENUATION
:
1114 R200_STATECHANGE(rmesa
, lit
[p
]);
1115 fcmd
[LIT_ATTEN_LINEAR
] = params
[0];
1117 case GL_QUADRATIC_ATTENUATION
:
1118 R200_STATECHANGE(rmesa
, lit
[p
]);
1119 fcmd
[LIT_ATTEN_QUADRATIC
] = params
[0];
1130 static void r200LightModelfv( GLcontext
*ctx
, GLenum pname
,
1131 const GLfloat
*param
)
1133 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1136 case GL_LIGHT_MODEL_AMBIENT
:
1137 update_global_ambient( ctx
);
1140 case GL_LIGHT_MODEL_LOCAL_VIEWER
:
1141 R200_STATECHANGE( rmesa
, tcl
);
1142 if (ctx
->Light
.Model
.LocalViewer
)
1143 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LOCAL_VIEWER
;
1145 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LOCAL_VIEWER
;
1148 case GL_LIGHT_MODEL_TWO_SIDE
:
1149 R200_STATECHANGE( rmesa
, tcl
);
1150 if (ctx
->Light
.Model
.TwoSide
)
1151 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHT_TWOSIDE
;
1153 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LIGHT_TWOSIDE
;
1155 check_twoside_fallback( ctx
);
1157 if (rmesa
->TclFallback
) {
1158 r200ChooseRenderState( ctx
);
1159 r200ChooseVertexState( ctx
);
1163 case GL_LIGHT_MODEL_COLOR_CONTROL
:
1164 r200UpdateSpecular(ctx
);
1172 static void r200ShadeModel( GLcontext
*ctx
, GLenum mode
)
1174 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1175 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
1177 s
&= ~(R200_DIFFUSE_SHADE_MASK
|
1178 R200_ALPHA_SHADE_MASK
|
1179 R200_SPECULAR_SHADE_MASK
|
1180 R200_FOG_SHADE_MASK
);
1184 s
|= (R200_DIFFUSE_SHADE_FLAT
|
1185 R200_ALPHA_SHADE_FLAT
|
1186 R200_SPECULAR_SHADE_FLAT
|
1187 R200_FOG_SHADE_FLAT
);
1190 s
|= (R200_DIFFUSE_SHADE_GOURAUD
|
1191 R200_ALPHA_SHADE_GOURAUD
|
1192 R200_SPECULAR_SHADE_GOURAUD
|
1193 R200_FOG_SHADE_GOURAUD
);
1199 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
1200 R200_STATECHANGE( rmesa
, set
);
1201 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
1206 /* =============================================================
1210 static void r200ClipPlane( GLcontext
*ctx
, GLenum plane
, const GLfloat
*eq
)
1212 GLint p
= (GLint
) plane
- (GLint
) GL_CLIP_PLANE0
;
1213 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1214 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1216 R200_STATECHANGE( rmesa
, ucp
[p
] );
1217 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1218 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1219 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1220 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1223 static void r200UpdateClipPlanes( GLcontext
*ctx
)
1225 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1228 for (p
= 0; p
< ctx
->Const
.MaxClipPlanes
; p
++) {
1229 if (ctx
->Transform
.ClipPlanesEnabled
& (1 << p
)) {
1230 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1232 R200_STATECHANGE( rmesa
, ucp
[p
] );
1233 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1234 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1235 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1236 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1242 /* =============================================================
1246 static void r200StencilFunc( GLcontext
*ctx
, GLenum func
,
1247 GLint ref
, GLuint mask
)
1249 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1250 GLuint refmask
= ((ctx
->Stencil
.Ref
[0] << R200_STENCIL_REF_SHIFT
) |
1251 (ctx
->Stencil
.ValueMask
[0] << R200_STENCIL_MASK_SHIFT
));
1253 R200_STATECHANGE( rmesa
, ctx
);
1254 R200_STATECHANGE( rmesa
, msk
);
1256 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_STENCIL_TEST_MASK
;
1257 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~(R200_STENCIL_REF_MASK
|
1258 R200_STENCIL_VALUE_MASK
);
1260 switch ( ctx
->Stencil
.Function
[0] ) {
1262 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEVER
;
1265 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LESS
;
1268 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_EQUAL
;
1271 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LEQUAL
;
1274 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GREATER
;
1277 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEQUAL
;
1280 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GEQUAL
;
1283 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_ALWAYS
;
1287 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |= refmask
;
1290 static void r200StencilMask( GLcontext
*ctx
, GLuint mask
)
1292 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1294 R200_STATECHANGE( rmesa
, msk
);
1295 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~R200_STENCIL_WRITE_MASK
;
1296 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |=
1297 (ctx
->Stencil
.WriteMask
[0] << R200_STENCIL_WRITEMASK_SHIFT
);
1300 static void r200StencilOp( GLcontext
*ctx
, GLenum fail
,
1301 GLenum zfail
, GLenum zpass
)
1303 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1305 R200_STATECHANGE( rmesa
, ctx
);
1306 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~(R200_STENCIL_FAIL_MASK
|
1307 R200_STENCIL_ZFAIL_MASK
|
1308 R200_STENCIL_ZPASS_MASK
);
1310 switch ( ctx
->Stencil
.FailFunc
[0] ) {
1312 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_KEEP
;
1315 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_ZERO
;
1318 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_REPLACE
;
1321 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC
;
1324 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC
;
1326 case GL_INCR_WRAP_EXT
:
1327 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC_WRAP
;
1329 case GL_DECR_WRAP_EXT
:
1330 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC_WRAP
;
1333 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INVERT
;
1337 switch ( ctx
->Stencil
.ZFailFunc
[0] ) {
1339 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_KEEP
;
1342 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_ZERO
;
1345 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_REPLACE
;
1348 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC
;
1351 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC
;
1353 case GL_INCR_WRAP_EXT
:
1354 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC_WRAP
;
1356 case GL_DECR_WRAP_EXT
:
1357 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC_WRAP
;
1360 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INVERT
;
1364 switch ( ctx
->Stencil
.ZPassFunc
[0] ) {
1366 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_KEEP
;
1369 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_ZERO
;
1372 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_REPLACE
;
1375 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC
;
1378 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC
;
1380 case GL_INCR_WRAP_EXT
:
1381 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC_WRAP
;
1383 case GL_DECR_WRAP_EXT
:
1384 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC_WRAP
;
1387 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INVERT
;
1392 static void r200ClearStencil( GLcontext
*ctx
, GLint s
)
1394 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1396 rmesa
->state
.stencil
.clear
=
1397 ((GLuint
) ctx
->Stencil
.Clear
|
1398 (0xff << R200_STENCIL_MASK_SHIFT
) |
1399 (ctx
->Stencil
.WriteMask
[0] << R200_STENCIL_WRITEMASK_SHIFT
));
1403 /* =============================================================
1404 * Window position and viewport transformation
1408 * To correctly position primitives:
1410 #define SUBPIXEL_X 0.125
1411 #define SUBPIXEL_Y 0.125
1413 void r200UpdateWindow( GLcontext
*ctx
)
1415 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1416 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
1417 GLfloat xoffset
= (GLfloat
)dPriv
->x
;
1418 GLfloat yoffset
= (GLfloat
)dPriv
->y
+ dPriv
->h
;
1419 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1421 GLfloat sx
= v
[MAT_SX
];
1422 GLfloat tx
= v
[MAT_TX
] + xoffset
+ SUBPIXEL_X
;
1423 GLfloat sy
= - v
[MAT_SY
];
1424 GLfloat ty
= (- v
[MAT_TY
]) + yoffset
+ SUBPIXEL_Y
;
1425 GLfloat sz
= v
[MAT_SZ
] * rmesa
->state
.depth
.scale
;
1426 GLfloat tz
= v
[MAT_TZ
] * rmesa
->state
.depth
.scale
;
1428 R200_FIREVERTICES( rmesa
);
1429 R200_STATECHANGE( rmesa
, vpt
);
1431 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XSCALE
] = *(GLuint
*)&sx
;
1432 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = *(GLuint
*)&tx
;
1433 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YSCALE
] = *(GLuint
*)&sy
;
1434 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = *(GLuint
*)&ty
;
1435 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZSCALE
] = *(GLuint
*)&sz
;
1436 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZOFFSET
] = *(GLuint
*)&tz
;
1441 static void r200Viewport( GLcontext
*ctx
, GLint x
, GLint y
,
1442 GLsizei width
, GLsizei height
)
1444 /* Don't pipeline viewport changes, conflict with window offset
1445 * setting below. Could apply deltas to rescue pipelined viewport
1446 * values, or keep the originals hanging around.
1448 R200_FIREVERTICES( R200_CONTEXT(ctx
) );
1449 r200UpdateWindow( ctx
);
1452 static void r200DepthRange( GLcontext
*ctx
, GLclampd nearval
,
1455 r200UpdateWindow( ctx
);
1458 void r200UpdateViewportOffset( GLcontext
*ctx
)
1460 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1461 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
1462 GLfloat xoffset
= (GLfloat
)dPriv
->x
;
1463 GLfloat yoffset
= (GLfloat
)dPriv
->y
+ dPriv
->h
;
1464 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1466 GLfloat tx
= v
[MAT_TX
] + xoffset
;
1467 GLfloat ty
= (- v
[MAT_TY
]) + yoffset
;
1469 if ( rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] != *(GLuint
*)&tx
||
1470 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] != *(GLuint
*)&ty
)
1472 /* Note: this should also modify whatever data the context reset
1475 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = *(GLuint
*)&tx
;
1476 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = *(GLuint
*)&ty
;
1478 /* update polygon stipple x/y screen offset */
1481 GLuint m
= rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
];
1483 m
&= ~(R200_STIPPLE_X_OFFSET_MASK
|
1484 R200_STIPPLE_Y_OFFSET_MASK
);
1486 /* add magic offsets, then invert */
1487 stx
= 31 - ((rmesa
->dri
.drawable
->x
- 1) & R200_STIPPLE_COORD_MASK
);
1488 sty
= 31 - ((rmesa
->dri
.drawable
->y
+ rmesa
->dri
.drawable
->h
- 1)
1489 & R200_STIPPLE_COORD_MASK
);
1491 m
|= ((stx
<< R200_STIPPLE_X_OFFSET_SHIFT
) |
1492 (sty
<< R200_STIPPLE_Y_OFFSET_SHIFT
));
1494 if ( rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] != m
) {
1495 R200_STATECHANGE( rmesa
, msc
);
1496 rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] = m
;
1501 r200UpdateScissor( ctx
);
1506 /* =============================================================
1510 static void r200ClearColor( GLcontext
*ctx
, const GLfloat c
[4] )
1512 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1514 CLAMPED_FLOAT_TO_UBYTE(color
[0], c
[0]);
1515 CLAMPED_FLOAT_TO_UBYTE(color
[1], c
[1]);
1516 CLAMPED_FLOAT_TO_UBYTE(color
[2], c
[2]);
1517 CLAMPED_FLOAT_TO_UBYTE(color
[3], c
[3]);
1518 rmesa
->state
.color
.clear
= r200PackColor( rmesa
->r200Screen
->cpp
,
1520 color
[2], color
[3] );
1524 static void r200RenderMode( GLcontext
*ctx
, GLenum mode
)
1526 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1527 FALLBACK( rmesa
, R200_FALLBACK_RENDER_MODE
, (mode
!= GL_RENDER
) );
1531 static GLuint r200_rop_tab
[] = {
1534 R200_ROP_AND_REVERSE
,
1536 R200_ROP_AND_INVERTED
,
1543 R200_ROP_OR_REVERSE
,
1544 R200_ROP_COPY_INVERTED
,
1545 R200_ROP_OR_INVERTED
,
1550 static void r200LogicOpCode( GLcontext
*ctx
, GLenum opcode
)
1552 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1553 GLuint rop
= (GLuint
)opcode
- GL_CLEAR
;
1557 R200_STATECHANGE( rmesa
, msk
);
1558 rmesa
->hw
.msk
.cmd
[MSK_RB3D_ROPCNTL
] = r200_rop_tab
[rop
];
1562 void r200SetCliprects( r200ContextPtr rmesa
, GLenum mode
)
1564 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
1568 rmesa
->numClipRects
= dPriv
->numClipRects
;
1569 rmesa
->pClipRects
= (XF86DRIClipRectPtr
)dPriv
->pClipRects
;
1572 /* Can't ignore 2d windows if we are page flipping.
1574 if ( dPriv
->numBackClipRects
== 0 || rmesa
->doPageFlip
) {
1575 rmesa
->numClipRects
= dPriv
->numClipRects
;
1576 rmesa
->pClipRects
= (XF86DRIClipRectPtr
)dPriv
->pClipRects
;
1579 rmesa
->numClipRects
= dPriv
->numBackClipRects
;
1580 rmesa
->pClipRects
= (XF86DRIClipRectPtr
)dPriv
->pBackClipRects
;
1584 fprintf(stderr
, "bad mode in r200SetCliprects\n");
1588 if (rmesa
->state
.scissor
.enabled
)
1589 r200RecalcScissorRects( rmesa
);
1593 static void r200DrawBuffer( GLcontext
*ctx
, GLenum mode
)
1595 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1597 if (R200_DEBUG
& DEBUG_DRI
)
1598 fprintf(stderr
, "%s %s\n", __FUNCTION__
,
1599 _mesa_lookup_enum_by_nr( mode
));
1601 R200_FIREVERTICES(rmesa
); /* don't pipeline cliprect changes */
1604 * _DrawDestMask is easier to cope with than <mode>.
1606 switch ( ctx
->Color
._DrawDestMask
) {
1607 case FRONT_LEFT_BIT
:
1608 FALLBACK( rmesa
, R200_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
1609 r200SetCliprects( rmesa
, GL_FRONT_LEFT
);
1612 FALLBACK( rmesa
, R200_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
1613 r200SetCliprects( rmesa
, GL_BACK_LEFT
);
1616 /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */
1617 FALLBACK( rmesa
, R200_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
1621 /* We want to update the s/w rast state too so that r200SetBuffer()
1624 _swrast_DrawBuffer(ctx
, mode
);
1626 R200_STATECHANGE( rmesa
, ctx
);
1627 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLOROFFSET
] = ((rmesa
->state
.color
.drawOffset
+
1628 rmesa
->r200Screen
->fbLocation
)
1629 & R200_COLOROFFSET_MASK
);
1630 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLORPITCH
] = rmesa
->state
.color
.drawPitch
;
1634 static void r200ReadBuffer( GLcontext
*ctx
, GLenum mode
)
1636 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
1639 /* =============================================================
1640 * State enable/disable
1643 static void r200Enable( GLcontext
*ctx
, GLenum cap
, GLboolean state
)
1645 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1648 if ( R200_DEBUG
& DEBUG_STATE
)
1649 fprintf( stderr
, "%s( %s = %s )\n", __FUNCTION__
,
1650 _mesa_lookup_enum_by_nr( cap
),
1651 state
? "GL_TRUE" : "GL_FALSE" );
1654 /* Fast track this one...
1662 R200_STATECHANGE( rmesa
, ctx
);
1664 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ALPHA_TEST_ENABLE
;
1666 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ALPHA_TEST_ENABLE
;
1671 R200_STATECHANGE( rmesa
, ctx
);
1673 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_ALPHA_BLEND_ENABLE
;
1675 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_ALPHA_BLEND_ENABLE
;
1677 if ( ctx
->Color
.ColorLogicOpEnabled
) {
1678 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_ROP_ENABLE
;
1680 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_ROP_ENABLE
;
1684 case GL_CLIP_PLANE0
:
1685 case GL_CLIP_PLANE1
:
1686 case GL_CLIP_PLANE2
:
1687 case GL_CLIP_PLANE3
:
1688 case GL_CLIP_PLANE4
:
1689 case GL_CLIP_PLANE5
:
1690 p
= cap
-GL_CLIP_PLANE0
;
1691 R200_STATECHANGE( rmesa
, tcl
);
1693 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= (R200_UCP_ENABLE_0
<<p
);
1694 r200ClipPlane( ctx
, cap
, NULL
);
1697 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~(R200_UCP_ENABLE_0
<<p
);
1701 case GL_COLOR_MATERIAL
:
1702 r200ColorMaterial( ctx
, 0, 0 );
1704 r200UpdateMaterial( ctx
);
1708 r200CullFace( ctx
, 0 );
1712 R200_STATECHANGE(rmesa
, ctx
);
1714 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_Z_ENABLE
;
1716 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_Z_ENABLE
;
1721 R200_STATECHANGE(rmesa
, ctx
);
1723 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_DITHER_ENABLE
;
1724 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~rmesa
->state
.color
.roundEnable
;
1726 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_DITHER_ENABLE
;
1727 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= rmesa
->state
.color
.roundEnable
;
1732 R200_STATECHANGE(rmesa
, ctx
);
1734 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_FOG_ENABLE
;
1735 r200Fogfv( ctx
, GL_FOG_MODE
, 0 );
1737 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_FOG_ENABLE
;
1738 R200_STATECHANGE(rmesa
, tcl
);
1739 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_TCL_FOG_MASK
;
1741 r200UpdateSpecular( ctx
); /* for PK_SPEC */
1742 if (rmesa
->TclFallback
)
1743 r200ChooseVertexState( ctx
);
1744 _mesa_allow_light_in_model( ctx
, !state
);
1755 R200_STATECHANGE(rmesa
, tcl
);
1756 p
= cap
- GL_LIGHT0
;
1758 flag
= (R200_LIGHT_1_ENABLE
|
1759 R200_LIGHT_1_ENABLE_AMBIENT
|
1760 R200_LIGHT_1_ENABLE_SPECULAR
);
1762 flag
= (R200_LIGHT_0_ENABLE
|
1763 R200_LIGHT_0_ENABLE_AMBIENT
|
1764 R200_LIGHT_0_ENABLE_SPECULAR
);
1767 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] |= flag
;
1769 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] &= ~flag
;
1773 update_light_colors( ctx
, p
);
1777 r200UpdateSpecular(ctx
);
1778 check_twoside_fallback( ctx
);
1781 case GL_LINE_SMOOTH
:
1782 R200_STATECHANGE( rmesa
, ctx
);
1784 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_LINE
;
1786 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_LINE
;
1790 case GL_LINE_STIPPLE
:
1791 R200_STATECHANGE( rmesa
, set
);
1793 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_PATTERN_ENABLE
;
1795 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_PATTERN_ENABLE
;
1799 case GL_COLOR_LOGIC_OP
:
1800 R200_STATECHANGE( rmesa
, ctx
);
1802 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_ROP_ENABLE
;
1804 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_ROP_ENABLE
;
1809 R200_STATECHANGE( rmesa
, tcl
);
1811 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_NORMALIZE_NORMALS
;
1813 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_NORMALIZE_NORMALS
;
1817 /* Pointsize registers on r200 don't seem to do anything. Maybe
1818 * have to pass pointsizes as vertex parameters? In any case,
1819 * setting pointmin == pointsizemax == 1.0, and doing nothing
1820 * for aa is enough to satisfy conform.
1822 case GL_POINT_SMOOTH
:
1825 /* These don't really do anything, as we don't use the 3vtx
1829 case GL_POLYGON_OFFSET_POINT
:
1830 R200_STATECHANGE( rmesa
, set
);
1832 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_POINT
;
1834 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_POINT
;
1838 case GL_POLYGON_OFFSET_LINE
:
1839 R200_STATECHANGE( rmesa
, set
);
1841 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_LINE
;
1843 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_LINE
;
1848 case GL_POLYGON_OFFSET_FILL
:
1849 R200_STATECHANGE( rmesa
, set
);
1851 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_TRI
;
1853 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_TRI
;
1857 case GL_POLYGON_SMOOTH
:
1858 R200_STATECHANGE( rmesa
, ctx
);
1860 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_POLY
;
1862 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_POLY
;
1866 case GL_POLYGON_STIPPLE
:
1867 R200_STATECHANGE(rmesa
, set
);
1869 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_STIPPLE_ENABLE
;
1871 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_STIPPLE_ENABLE
;
1875 case GL_RESCALE_NORMAL_EXT
: {
1876 GLboolean tmp
= ctx
->_NeedEyeCoords
? state
: !state
;
1877 R200_STATECHANGE( rmesa
, tcl
);
1879 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
1881 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
1886 case GL_SCISSOR_TEST
:
1887 R200_FIREVERTICES( rmesa
);
1888 rmesa
->state
.scissor
.enabled
= state
;
1889 r200UpdateScissor( ctx
);
1892 case GL_STENCIL_TEST
:
1893 if ( rmesa
->state
.stencil
.hwBuffer
) {
1894 R200_STATECHANGE( rmesa
, ctx
);
1896 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_STENCIL_ENABLE
;
1898 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_STENCIL_ENABLE
;
1901 FALLBACK( rmesa
, R200_FALLBACK_STENCIL
, state
);
1905 case GL_TEXTURE_GEN_Q
:
1906 case GL_TEXTURE_GEN_R
:
1907 case GL_TEXTURE_GEN_S
:
1908 case GL_TEXTURE_GEN_T
:
1909 /* Picked up in r200UpdateTextureState.
1911 rmesa
->recheck_texgen
[ctx
->Texture
.CurrentUnit
] = GL_TRUE
;
1914 case GL_COLOR_SUM_EXT
:
1915 r200UpdateSpecular ( ctx
);
1924 void r200LightingSpaceChange( GLcontext
*ctx
)
1926 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1929 if (R200_DEBUG
& DEBUG_STATE
)
1930 fprintf(stderr
, "%s %d BEFORE %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
1931 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
1933 if (ctx
->_NeedEyeCoords
)
1934 tmp
= ctx
->Transform
.RescaleNormals
;
1936 tmp
= !ctx
->Transform
.RescaleNormals
;
1938 R200_STATECHANGE( rmesa
, tcl
);
1940 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
1942 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
1945 if (R200_DEBUG
& DEBUG_STATE
)
1946 fprintf(stderr
, "%s %d AFTER %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
1947 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
1950 /* =============================================================
1951 * Deferred state management - matrices, textures, other?
1957 static void upload_matrix( r200ContextPtr rmesa
, GLfloat
*src
, int idx
)
1959 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
1963 for (i
= 0 ; i
< 4 ; i
++) {
1967 *dest
++ = src
[i
+12];
1970 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
1973 static void upload_matrix_t( r200ContextPtr rmesa
, const GLfloat
*src
, int idx
)
1975 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
1976 memcpy(dest
, src
, 16*sizeof(float));
1977 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
1981 static void update_texturematrix( GLcontext
*ctx
)
1983 r200ContextPtr rmesa
= R200_CONTEXT( ctx
);
1984 GLuint tpc
= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
];
1985 GLuint compsel
= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
];
1988 if (R200_DEBUG
& DEBUG_STATE
)
1989 fprintf(stderr
, "%s before COMPSEL: %x\n", __FUNCTION__
,
1990 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]);
1992 rmesa
->TexMatEnabled
= 0;
1993 rmesa
->TexMatCompSel
= 0;
1995 for (unit
= 0 ; unit
< 2; unit
++) {
1996 if (!ctx
->Texture
.Unit
[unit
]._ReallyEnabled
)
1999 if (ctx
->TextureMatrixStack
[unit
].Top
->type
!= MATRIX_IDENTITY
) {
2000 rmesa
->TexMatEnabled
|= (R200_TEXGEN_TEXMAT_0_ENABLE
|
2001 R200_TEXMAT_0_ENABLE
) << unit
;
2003 rmesa
->TexMatCompSel
|= R200_OUTPUT_TEX_0
<< unit
;
2005 if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2006 /* Need to preconcatenate any active texgen
2007 * obj/eyeplane matrices:
2009 _math_matrix_mul_matrix( &rmesa
->tmpmat
,
2010 &rmesa
->TexGenMatrix
[unit
],
2011 ctx
->TextureMatrixStack
[unit
].Top
);
2012 upload_matrix( rmesa
, rmesa
->tmpmat
.m
, R200_MTX_TEX0
+unit
);
2015 upload_matrix( rmesa
, ctx
->TextureMatrixStack
[unit
].Top
->m
,
2016 R200_MTX_TEX0
+unit
);
2019 else if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2020 upload_matrix( rmesa
, rmesa
->TexGenMatrix
[unit
].m
,
2021 R200_MTX_TEX0
+unit
);
2025 tpc
= (rmesa
->TexMatEnabled
| rmesa
->TexGenEnabled
);
2026 if (tpc
!= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
] ||
2027 rmesa
->TexGenInputs
!= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_1
]) {
2028 R200_STATECHANGE(rmesa
, tcg
);
2029 rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
] = tpc
;
2030 rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_1
] = rmesa
->TexGenInputs
;
2033 compsel
&= ~R200_OUTPUT_TEX_MASK
;
2034 compsel
|= rmesa
->TexMatCompSel
| rmesa
->TexGenCompSel
;
2035 if (compsel
!= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]) {
2036 R200_STATECHANGE(rmesa
, vtx
);
2037 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] = compsel
;
2043 void r200ValidateState( GLcontext
*ctx
)
2045 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2046 GLuint new_state
= rmesa
->NewGLState
;
2048 if (new_state
& _NEW_TEXTURE
) {
2049 r200UpdateTextureState( ctx
);
2050 new_state
|= rmesa
->NewGLState
; /* may add TEXTURE_MATRIX */
2053 /* Need an event driven matrix update?
2055 if (new_state
& (_NEW_MODELVIEW
|_NEW_PROJECTION
))
2056 upload_matrix( rmesa
, ctx
->_ModelProjectMatrix
.m
, R200_MTX_MVP
);
2058 /* Need these for lighting (shouldn't upload otherwise)
2060 if (new_state
& (_NEW_MODELVIEW
)) {
2061 upload_matrix( rmesa
, ctx
->ModelviewMatrixStack
.Top
->m
, R200_MTX_MV
);
2062 upload_matrix_t( rmesa
, ctx
->ModelviewMatrixStack
.Top
->inv
, R200_MTX_IMV
);
2065 /* Does this need to be triggered on eg. modelview for
2066 * texgen-derived objplane/eyeplane matrices?
2068 if (new_state
& (_NEW_TEXTURE
|_NEW_TEXTURE_MATRIX
)) {
2069 update_texturematrix( ctx
);
2072 if (new_state
& (_NEW_LIGHT
|_NEW_MODELVIEW
|_MESA_NEW_NEED_EYE_COORDS
)) {
2073 update_light( ctx
);
2076 /* emit all active clip planes if projection matrix changes.
2078 if (new_state
& (_NEW_PROJECTION
)) {
2079 if (ctx
->Transform
.ClipPlanesEnabled
)
2080 r200UpdateClipPlanes( ctx
);
2084 rmesa
->NewGLState
= 0;
2088 static void r200InvalidateState( GLcontext
*ctx
, GLuint new_state
)
2090 _swrast_InvalidateState( ctx
, new_state
);
2091 _swsetup_InvalidateState( ctx
, new_state
);
2092 _ac_InvalidateState( ctx
, new_state
);
2093 _tnl_InvalidateState( ctx
, new_state
);
2094 _ae_invalidate_state( ctx
, new_state
);
2095 R200_CONTEXT(ctx
)->NewGLState
|= new_state
;
2096 r200VtxfmtInvalidate( ctx
);
2099 /* A hack. The r200 can actually cope just fine with materials
2100 * between begin/ends, so fix this.
2102 static GLboolean
check_material( GLcontext
*ctx
)
2104 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
2107 for (i
= _TNL_ATTRIB_MAT_FRONT_AMBIENT
;
2108 i
< _TNL_ATTRIB_MAT_BACK_INDEXES
;
2110 if (tnl
->vb
.AttribPtr
[i
] &&
2111 tnl
->vb
.AttribPtr
[i
]->stride
)
2118 static void r200WrapRunPipeline( GLcontext
*ctx
)
2120 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2121 GLboolean has_material
;
2124 fprintf(stderr
, "%s, newstate: %x\n", __FUNCTION__
, rmesa
->NewGLState
);
2128 if (rmesa
->NewGLState
)
2129 r200ValidateState( ctx
);
2131 has_material
= (ctx
->Light
.Enabled
&& check_material( ctx
));
2134 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_TRUE
);
2137 /* Run the pipeline.
2139 _tnl_run_pipeline( ctx
);
2142 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_FALSE
);
2147 /* Initialize the driver's state functions.
2149 void r200InitStateFuncs( struct dd_function_table
*functions
)
2151 functions
->UpdateState
= r200InvalidateState
;
2152 functions
->LightingSpaceChange
= r200LightingSpaceChange
;
2154 functions
->DrawBuffer
= r200DrawBuffer
;
2155 functions
->ReadBuffer
= r200ReadBuffer
;
2157 functions
->AlphaFunc
= r200AlphaFunc
;
2158 functions
->BlendEquation
= r200BlendEquation
;
2159 functions
->BlendFunc
= r200BlendFunc
;
2160 functions
->BlendFuncSeparate
= r200BlendFuncSeparate
;
2161 functions
->ClearColor
= r200ClearColor
;
2162 functions
->ClearDepth
= NULL
;
2163 functions
->ClearIndex
= NULL
;
2164 functions
->ClearStencil
= r200ClearStencil
;
2165 functions
->ClipPlane
= r200ClipPlane
;
2166 functions
->ColorMask
= r200ColorMask
;
2167 functions
->CullFace
= r200CullFace
;
2168 functions
->DepthFunc
= r200DepthFunc
;
2169 functions
->DepthMask
= r200DepthMask
;
2170 functions
->DepthRange
= r200DepthRange
;
2171 functions
->Enable
= r200Enable
;
2172 functions
->Fogfv
= r200Fogfv
;
2173 functions
->FrontFace
= r200FrontFace
;
2174 functions
->Hint
= NULL
;
2175 functions
->IndexMask
= NULL
;
2176 functions
->LightModelfv
= r200LightModelfv
;
2177 functions
->Lightfv
= r200Lightfv
;
2178 functions
->LineStipple
= r200LineStipple
;
2179 functions
->LineWidth
= r200LineWidth
;
2180 functions
->LogicOpcode
= r200LogicOpCode
;
2181 functions
->PolygonMode
= r200PolygonMode
;
2182 functions
->PolygonOffset
= r200PolygonOffset
;
2183 functions
->PolygonStipple
= r200PolygonStipple
;
2184 functions
->PointSize
= r200PointSize
;
2185 functions
->RenderMode
= r200RenderMode
;
2186 functions
->Scissor
= r200Scissor
;
2187 functions
->ShadeModel
= r200ShadeModel
;
2188 functions
->StencilFunc
= r200StencilFunc
;
2189 functions
->StencilMask
= r200StencilMask
;
2190 functions
->StencilOp
= r200StencilOp
;
2191 functions
->Viewport
= r200Viewport
;
2193 /* Swrast hooks for imaging extensions:
2195 functions
->CopyColorTable
= _swrast_CopyColorTable
;
2196 functions
->CopyColorSubTable
= _swrast_CopyColorSubTable
;
2197 functions
->CopyConvolutionFilter1D
= _swrast_CopyConvolutionFilter1D
;
2198 functions
->CopyConvolutionFilter2D
= _swrast_CopyConvolutionFilter2D
;
2202 void r200InitTnlFuncs( GLcontext
*ctx
)
2204 TNL_CONTEXT(ctx
)->Driver
.NotifyMaterialChange
= r200UpdateMaterial
;
2205 TNL_CONTEXT(ctx
)->Driver
.RunPipeline
= r200WrapRunPipeline
;