2 /**************************************************************************
4 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
6 The Weather Channel (TM) funded Tungsten Graphics to develop the
7 initial release of the Radeon 8500 driver under the XFree86 license.
8 This notice must be preserved.
10 Permission is hereby granted, free of charge, to any person obtaining
11 a copy of this software and associated documentation files (the
12 "Software"), to deal in the Software without restriction, including
13 without limitation the rights to use, copy, modify, merge, publish,
14 distribute, sublicense, and/or sell copies of the Software, and to
15 permit persons to whom the Software is furnished to do so, subject to
16 the following conditions:
18 The above copyright notice and this permission notice (including the
19 next paragraph) shall be included in all copies or substantial
20 portions of the Software.
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
25 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
26 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 **************************************************************************/
34 * Keith Whitwell <keith@tungstengraphics.com>
39 #include "api_arrayelt.h"
43 #include "swrast/swrast.h"
44 #include "array_cache/acache.h"
46 #include "tnl/t_pipeline.h"
47 #include "swrast_setup/swrast_setup.h"
50 #include "r200_context.h"
51 #include "r200_ioctl.h"
52 #include "r200_state.h"
55 #include "r200_swtcl.h"
56 #include "r200_vtxfmt.h"
59 /* =============================================================
63 static void r200AlphaFunc( GLcontext
*ctx
, GLenum func
, GLfloat ref
)
65 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
66 int pp_misc
= rmesa
->hw
.ctx
.cmd
[CTX_PP_MISC
];
69 CLAMPED_FLOAT_TO_UBYTE(refByte
, ref
);
71 R200_STATECHANGE( rmesa
, ctx
);
73 pp_misc
&= ~(R200_ALPHA_TEST_OP_MASK
| R200_REF_ALPHA_MASK
);
74 pp_misc
|= (refByte
& R200_REF_ALPHA_MASK
);
78 pp_misc
|= R200_ALPHA_TEST_FAIL
;
81 pp_misc
|= R200_ALPHA_TEST_LESS
;
84 pp_misc
|= R200_ALPHA_TEST_EQUAL
;
87 pp_misc
|= R200_ALPHA_TEST_LEQUAL
;
90 pp_misc
|= R200_ALPHA_TEST_GREATER
;
93 pp_misc
|= R200_ALPHA_TEST_NEQUAL
;
96 pp_misc
|= R200_ALPHA_TEST_GEQUAL
;
99 pp_misc
|= R200_ALPHA_TEST_PASS
;
103 rmesa
->hw
.ctx
.cmd
[CTX_PP_MISC
] = pp_misc
;
106 static void r200BlendEquation( GLcontext
*ctx
, GLenum mode
)
108 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
109 GLuint b
= rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] & ~R200_COMB_FCN_MASK
;
114 b
|= R200_COMB_FCN_ADD_CLAMP
;
117 case GL_FUNC_SUBTRACT
:
118 b
|= R200_COMB_FCN_SUB_CLAMP
;
121 case GL_FUNC_REVERSE_SUBTRACT
:
122 b
|= R200_COMB_FCN_RSUB_CLAMP
;
126 b
|= R200_COMB_FCN_MIN
;
130 b
|= R200_COMB_FCN_MAX
;
137 R200_STATECHANGE( rmesa
, ctx
);
138 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] = b
;
139 if ( ctx
->Color
.ColorLogicOpEnabled
) {
140 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_ROP_ENABLE
;
142 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_ROP_ENABLE
;
146 static void r200BlendFunc( GLcontext
*ctx
, GLenum sfactor
, GLenum dfactor
)
148 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
149 GLuint b
= rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] &
150 ~(R200_SRC_BLEND_MASK
| R200_DST_BLEND_MASK
);
152 switch ( ctx
->Color
.BlendSrcRGB
) {
154 b
|= R200_SRC_BLEND_GL_ZERO
;
157 b
|= R200_SRC_BLEND_GL_ONE
;
160 b
|= R200_SRC_BLEND_GL_DST_COLOR
;
162 case GL_ONE_MINUS_DST_COLOR
:
163 b
|= R200_SRC_BLEND_GL_ONE_MINUS_DST_COLOR
;
166 b
|= R200_SRC_BLEND_GL_SRC_COLOR
;
168 case GL_ONE_MINUS_SRC_COLOR
:
169 b
|= R200_SRC_BLEND_GL_ONE_MINUS_SRC_COLOR
;
172 b
|= R200_SRC_BLEND_GL_SRC_ALPHA
;
174 case GL_ONE_MINUS_SRC_ALPHA
:
175 b
|= R200_SRC_BLEND_GL_ONE_MINUS_SRC_ALPHA
;
178 b
|= R200_SRC_BLEND_GL_DST_ALPHA
;
180 case GL_ONE_MINUS_DST_ALPHA
:
181 b
|= R200_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA
;
183 case GL_SRC_ALPHA_SATURATE
:
184 b
|= R200_SRC_BLEND_GL_SRC_ALPHA_SATURATE
;
186 case GL_CONSTANT_COLOR
:
187 b
|= R200_SRC_BLEND_GL_CONST_COLOR
;
189 case GL_ONE_MINUS_CONSTANT_COLOR
:
190 b
|= R200_SRC_BLEND_GL_ONE_MINUS_CONST_COLOR
;
192 case GL_CONSTANT_ALPHA
:
193 b
|= R200_SRC_BLEND_GL_CONST_ALPHA
;
195 case GL_ONE_MINUS_CONSTANT_ALPHA
:
196 b
|= R200_SRC_BLEND_GL_ONE_MINUS_CONST_ALPHA
;
202 switch ( ctx
->Color
.BlendDstRGB
) {
204 b
|= R200_DST_BLEND_GL_ZERO
;
207 b
|= R200_DST_BLEND_GL_ONE
;
210 b
|= R200_DST_BLEND_GL_SRC_COLOR
;
212 case GL_ONE_MINUS_SRC_COLOR
:
213 b
|= R200_DST_BLEND_GL_ONE_MINUS_SRC_COLOR
;
216 b
|= R200_DST_BLEND_GL_SRC_ALPHA
;
218 case GL_ONE_MINUS_SRC_ALPHA
:
219 b
|= R200_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA
;
222 b
|= R200_DST_BLEND_GL_DST_COLOR
;
224 case GL_ONE_MINUS_DST_COLOR
:
225 b
|= R200_DST_BLEND_GL_ONE_MINUS_DST_COLOR
;
228 b
|= R200_DST_BLEND_GL_DST_ALPHA
;
230 case GL_ONE_MINUS_DST_ALPHA
:
231 b
|= R200_DST_BLEND_GL_ONE_MINUS_DST_ALPHA
;
233 case GL_CONSTANT_COLOR
:
234 b
|= R200_DST_BLEND_GL_CONST_COLOR
;
236 case GL_ONE_MINUS_CONSTANT_COLOR
:
237 b
|= R200_DST_BLEND_GL_ONE_MINUS_CONST_COLOR
;
239 case GL_CONSTANT_ALPHA
:
240 b
|= R200_DST_BLEND_GL_CONST_ALPHA
;
242 case GL_ONE_MINUS_CONSTANT_ALPHA
:
243 b
|= R200_DST_BLEND_GL_ONE_MINUS_CONST_ALPHA
;
249 R200_STATECHANGE( rmesa
, ctx
);
250 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] = b
;
253 static void r200BlendFuncSeparate( GLcontext
*ctx
,
254 GLenum sfactorRGB
, GLenum dfactorRGB
,
255 GLenum sfactorA
, GLenum dfactorA
)
257 r200BlendFunc( ctx
, sfactorRGB
, dfactorRGB
);
261 /* =============================================================
265 static void r200DepthFunc( GLcontext
*ctx
, GLenum func
)
267 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
269 R200_STATECHANGE( rmesa
, ctx
);
270 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_Z_TEST_MASK
;
272 switch ( ctx
->Depth
.Func
) {
274 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_NEVER
;
277 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_LESS
;
280 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_EQUAL
;
283 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_LEQUAL
;
286 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_GREATER
;
289 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_NEQUAL
;
292 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_GEQUAL
;
295 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_ALWAYS
;
301 static void r200DepthMask( GLcontext
*ctx
, GLboolean flag
)
303 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
304 R200_STATECHANGE( rmesa
, ctx
);
306 if ( ctx
->Depth
.Mask
) {
307 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_WRITE_ENABLE
;
309 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_Z_WRITE_ENABLE
;
314 /* =============================================================
319 static void r200Fogfv( GLcontext
*ctx
, GLenum pname
, const GLfloat
*param
)
321 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
322 union { int i
; float f
; } c
, d
;
326 c
.i
= rmesa
->hw
.fog
.cmd
[FOG_C
];
327 d
.i
= rmesa
->hw
.fog
.cmd
[FOG_D
];
331 if (!ctx
->Fog
.Enabled
)
333 R200_STATECHANGE(rmesa
, tcl
);
334 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_TCL_FOG_MASK
;
335 switch (ctx
->Fog
.Mode
) {
337 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_LINEAR
;
338 if (ctx
->Fog
.Start
== ctx
->Fog
.End
) {
343 c
.f
= ctx
->Fog
.End
/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
344 d
.f
= -1.0/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
348 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_EXP
;
350 d
.f
= -ctx
->Fog
.Density
;
353 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_EXP2
;
355 d
.f
= -(ctx
->Fog
.Density
* ctx
->Fog
.Density
);
362 switch (ctx
->Fog
.Mode
) {
365 d
.f
= -ctx
->Fog
.Density
;
369 d
.f
= -(ctx
->Fog
.Density
* ctx
->Fog
.Density
);
377 if (ctx
->Fog
.Mode
== GL_LINEAR
) {
378 if (ctx
->Fog
.Start
== ctx
->Fog
.End
) {
382 c
.f
= ctx
->Fog
.End
/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
383 d
.f
= -1.0/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
388 R200_STATECHANGE( rmesa
, ctx
);
389 UNCLAMPED_FLOAT_TO_RGB_CHAN( col
, ctx
->Fog
.Color
);
390 i
= r200PackColor( 4, col
[0], col
[1], col
[2], 0 );
391 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] &= ~R200_FOG_COLOR_MASK
;
392 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] |= i
;
394 case GL_FOG_COORDINATE_SOURCE_EXT
:
402 if (c
.i
!= rmesa
->hw
.fog
.cmd
[FOG_C
] || d
.i
!= rmesa
->hw
.fog
.cmd
[FOG_D
]) {
403 R200_STATECHANGE( rmesa
, fog
);
404 rmesa
->hw
.fog
.cmd
[FOG_C
] = c
.i
;
405 rmesa
->hw
.fog
.cmd
[FOG_D
] = d
.i
;
410 /* =============================================================
415 static GLboolean
intersect_rect( XF86DRIClipRectPtr out
,
416 XF86DRIClipRectPtr a
,
417 XF86DRIClipRectPtr b
)
420 if ( b
->x1
> out
->x1
) out
->x1
= b
->x1
;
421 if ( b
->y1
> out
->y1
) out
->y1
= b
->y1
;
422 if ( b
->x2
< out
->x2
) out
->x2
= b
->x2
;
423 if ( b
->y2
< out
->y2
) out
->y2
= b
->y2
;
424 if ( out
->x1
>= out
->x2
) return GL_FALSE
;
425 if ( out
->y1
>= out
->y2
) return GL_FALSE
;
430 void r200RecalcScissorRects( r200ContextPtr rmesa
)
432 XF86DRIClipRectPtr out
;
435 /* Grow cliprect store?
437 if (rmesa
->state
.scissor
.numAllocedClipRects
< rmesa
->numClipRects
) {
438 while (rmesa
->state
.scissor
.numAllocedClipRects
< rmesa
->numClipRects
) {
439 rmesa
->state
.scissor
.numAllocedClipRects
+= 1; /* zero case */
440 rmesa
->state
.scissor
.numAllocedClipRects
*= 2;
443 if (rmesa
->state
.scissor
.pClipRects
)
444 FREE(rmesa
->state
.scissor
.pClipRects
);
446 rmesa
->state
.scissor
.pClipRects
=
447 MALLOC( rmesa
->state
.scissor
.numAllocedClipRects
*
448 sizeof(XF86DRIClipRectRec
) );
450 if ( rmesa
->state
.scissor
.pClipRects
== NULL
) {
451 rmesa
->state
.scissor
.numAllocedClipRects
= 0;
456 out
= rmesa
->state
.scissor
.pClipRects
;
457 rmesa
->state
.scissor
.numClipRects
= 0;
459 for ( i
= 0 ; i
< rmesa
->numClipRects
; i
++ ) {
460 if ( intersect_rect( out
,
461 &rmesa
->pClipRects
[i
],
462 &rmesa
->state
.scissor
.rect
) ) {
463 rmesa
->state
.scissor
.numClipRects
++;
470 static void r200UpdateScissor( GLcontext
*ctx
)
472 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
474 if ( rmesa
->dri
.drawable
) {
475 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
477 int x
= ctx
->Scissor
.X
;
478 int y
= dPriv
->h
- ctx
->Scissor
.Y
- ctx
->Scissor
.Height
;
479 int w
= ctx
->Scissor
.X
+ ctx
->Scissor
.Width
- 1;
480 int h
= dPriv
->h
- ctx
->Scissor
.Y
- 1;
482 rmesa
->state
.scissor
.rect
.x1
= x
+ dPriv
->x
;
483 rmesa
->state
.scissor
.rect
.y1
= y
+ dPriv
->y
;
484 rmesa
->state
.scissor
.rect
.x2
= w
+ dPriv
->x
+ 1;
485 rmesa
->state
.scissor
.rect
.y2
= h
+ dPriv
->y
+ 1;
487 r200RecalcScissorRects( rmesa
);
492 static void r200Scissor( GLcontext
*ctx
,
493 GLint x
, GLint y
, GLsizei w
, GLsizei h
)
495 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
497 if ( ctx
->Scissor
.Enabled
) {
498 R200_FIREVERTICES( rmesa
); /* don't pipeline cliprect changes */
499 r200UpdateScissor( ctx
);
505 /* =============================================================
509 static void r200CullFace( GLcontext
*ctx
, GLenum unused
)
511 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
512 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
513 GLuint t
= rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
];
515 s
|= R200_FFACE_SOLID
| R200_BFACE_SOLID
;
516 t
&= ~(R200_CULL_FRONT
| R200_CULL_BACK
);
518 if ( ctx
->Polygon
.CullFlag
) {
519 switch ( ctx
->Polygon
.CullFaceMode
) {
521 s
&= ~R200_FFACE_SOLID
;
522 t
|= R200_CULL_FRONT
;
525 s
&= ~R200_BFACE_SOLID
;
528 case GL_FRONT_AND_BACK
:
529 s
&= ~(R200_FFACE_SOLID
| R200_BFACE_SOLID
);
530 t
|= (R200_CULL_FRONT
| R200_CULL_BACK
);
535 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
536 R200_STATECHANGE(rmesa
, set
);
537 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
540 if ( rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] != t
) {
541 R200_STATECHANGE(rmesa
, tcl
);
542 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] = t
;
546 static void r200FrontFace( GLcontext
*ctx
, GLenum mode
)
548 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
550 R200_STATECHANGE( rmesa
, set
);
551 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_FFACE_CULL_DIR_MASK
;
553 R200_STATECHANGE( rmesa
, tcl
);
554 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_CULL_FRONT_IS_CCW
;
558 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_FFACE_CULL_CW
;
561 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_FFACE_CULL_CCW
;
562 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_CULL_FRONT_IS_CCW
;
567 /* =============================================================
570 static void r200PointSize( GLcontext
*ctx
, GLfloat size
)
572 if (0) fprintf(stderr
, "%s: %f\n", __FUNCTION__
, size
);
575 /* =============================================================
578 static void r200LineWidth( GLcontext
*ctx
, GLfloat widthf
)
580 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
582 R200_STATECHANGE( rmesa
, lin
);
583 R200_STATECHANGE( rmesa
, set
);
585 /* Line width is stored in U6.4 format.
587 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] &= ~0xffff;
588 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] |= (GLuint
)(ctx
->Line
._Width
* 16.0);
590 if ( widthf
> 1.0 ) {
591 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_WIDELINE_ENABLE
;
593 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_WIDELINE_ENABLE
;
597 static void r200LineStipple( GLcontext
*ctx
, GLint factor
, GLushort pattern
)
599 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
601 R200_STATECHANGE( rmesa
, lin
);
602 rmesa
->hw
.lin
.cmd
[LIN_RE_LINE_PATTERN
] =
603 ((((GLuint
)factor
& 0xff) << 16) | ((GLuint
)pattern
));
607 /* =============================================================
610 static void r200ColorMask( GLcontext
*ctx
,
611 GLboolean r
, GLboolean g
,
612 GLboolean b
, GLboolean a
)
614 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
615 GLuint mask
= r200PackColor( rmesa
->r200Screen
->cpp
,
616 ctx
->Color
.ColorMask
[RCOMP
],
617 ctx
->Color
.ColorMask
[GCOMP
],
618 ctx
->Color
.ColorMask
[BCOMP
],
619 ctx
->Color
.ColorMask
[ACOMP
] );
621 GLuint flag
= rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] & ~R200_PLANE_MASK_ENABLE
;
623 if (!(r
&& g
&& b
&& a
))
624 flag
|= R200_PLANE_MASK_ENABLE
;
626 if ( rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] != flag
) {
627 R200_STATECHANGE( rmesa
, ctx
);
628 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = flag
;
631 if ( rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
] != mask
) {
632 R200_STATECHANGE( rmesa
, msk
);
633 rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
] = mask
;
638 /* =============================================================
642 static void r200PolygonOffset( GLcontext
*ctx
,
643 GLfloat factor
, GLfloat units
)
645 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
646 GLfloat constant
= units
* rmesa
->state
.depth
.scale
;
651 /* fprintf(stderr, "%s f:%f u:%f\n", __FUNCTION__, factor, constant); */
653 R200_STATECHANGE( rmesa
, zbs
);
654 rmesa
->hw
.zbs
.cmd
[ZBS_SE_ZBIAS_FACTOR
] = *(GLuint
*)&factor
;
655 rmesa
->hw
.zbs
.cmd
[ZBS_SE_ZBIAS_CONSTANT
] = *(GLuint
*)&constant
;
658 static void r200PolygonStipple( GLcontext
*ctx
, const GLubyte
*mask
)
660 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
662 drmRadeonStipple stipple
;
664 /* Must flip pattern upside down.
666 for ( i
= 0 ; i
< 32 ; i
++ ) {
667 rmesa
->state
.stipple
.mask
[31 - i
] = ((GLuint
*) mask
)[i
];
670 /* TODO: push this into cmd mechanism
672 R200_FIREVERTICES( rmesa
);
673 LOCK_HARDWARE( rmesa
);
675 /* FIXME: Use window x,y offsets into stipple RAM.
677 stipple
.mask
= rmesa
->state
.stipple
.mask
;
678 drmCommandWrite( rmesa
->dri
.fd
, DRM_RADEON_STIPPLE
,
679 &stipple
, sizeof(drmRadeonStipple
) );
680 UNLOCK_HARDWARE( rmesa
);
683 static void r200PolygonMode( GLcontext
*ctx
, GLenum face
, GLenum mode
)
685 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
686 GLboolean flag
= (ctx
->_TriangleCaps
& DD_TRI_UNFILLED
) != 0;
688 /* Can't generally do unfilled via tcl, but some good special
691 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_UNFILLED
, flag
);
692 if (rmesa
->TclFallback
) {
693 r200ChooseRenderState( ctx
);
694 r200ChooseVertexState( ctx
);
699 /* =============================================================
700 * Rendering attributes
702 * We really don't want to recalculate all this every time we bind a
703 * texture. These things shouldn't change all that often, so it makes
704 * sense to break them out of the core texture state update routines.
707 /* Examine lighting and texture state to determine if separate specular
710 static void r200UpdateSpecular( GLcontext
*ctx
)
712 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
713 CARD32 p
= rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
];
715 R200_STATECHANGE( rmesa
, tcl
);
716 R200_STATECHANGE( rmesa
, vtx
);
718 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~(3<<R200_VTX_COLOR_0_SHIFT
);
719 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~(3<<R200_VTX_COLOR_1_SHIFT
);
720 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_COLOR_0
;
721 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_COLOR_1
;
722 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LIGHTING_ENABLE
;
724 p
&= ~R200_SPECULAR_ENABLE
;
726 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_DIFFUSE_SPECULAR_COMBINE
;
729 if (ctx
->Light
.Enabled
&&
730 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
) {
731 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
732 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
) |
733 (R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
734 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_0
;
735 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_1
;
736 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHTING_ENABLE
;
737 p
|= R200_SPECULAR_ENABLE
;
738 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &=
739 ~R200_DIFFUSE_SPECULAR_COMBINE
;
741 else if (ctx
->Light
.Enabled
) {
742 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
743 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
));
744 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_0
;
745 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHTING_ENABLE
;
746 } else if (ctx
->Fog
.ColorSumEnabled
) {
747 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
748 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
) |
749 (R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
750 p
|= R200_SPECULAR_ENABLE
;
752 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
753 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
));
756 if (ctx
->Fog
.Enabled
) {
757 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
758 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
759 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_1
;
762 if ( rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] != p
) {
763 R200_STATECHANGE( rmesa
, ctx
);
764 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] = p
;
767 /* Update vertex/render formats
769 if (rmesa
->TclFallback
) {
770 r200ChooseRenderState( ctx
);
771 r200ChooseVertexState( ctx
);
776 /* =============================================================
781 /* Update on colormaterial, material emmissive/ambient,
782 * lightmodel.globalambient
784 static void update_global_ambient( GLcontext
*ctx
)
786 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
787 float *fcmd
= (float *)R200_DB_STATE( glt
);
789 /* Need to do more if both emmissive & ambient are PREMULT:
791 if ((rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
] &
792 ((3 << R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
793 (3 << R200_FRONT_AMBIENT_SOURCE_SHIFT
))) == 0)
795 COPY_3V( &fcmd
[GLT_RED
],
796 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_EMISSION
]);
797 ACC_SCALE_3V( &fcmd
[GLT_RED
],
798 ctx
->Light
.Model
.Ambient
,
799 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_AMBIENT
]);
803 COPY_3V( &fcmd
[GLT_RED
], ctx
->Light
.Model
.Ambient
);
806 R200_DB_STATECHANGE(rmesa
, &rmesa
->hw
.glt
);
809 /* Update on change to
813 * - colormaterial enabled
814 * - colormaterial bitmask
816 static void update_light_colors( GLcontext
*ctx
, GLuint p
)
818 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
820 /* fprintf(stderr, "%s\n", __FUNCTION__); */
823 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
824 float *fcmd
= (float *)R200_DB_STATE( lit
[p
] );
825 GLuint bitmask
= ctx
->Light
.ColorMaterialBitmask
;
826 GLfloat (*mat
)[4] = ctx
->Light
.Material
.Attrib
;
828 COPY_4V( &fcmd
[LIT_AMBIENT_RED
], l
->Ambient
);
829 COPY_4V( &fcmd
[LIT_DIFFUSE_RED
], l
->Diffuse
);
830 COPY_4V( &fcmd
[LIT_SPECULAR_RED
], l
->Specular
);
832 if (!ctx
->Light
.ColorMaterialEnabled
)
835 if ((bitmask
& MAT_BIT_FRONT_AMBIENT
) == 0)
836 SELF_SCALE_3V( &fcmd
[LIT_AMBIENT_RED
], mat
[MAT_ATTRIB_FRONT_AMBIENT
] );
838 if ((bitmask
& MAT_BIT_FRONT_DIFFUSE
) == 0)
839 SELF_SCALE_3V( &fcmd
[LIT_DIFFUSE_RED
], mat
[MAT_ATTRIB_FRONT_DIFFUSE
] );
841 if ((bitmask
& MAT_BIT_FRONT_SPECULAR
) == 0)
842 SELF_SCALE_3V( &fcmd
[LIT_SPECULAR_RED
], mat
[MAT_ATTRIB_FRONT_SPECULAR
] );
844 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
848 /* Also fallback for asym colormaterial mode in twoside lighting...
850 static void check_twoside_fallback( GLcontext
*ctx
)
852 GLboolean fallback
= GL_FALSE
;
855 if (ctx
->Light
.Enabled
&& ctx
->Light
.Model
.TwoSide
) {
856 if (ctx
->Light
.ColorMaterialEnabled
&&
857 (ctx
->Light
.ColorMaterialBitmask
& BACK_MATERIAL_BITS
) !=
858 ((ctx
->Light
.ColorMaterialBitmask
& FRONT_MATERIAL_BITS
)<<1))
861 for (i
= MAT_ATTRIB_FRONT_AMBIENT
; i
< MAT_ATTRIB_FRONT_INDEXES
; i
+=2)
862 if (memcmp( ctx
->Light
.Material
.Attrib
[i
],
863 ctx
->Light
.Material
.Attrib
[i
+1],
864 sizeof(GLfloat
)*4) != 0) {
871 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_LIGHT_TWOSIDE
, fallback
);
874 static void r200ColorMaterial( GLcontext
*ctx
, GLenum face
, GLenum mode
)
876 if (ctx
->Light
.ColorMaterialEnabled
) {
877 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
878 GLuint light_model_ctl1
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
];
879 GLuint mask
= ctx
->Light
.ColorMaterialBitmask
;
881 /* Default to PREMULT:
883 light_model_ctl1
&= ~((0xf << R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
884 (0xf << R200_FRONT_AMBIENT_SOURCE_SHIFT
) |
885 (0xf << R200_FRONT_DIFFUSE_SOURCE_SHIFT
) |
886 (0xf << R200_FRONT_SPECULAR_SOURCE_SHIFT
));
888 if (mask
& MAT_BIT_FRONT_EMISSION
) {
889 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
890 R200_FRONT_EMISSIVE_SOURCE_SHIFT
);
893 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
894 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
895 R200_FRONT_AMBIENT_SOURCE_SHIFT
);
898 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
899 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
900 R200_FRONT_DIFFUSE_SOURCE_SHIFT
);
903 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
904 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
905 R200_FRONT_SPECULAR_SOURCE_SHIFT
);
908 if (light_model_ctl1
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
]) {
911 R200_STATECHANGE( rmesa
, tcl
);
912 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
] = light_model_ctl1
;
914 for (p
= 0 ; p
< MAX_LIGHTS
; p
++)
915 update_light_colors( ctx
, p
);
916 update_global_ambient( ctx
);
920 check_twoside_fallback( ctx
);
923 void r200UpdateMaterial( GLcontext
*ctx
)
925 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
926 GLfloat (*mat
)[4] = ctx
->Light
.Material
.Attrib
;
927 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( mtl
[0] );
931 if (ctx
->Light
.ColorMaterialEnabled
)
932 mask
&= ~ctx
->Light
.ColorMaterialBitmask
;
934 if (R200_DEBUG
& DEBUG_STATE
)
935 fprintf(stderr
, "%s\n", __FUNCTION__
);
938 if (mask
& MAT_BIT_FRONT_EMISSION
) {
939 fcmd
[MTL_EMMISSIVE_RED
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][0];
940 fcmd
[MTL_EMMISSIVE_GREEN
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][1];
941 fcmd
[MTL_EMMISSIVE_BLUE
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][2];
942 fcmd
[MTL_EMMISSIVE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][3];
944 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
945 fcmd
[MTL_AMBIENT_RED
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][0];
946 fcmd
[MTL_AMBIENT_GREEN
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][1];
947 fcmd
[MTL_AMBIENT_BLUE
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][2];
948 fcmd
[MTL_AMBIENT_ALPHA
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][3];
950 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
951 fcmd
[MTL_DIFFUSE_RED
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][0];
952 fcmd
[MTL_DIFFUSE_GREEN
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][1];
953 fcmd
[MTL_DIFFUSE_BLUE
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][2];
954 fcmd
[MTL_DIFFUSE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][3];
956 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
957 fcmd
[MTL_SPECULAR_RED
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][0];
958 fcmd
[MTL_SPECULAR_GREEN
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][1];
959 fcmd
[MTL_SPECULAR_BLUE
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][2];
960 fcmd
[MTL_SPECULAR_ALPHA
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][3];
962 if (mask
& MAT_BIT_FRONT_SHININESS
) {
963 fcmd
[MTL_SHININESS
] = mat
[MAT_ATTRIB_FRONT_SHININESS
][0];
966 if (R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mtl
[0] )) {
967 for (p
= 0 ; p
< MAX_LIGHTS
; p
++)
968 update_light_colors( ctx
, p
);
970 check_twoside_fallback( ctx
);
971 update_global_ambient( ctx
);
973 else if (R200_DEBUG
& (DEBUG_PRIMS
|DEBUG_STATE
))
974 fprintf(stderr
, "%s: Elided noop material call\n", __FUNCTION__
);
979 * _MESA_NEW_NEED_EYE_COORDS
981 * Uses derived state from mesa:
990 * which are calculated in light.c and are correct for the current
991 * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
992 * and _MESA_NEW_NEED_EYE_COORDS.
994 static void update_light( GLcontext
*ctx
)
996 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
998 /* Have to check these, or have an automatic shortcircuit mechanism
999 * to remove noop statechanges. (Or just do a better job on the
1003 GLuint tmp
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
];
1005 if (ctx
->_NeedEyeCoords
)
1006 tmp
&= ~R200_LIGHT_IN_MODELSPACE
;
1008 tmp
|= R200_LIGHT_IN_MODELSPACE
;
1010 if (tmp
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
])
1012 R200_STATECHANGE( rmesa
, tcl
);
1013 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] = tmp
;
1018 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( eye
);
1019 fcmd
[EYE_X
] = ctx
->_EyeZDir
[0];
1020 fcmd
[EYE_Y
] = ctx
->_EyeZDir
[1];
1021 fcmd
[EYE_Z
] = - ctx
->_EyeZDir
[2];
1022 fcmd
[EYE_RESCALE_FACTOR
] = ctx
->_ModelViewInvScale
;
1023 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.eye
);
1028 if (ctx
->Light
.Enabled
) {
1030 for (p
= 0 ; p
< MAX_LIGHTS
; p
++) {
1031 if (ctx
->Light
.Light
[p
].Enabled
) {
1032 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1033 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( lit
[p
] );
1035 if (l
->EyePosition
[3] == 0.0) {
1036 COPY_3FV( &fcmd
[LIT_POSITION_X
], l
->_VP_inf_norm
);
1037 COPY_3FV( &fcmd
[LIT_DIRECTION_X
], l
->_h_inf_norm
);
1038 fcmd
[LIT_POSITION_W
] = 0;
1039 fcmd
[LIT_DIRECTION_W
] = 0;
1041 COPY_4V( &fcmd
[LIT_POSITION_X
], l
->_Position
);
1042 fcmd
[LIT_DIRECTION_X
] = -l
->_NormDirection
[0];
1043 fcmd
[LIT_DIRECTION_Y
] = -l
->_NormDirection
[1];
1044 fcmd
[LIT_DIRECTION_Z
] = -l
->_NormDirection
[2];
1045 fcmd
[LIT_DIRECTION_W
] = 0;
1048 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
1054 static void r200Lightfv( GLcontext
*ctx
, GLenum light
,
1055 GLenum pname
, const GLfloat
*params
)
1057 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1058 GLint p
= light
- GL_LIGHT0
;
1059 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1060 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.lit
[p
].cmd
;
1067 update_light_colors( ctx
, p
);
1070 case GL_SPOT_DIRECTION
:
1071 /* picked up in update_light */
1075 /* positions picked up in update_light, but can do flag here */
1076 GLuint flag
= (p
&1)? R200_LIGHT_1_IS_LOCAL
: R200_LIGHT_0_IS_LOCAL
;
1077 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1079 R200_STATECHANGE(rmesa
, tcl
);
1080 if (l
->EyePosition
[3] != 0.0F
)
1081 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1083 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1087 case GL_SPOT_EXPONENT
:
1088 R200_STATECHANGE(rmesa
, lit
[p
]);
1089 fcmd
[LIT_SPOT_EXPONENT
] = params
[0];
1092 case GL_SPOT_CUTOFF
: {
1093 GLuint flag
= (p
&1) ? R200_LIGHT_1_IS_SPOT
: R200_LIGHT_0_IS_SPOT
;
1094 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1096 R200_STATECHANGE(rmesa
, lit
[p
]);
1097 fcmd
[LIT_SPOT_CUTOFF
] = l
->_CosCutoff
;
1099 R200_STATECHANGE(rmesa
, tcl
);
1100 if (l
->SpotCutoff
!= 180.0F
)
1101 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1103 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1108 case GL_CONSTANT_ATTENUATION
:
1109 R200_STATECHANGE(rmesa
, lit
[p
]);
1110 fcmd
[LIT_ATTEN_CONST
] = params
[0];
1112 case GL_LINEAR_ATTENUATION
:
1113 R200_STATECHANGE(rmesa
, lit
[p
]);
1114 fcmd
[LIT_ATTEN_LINEAR
] = params
[0];
1116 case GL_QUADRATIC_ATTENUATION
:
1117 R200_STATECHANGE(rmesa
, lit
[p
]);
1118 fcmd
[LIT_ATTEN_QUADRATIC
] = params
[0];
1129 static void r200LightModelfv( GLcontext
*ctx
, GLenum pname
,
1130 const GLfloat
*param
)
1132 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1135 case GL_LIGHT_MODEL_AMBIENT
:
1136 update_global_ambient( ctx
);
1139 case GL_LIGHT_MODEL_LOCAL_VIEWER
:
1140 R200_STATECHANGE( rmesa
, tcl
);
1141 if (ctx
->Light
.Model
.LocalViewer
)
1142 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LOCAL_VIEWER
;
1144 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LOCAL_VIEWER
;
1147 case GL_LIGHT_MODEL_TWO_SIDE
:
1148 R200_STATECHANGE( rmesa
, tcl
);
1149 if (ctx
->Light
.Model
.TwoSide
)
1150 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHT_TWOSIDE
;
1152 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LIGHT_TWOSIDE
;
1154 check_twoside_fallback( ctx
);
1156 if (rmesa
->TclFallback
) {
1157 r200ChooseRenderState( ctx
);
1158 r200ChooseVertexState( ctx
);
1162 case GL_LIGHT_MODEL_COLOR_CONTROL
:
1163 r200UpdateSpecular(ctx
);
1171 static void r200ShadeModel( GLcontext
*ctx
, GLenum mode
)
1173 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1174 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
1176 s
&= ~(R200_DIFFUSE_SHADE_MASK
|
1177 R200_ALPHA_SHADE_MASK
|
1178 R200_SPECULAR_SHADE_MASK
|
1179 R200_FOG_SHADE_MASK
);
1183 s
|= (R200_DIFFUSE_SHADE_FLAT
|
1184 R200_ALPHA_SHADE_FLAT
|
1185 R200_SPECULAR_SHADE_FLAT
|
1186 R200_FOG_SHADE_FLAT
);
1189 s
|= (R200_DIFFUSE_SHADE_GOURAUD
|
1190 R200_ALPHA_SHADE_GOURAUD
|
1191 R200_SPECULAR_SHADE_GOURAUD
|
1192 R200_FOG_SHADE_GOURAUD
);
1198 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
1199 R200_STATECHANGE( rmesa
, set
);
1200 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
1205 /* =============================================================
1209 static void r200ClipPlane( GLcontext
*ctx
, GLenum plane
, const GLfloat
*eq
)
1211 GLint p
= (GLint
) plane
- (GLint
) GL_CLIP_PLANE0
;
1212 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1213 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1215 R200_STATECHANGE( rmesa
, ucp
[p
] );
1216 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1217 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1218 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1219 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1222 static void r200UpdateClipPlanes( GLcontext
*ctx
)
1224 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1227 for (p
= 0; p
< ctx
->Const
.MaxClipPlanes
; p
++) {
1228 if (ctx
->Transform
.ClipPlanesEnabled
& (1 << p
)) {
1229 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1231 R200_STATECHANGE( rmesa
, ucp
[p
] );
1232 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1233 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1234 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1235 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1241 /* =============================================================
1245 static void r200StencilFunc( GLcontext
*ctx
, GLenum func
,
1246 GLint ref
, GLuint mask
)
1248 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1249 GLuint refmask
= ((ctx
->Stencil
.Ref
[0] << R200_STENCIL_REF_SHIFT
) |
1250 (ctx
->Stencil
.ValueMask
[0] << R200_STENCIL_MASK_SHIFT
));
1252 R200_STATECHANGE( rmesa
, ctx
);
1253 R200_STATECHANGE( rmesa
, msk
);
1255 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_STENCIL_TEST_MASK
;
1256 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~(R200_STENCIL_REF_MASK
|
1257 R200_STENCIL_VALUE_MASK
);
1259 switch ( ctx
->Stencil
.Function
[0] ) {
1261 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEVER
;
1264 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LESS
;
1267 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_EQUAL
;
1270 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LEQUAL
;
1273 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GREATER
;
1276 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEQUAL
;
1279 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GEQUAL
;
1282 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_ALWAYS
;
1286 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |= refmask
;
1289 static void r200StencilMask( GLcontext
*ctx
, GLuint mask
)
1291 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1293 R200_STATECHANGE( rmesa
, msk
);
1294 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~R200_STENCIL_WRITE_MASK
;
1295 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |=
1296 (ctx
->Stencil
.WriteMask
[0] << R200_STENCIL_WRITEMASK_SHIFT
);
1299 static void r200StencilOp( GLcontext
*ctx
, GLenum fail
,
1300 GLenum zfail
, GLenum zpass
)
1302 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1304 R200_STATECHANGE( rmesa
, ctx
);
1305 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~(R200_STENCIL_FAIL_MASK
|
1306 R200_STENCIL_ZFAIL_MASK
|
1307 R200_STENCIL_ZPASS_MASK
);
1309 switch ( ctx
->Stencil
.FailFunc
[0] ) {
1311 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_KEEP
;
1314 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_ZERO
;
1317 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_REPLACE
;
1320 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC
;
1323 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC
;
1325 case GL_INCR_WRAP_EXT
:
1326 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC_WRAP
;
1328 case GL_DECR_WRAP_EXT
:
1329 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC_WRAP
;
1332 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INVERT
;
1336 switch ( ctx
->Stencil
.ZFailFunc
[0] ) {
1338 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_KEEP
;
1341 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_ZERO
;
1344 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_REPLACE
;
1347 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC
;
1350 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC
;
1352 case GL_INCR_WRAP_EXT
:
1353 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC_WRAP
;
1355 case GL_DECR_WRAP_EXT
:
1356 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC_WRAP
;
1359 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INVERT
;
1363 switch ( ctx
->Stencil
.ZPassFunc
[0] ) {
1365 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_KEEP
;
1368 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_ZERO
;
1371 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_REPLACE
;
1374 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC
;
1377 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC
;
1379 case GL_INCR_WRAP_EXT
:
1380 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC_WRAP
;
1382 case GL_DECR_WRAP_EXT
:
1383 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC_WRAP
;
1386 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INVERT
;
1391 static void r200ClearStencil( GLcontext
*ctx
, GLint s
)
1393 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1395 rmesa
->state
.stencil
.clear
=
1396 ((GLuint
) ctx
->Stencil
.Clear
|
1397 (0xff << R200_STENCIL_MASK_SHIFT
) |
1398 (ctx
->Stencil
.WriteMask
[0] << R200_STENCIL_WRITEMASK_SHIFT
));
1402 /* =============================================================
1403 * Window position and viewport transformation
1407 * To correctly position primitives:
1409 #define SUBPIXEL_X 0.125
1410 #define SUBPIXEL_Y 0.125
1412 void r200UpdateWindow( GLcontext
*ctx
)
1414 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1415 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
1416 GLfloat xoffset
= (GLfloat
)dPriv
->x
;
1417 GLfloat yoffset
= (GLfloat
)dPriv
->y
+ dPriv
->h
;
1418 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1420 GLfloat sx
= v
[MAT_SX
];
1421 GLfloat tx
= v
[MAT_TX
] + xoffset
+ SUBPIXEL_X
;
1422 GLfloat sy
= - v
[MAT_SY
];
1423 GLfloat ty
= (- v
[MAT_TY
]) + yoffset
+ SUBPIXEL_Y
;
1424 GLfloat sz
= v
[MAT_SZ
] * rmesa
->state
.depth
.scale
;
1425 GLfloat tz
= v
[MAT_TZ
] * rmesa
->state
.depth
.scale
;
1427 R200_FIREVERTICES( rmesa
);
1428 R200_STATECHANGE( rmesa
, vpt
);
1430 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XSCALE
] = *(GLuint
*)&sx
;
1431 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = *(GLuint
*)&tx
;
1432 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YSCALE
] = *(GLuint
*)&sy
;
1433 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = *(GLuint
*)&ty
;
1434 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZSCALE
] = *(GLuint
*)&sz
;
1435 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZOFFSET
] = *(GLuint
*)&tz
;
1440 static void r200Viewport( GLcontext
*ctx
, GLint x
, GLint y
,
1441 GLsizei width
, GLsizei height
)
1443 /* Don't pipeline viewport changes, conflict with window offset
1444 * setting below. Could apply deltas to rescue pipelined viewport
1445 * values, or keep the originals hanging around.
1447 R200_FIREVERTICES( R200_CONTEXT(ctx
) );
1448 r200UpdateWindow( ctx
);
1451 static void r200DepthRange( GLcontext
*ctx
, GLclampd nearval
,
1454 r200UpdateWindow( ctx
);
1457 void r200UpdateViewportOffset( GLcontext
*ctx
)
1459 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1460 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
1461 GLfloat xoffset
= (GLfloat
)dPriv
->x
;
1462 GLfloat yoffset
= (GLfloat
)dPriv
->y
+ dPriv
->h
;
1463 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1465 GLfloat tx
= v
[MAT_TX
] + xoffset
;
1466 GLfloat ty
= (- v
[MAT_TY
]) + yoffset
;
1468 if ( rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] != *(GLuint
*)&tx
||
1469 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] != *(GLuint
*)&ty
)
1471 /* Note: this should also modify whatever data the context reset
1474 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = *(GLuint
*)&tx
;
1475 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = *(GLuint
*)&ty
;
1477 /* update polygon stipple x/y screen offset */
1480 GLuint m
= rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
];
1482 m
&= ~(R200_STIPPLE_X_OFFSET_MASK
|
1483 R200_STIPPLE_Y_OFFSET_MASK
);
1485 /* add magic offsets, then invert */
1486 stx
= 31 - ((rmesa
->dri
.drawable
->x
- 1) & R200_STIPPLE_COORD_MASK
);
1487 sty
= 31 - ((rmesa
->dri
.drawable
->y
+ rmesa
->dri
.drawable
->h
- 1)
1488 & R200_STIPPLE_COORD_MASK
);
1490 m
|= ((stx
<< R200_STIPPLE_X_OFFSET_SHIFT
) |
1491 (sty
<< R200_STIPPLE_Y_OFFSET_SHIFT
));
1493 if ( rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] != m
) {
1494 R200_STATECHANGE( rmesa
, msc
);
1495 rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] = m
;
1500 r200UpdateScissor( ctx
);
1505 /* =============================================================
1509 static void r200ClearColor( GLcontext
*ctx
, const GLfloat c
[4] )
1511 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1513 CLAMPED_FLOAT_TO_UBYTE(color
[0], c
[0]);
1514 CLAMPED_FLOAT_TO_UBYTE(color
[1], c
[1]);
1515 CLAMPED_FLOAT_TO_UBYTE(color
[2], c
[2]);
1516 CLAMPED_FLOAT_TO_UBYTE(color
[3], c
[3]);
1517 rmesa
->state
.color
.clear
= r200PackColor( rmesa
->r200Screen
->cpp
,
1519 color
[2], color
[3] );
1523 static void r200RenderMode( GLcontext
*ctx
, GLenum mode
)
1525 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1526 FALLBACK( rmesa
, R200_FALLBACK_RENDER_MODE
, (mode
!= GL_RENDER
) );
1530 static GLuint r200_rop_tab
[] = {
1533 R200_ROP_AND_REVERSE
,
1535 R200_ROP_AND_INVERTED
,
1542 R200_ROP_OR_REVERSE
,
1543 R200_ROP_COPY_INVERTED
,
1544 R200_ROP_OR_INVERTED
,
1549 static void r200LogicOpCode( GLcontext
*ctx
, GLenum opcode
)
1551 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1552 GLuint rop
= (GLuint
)opcode
- GL_CLEAR
;
1556 R200_STATECHANGE( rmesa
, msk
);
1557 rmesa
->hw
.msk
.cmd
[MSK_RB3D_ROPCNTL
] = r200_rop_tab
[rop
];
1561 void r200SetCliprects( r200ContextPtr rmesa
, GLenum mode
)
1563 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
1567 rmesa
->numClipRects
= dPriv
->numClipRects
;
1568 rmesa
->pClipRects
= (XF86DRIClipRectPtr
)dPriv
->pClipRects
;
1571 /* Can't ignore 2d windows if we are page flipping.
1573 if ( dPriv
->numBackClipRects
== 0 || rmesa
->doPageFlip
) {
1574 rmesa
->numClipRects
= dPriv
->numClipRects
;
1575 rmesa
->pClipRects
= (XF86DRIClipRectPtr
)dPriv
->pClipRects
;
1578 rmesa
->numClipRects
= dPriv
->numBackClipRects
;
1579 rmesa
->pClipRects
= (XF86DRIClipRectPtr
)dPriv
->pBackClipRects
;
1583 fprintf(stderr
, "bad mode in r200SetCliprects\n");
1587 if (rmesa
->state
.scissor
.enabled
)
1588 r200RecalcScissorRects( rmesa
);
1592 static void r200DrawBuffer( GLcontext
*ctx
, GLenum mode
)
1594 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1596 if (R200_DEBUG
& DEBUG_DRI
)
1597 fprintf(stderr
, "%s %s\n", __FUNCTION__
,
1598 _mesa_lookup_enum_by_nr( mode
));
1600 R200_FIREVERTICES(rmesa
); /* don't pipeline cliprect changes */
1603 * _DrawDestMask is easier to cope with than <mode>.
1605 switch ( ctx
->Color
._DrawDestMask
) {
1606 case FRONT_LEFT_BIT
:
1607 FALLBACK( rmesa
, R200_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
1608 r200SetCliprects( rmesa
, GL_FRONT_LEFT
);
1611 FALLBACK( rmesa
, R200_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
1612 r200SetCliprects( rmesa
, GL_BACK_LEFT
);
1615 /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */
1616 FALLBACK( rmesa
, R200_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
1620 /* We want to update the s/w rast state too so that r200SetBuffer()
1623 _swrast_DrawBuffer(ctx
, mode
);
1625 R200_STATECHANGE( rmesa
, ctx
);
1626 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLOROFFSET
] = ((rmesa
->state
.color
.drawOffset
+
1627 rmesa
->r200Screen
->fbLocation
)
1628 & R200_COLOROFFSET_MASK
);
1629 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLORPITCH
] = rmesa
->state
.color
.drawPitch
;
1633 static void r200ReadBuffer( GLcontext
*ctx
, GLenum mode
)
1635 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
1638 /* =============================================================
1639 * State enable/disable
1642 static void r200Enable( GLcontext
*ctx
, GLenum cap
, GLboolean state
)
1644 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1647 if ( R200_DEBUG
& DEBUG_STATE
)
1648 fprintf( stderr
, "%s( %s = %s )\n", __FUNCTION__
,
1649 _mesa_lookup_enum_by_nr( cap
),
1650 state
? "GL_TRUE" : "GL_FALSE" );
1653 /* Fast track this one...
1661 R200_STATECHANGE( rmesa
, ctx
);
1663 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ALPHA_TEST_ENABLE
;
1665 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ALPHA_TEST_ENABLE
;
1670 R200_STATECHANGE( rmesa
, ctx
);
1672 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_ALPHA_BLEND_ENABLE
;
1674 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_ALPHA_BLEND_ENABLE
;
1676 if ( ctx
->Color
.ColorLogicOpEnabled
) {
1677 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_ROP_ENABLE
;
1679 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_ROP_ENABLE
;
1683 case GL_CLIP_PLANE0
:
1684 case GL_CLIP_PLANE1
:
1685 case GL_CLIP_PLANE2
:
1686 case GL_CLIP_PLANE3
:
1687 case GL_CLIP_PLANE4
:
1688 case GL_CLIP_PLANE5
:
1689 p
= cap
-GL_CLIP_PLANE0
;
1690 R200_STATECHANGE( rmesa
, tcl
);
1692 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= (R200_UCP_ENABLE_0
<<p
);
1693 r200ClipPlane( ctx
, cap
, NULL
);
1696 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~(R200_UCP_ENABLE_0
<<p
);
1700 case GL_COLOR_MATERIAL
:
1701 r200ColorMaterial( ctx
, 0, 0 );
1703 r200UpdateMaterial( ctx
);
1707 r200CullFace( ctx
, 0 );
1711 R200_STATECHANGE(rmesa
, ctx
);
1713 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_Z_ENABLE
;
1715 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_Z_ENABLE
;
1720 R200_STATECHANGE(rmesa
, ctx
);
1722 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_DITHER_ENABLE
;
1723 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~rmesa
->state
.color
.roundEnable
;
1725 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_DITHER_ENABLE
;
1726 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= rmesa
->state
.color
.roundEnable
;
1731 R200_STATECHANGE(rmesa
, ctx
);
1733 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_FOG_ENABLE
;
1734 r200Fogfv( ctx
, GL_FOG_MODE
, 0 );
1736 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_FOG_ENABLE
;
1737 R200_STATECHANGE(rmesa
, tcl
);
1738 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_TCL_FOG_MASK
;
1740 r200UpdateSpecular( ctx
); /* for PK_SPEC */
1741 if (rmesa
->TclFallback
)
1742 r200ChooseVertexState( ctx
);
1743 _mesa_allow_light_in_model( ctx
, !state
);
1754 R200_STATECHANGE(rmesa
, tcl
);
1755 p
= cap
- GL_LIGHT0
;
1757 flag
= (R200_LIGHT_1_ENABLE
|
1758 R200_LIGHT_1_ENABLE_AMBIENT
|
1759 R200_LIGHT_1_ENABLE_SPECULAR
);
1761 flag
= (R200_LIGHT_0_ENABLE
|
1762 R200_LIGHT_0_ENABLE_AMBIENT
|
1763 R200_LIGHT_0_ENABLE_SPECULAR
);
1766 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] |= flag
;
1768 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] &= ~flag
;
1772 update_light_colors( ctx
, p
);
1776 r200UpdateSpecular(ctx
);
1777 check_twoside_fallback( ctx
);
1780 case GL_LINE_SMOOTH
:
1781 R200_STATECHANGE( rmesa
, ctx
);
1783 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_LINE
;
1785 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_LINE
;
1789 case GL_LINE_STIPPLE
:
1790 R200_STATECHANGE( rmesa
, set
);
1792 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_PATTERN_ENABLE
;
1794 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_PATTERN_ENABLE
;
1798 case GL_COLOR_LOGIC_OP
:
1799 R200_STATECHANGE( rmesa
, ctx
);
1801 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_ROP_ENABLE
;
1803 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_ROP_ENABLE
;
1808 R200_STATECHANGE( rmesa
, tcl
);
1810 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_NORMALIZE_NORMALS
;
1812 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_NORMALIZE_NORMALS
;
1816 /* Pointsize registers on r200 don't seem to do anything. Maybe
1817 * have to pass pointsizes as vertex parameters? In any case,
1818 * setting pointmin == pointsizemax == 1.0, and doing nothing
1819 * for aa is enough to satisfy conform.
1821 case GL_POINT_SMOOTH
:
1824 /* These don't really do anything, as we don't use the 3vtx
1828 case GL_POLYGON_OFFSET_POINT
:
1829 R200_STATECHANGE( rmesa
, set
);
1831 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_POINT
;
1833 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_POINT
;
1837 case GL_POLYGON_OFFSET_LINE
:
1838 R200_STATECHANGE( rmesa
, set
);
1840 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_LINE
;
1842 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_LINE
;
1847 case GL_POLYGON_OFFSET_FILL
:
1848 R200_STATECHANGE( rmesa
, set
);
1850 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_TRI
;
1852 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_TRI
;
1856 case GL_POLYGON_SMOOTH
:
1857 R200_STATECHANGE( rmesa
, ctx
);
1859 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_POLY
;
1861 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_POLY
;
1865 case GL_POLYGON_STIPPLE
:
1866 R200_STATECHANGE(rmesa
, set
);
1868 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_STIPPLE_ENABLE
;
1870 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_STIPPLE_ENABLE
;
1874 case GL_RESCALE_NORMAL_EXT
: {
1875 GLboolean tmp
= ctx
->_NeedEyeCoords
? state
: !state
;
1876 R200_STATECHANGE( rmesa
, tcl
);
1878 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
1880 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
1885 case GL_SCISSOR_TEST
:
1886 R200_FIREVERTICES( rmesa
);
1887 rmesa
->state
.scissor
.enabled
= state
;
1888 r200UpdateScissor( ctx
);
1891 case GL_STENCIL_TEST
:
1892 if ( rmesa
->state
.stencil
.hwBuffer
) {
1893 R200_STATECHANGE( rmesa
, ctx
);
1895 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_STENCIL_ENABLE
;
1897 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_STENCIL_ENABLE
;
1900 FALLBACK( rmesa
, R200_FALLBACK_STENCIL
, state
);
1904 case GL_TEXTURE_GEN_Q
:
1905 case GL_TEXTURE_GEN_R
:
1906 case GL_TEXTURE_GEN_S
:
1907 case GL_TEXTURE_GEN_T
:
1908 /* Picked up in r200UpdateTextureState.
1910 rmesa
->recheck_texgen
[ctx
->Texture
.CurrentUnit
] = GL_TRUE
;
1913 case GL_COLOR_SUM_EXT
:
1914 r200UpdateSpecular ( ctx
);
1923 void r200LightingSpaceChange( GLcontext
*ctx
)
1925 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1928 if (R200_DEBUG
& DEBUG_STATE
)
1929 fprintf(stderr
, "%s %d BEFORE %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
1930 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
1932 if (ctx
->_NeedEyeCoords
)
1933 tmp
= ctx
->Transform
.RescaleNormals
;
1935 tmp
= !ctx
->Transform
.RescaleNormals
;
1937 R200_STATECHANGE( rmesa
, tcl
);
1939 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
1941 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
1944 if (R200_DEBUG
& DEBUG_STATE
)
1945 fprintf(stderr
, "%s %d AFTER %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
1946 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
1949 /* =============================================================
1950 * Deferred state management - matrices, textures, other?
1956 static void upload_matrix( r200ContextPtr rmesa
, GLfloat
*src
, int idx
)
1958 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
1962 for (i
= 0 ; i
< 4 ; i
++) {
1966 *dest
++ = src
[i
+12];
1969 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
1972 static void upload_matrix_t( r200ContextPtr rmesa
, const GLfloat
*src
, int idx
)
1974 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
1975 memcpy(dest
, src
, 16*sizeof(float));
1976 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
1980 static void update_texturematrix( GLcontext
*ctx
)
1982 r200ContextPtr rmesa
= R200_CONTEXT( ctx
);
1983 GLuint tpc
= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
];
1984 GLuint compsel
= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
];
1987 if (R200_DEBUG
& DEBUG_STATE
)
1988 fprintf(stderr
, "%s before COMPSEL: %x\n", __FUNCTION__
,
1989 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]);
1991 rmesa
->TexMatEnabled
= 0;
1992 rmesa
->TexMatCompSel
= 0;
1994 for (unit
= 0 ; unit
< 2; unit
++) {
1995 if (!ctx
->Texture
.Unit
[unit
]._ReallyEnabled
)
1998 if (ctx
->TextureMatrixStack
[unit
].Top
->type
!= MATRIX_IDENTITY
) {
1999 rmesa
->TexMatEnabled
|= (R200_TEXGEN_TEXMAT_0_ENABLE
|
2000 R200_TEXMAT_0_ENABLE
) << unit
;
2002 rmesa
->TexMatCompSel
|= R200_OUTPUT_TEX_0
<< unit
;
2004 if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2005 /* Need to preconcatenate any active texgen
2006 * obj/eyeplane matrices:
2008 _math_matrix_mul_matrix( &rmesa
->tmpmat
,
2009 &rmesa
->TexGenMatrix
[unit
],
2010 ctx
->TextureMatrixStack
[unit
].Top
);
2011 upload_matrix( rmesa
, rmesa
->tmpmat
.m
, R200_MTX_TEX0
+unit
);
2014 upload_matrix( rmesa
, ctx
->TextureMatrixStack
[unit
].Top
->m
,
2015 R200_MTX_TEX0
+unit
);
2018 else if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2019 upload_matrix( rmesa
, rmesa
->TexGenMatrix
[unit
].m
,
2020 R200_MTX_TEX0
+unit
);
2024 tpc
= (rmesa
->TexMatEnabled
| rmesa
->TexGenEnabled
);
2025 if (tpc
!= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
] ||
2026 rmesa
->TexGenInputs
!= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_1
]) {
2027 R200_STATECHANGE(rmesa
, tcg
);
2028 rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
] = tpc
;
2029 rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_1
] = rmesa
->TexGenInputs
;
2032 compsel
&= ~R200_OUTPUT_TEX_MASK
;
2033 compsel
|= rmesa
->TexMatCompSel
| rmesa
->TexGenCompSel
;
2034 if (compsel
!= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]) {
2035 R200_STATECHANGE(rmesa
, vtx
);
2036 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] = compsel
;
2042 void r200ValidateState( GLcontext
*ctx
)
2044 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2045 GLuint new_state
= rmesa
->NewGLState
;
2047 if (new_state
& _NEW_TEXTURE
) {
2048 r200UpdateTextureState( ctx
);
2049 new_state
|= rmesa
->NewGLState
; /* may add TEXTURE_MATRIX */
2052 /* Need an event driven matrix update?
2054 if (new_state
& (_NEW_MODELVIEW
|_NEW_PROJECTION
))
2055 upload_matrix( rmesa
, ctx
->_ModelProjectMatrix
.m
, R200_MTX_MVP
);
2057 /* Need these for lighting (shouldn't upload otherwise)
2059 if (new_state
& (_NEW_MODELVIEW
)) {
2060 upload_matrix( rmesa
, ctx
->ModelviewMatrixStack
.Top
->m
, R200_MTX_MV
);
2061 upload_matrix_t( rmesa
, ctx
->ModelviewMatrixStack
.Top
->inv
, R200_MTX_IMV
);
2064 /* Does this need to be triggered on eg. modelview for
2065 * texgen-derived objplane/eyeplane matrices?
2067 if (new_state
& (_NEW_TEXTURE
|_NEW_TEXTURE_MATRIX
)) {
2068 update_texturematrix( ctx
);
2071 if (new_state
& (_NEW_LIGHT
|_NEW_MODELVIEW
|_MESA_NEW_NEED_EYE_COORDS
)) {
2072 update_light( ctx
);
2075 /* emit all active clip planes if projection matrix changes.
2077 if (new_state
& (_NEW_PROJECTION
)) {
2078 if (ctx
->Transform
.ClipPlanesEnabled
)
2079 r200UpdateClipPlanes( ctx
);
2083 rmesa
->NewGLState
= 0;
2087 static void r200InvalidateState( GLcontext
*ctx
, GLuint new_state
)
2089 _swrast_InvalidateState( ctx
, new_state
);
2090 _swsetup_InvalidateState( ctx
, new_state
);
2091 _ac_InvalidateState( ctx
, new_state
);
2092 _tnl_InvalidateState( ctx
, new_state
);
2093 _ae_invalidate_state( ctx
, new_state
);
2094 R200_CONTEXT(ctx
)->NewGLState
|= new_state
;
2095 r200VtxfmtInvalidate( ctx
);
2098 /* A hack. The r200 can actually cope just fine with materials
2099 * between begin/ends, so fix this.
2101 static GLboolean
check_material( GLcontext
*ctx
)
2103 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
2106 for (i
= _TNL_ATTRIB_MAT_FRONT_AMBIENT
;
2107 i
< _TNL_ATTRIB_MAT_BACK_INDEXES
;
2109 if (tnl
->vb
.AttribPtr
[i
] &&
2110 tnl
->vb
.AttribPtr
[i
]->stride
)
2117 static void r200WrapRunPipeline( GLcontext
*ctx
)
2119 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2120 GLboolean has_material
;
2123 fprintf(stderr
, "%s, newstate: %x\n", __FUNCTION__
, rmesa
->NewGLState
);
2127 if (rmesa
->NewGLState
)
2128 r200ValidateState( ctx
);
2130 has_material
= (ctx
->Light
.Enabled
&& check_material( ctx
));
2133 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_TRUE
);
2136 /* Run the pipeline.
2138 _tnl_run_pipeline( ctx
);
2141 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_FALSE
);
2146 /* Initialize the driver's state functions.
2148 void r200InitStateFuncs( GLcontext
*ctx
)
2150 ctx
->Driver
.UpdateState
= r200InvalidateState
;
2151 ctx
->Driver
.LightingSpaceChange
= r200LightingSpaceChange
;
2153 ctx
->Driver
.DrawBuffer
= r200DrawBuffer
;
2154 ctx
->Driver
.ReadBuffer
= r200ReadBuffer
;
2156 ctx
->Driver
.AlphaFunc
= r200AlphaFunc
;
2157 ctx
->Driver
.BlendEquation
= r200BlendEquation
;
2158 ctx
->Driver
.BlendFunc
= r200BlendFunc
;
2159 ctx
->Driver
.BlendFuncSeparate
= r200BlendFuncSeparate
;
2160 ctx
->Driver
.ClearColor
= r200ClearColor
;
2161 ctx
->Driver
.ClearDepth
= NULL
;
2162 ctx
->Driver
.ClearIndex
= NULL
;
2163 ctx
->Driver
.ClearStencil
= r200ClearStencil
;
2164 ctx
->Driver
.ClipPlane
= r200ClipPlane
;
2165 ctx
->Driver
.ColorMask
= r200ColorMask
;
2166 ctx
->Driver
.CullFace
= r200CullFace
;
2167 ctx
->Driver
.DepthFunc
= r200DepthFunc
;
2168 ctx
->Driver
.DepthMask
= r200DepthMask
;
2169 ctx
->Driver
.DepthRange
= r200DepthRange
;
2170 ctx
->Driver
.Enable
= r200Enable
;
2171 ctx
->Driver
.Fogfv
= r200Fogfv
;
2172 ctx
->Driver
.FrontFace
= r200FrontFace
;
2173 ctx
->Driver
.Hint
= NULL
;
2174 ctx
->Driver
.IndexMask
= NULL
;
2175 ctx
->Driver
.LightModelfv
= r200LightModelfv
;
2176 ctx
->Driver
.Lightfv
= r200Lightfv
;
2177 ctx
->Driver
.LineStipple
= r200LineStipple
;
2178 ctx
->Driver
.LineWidth
= r200LineWidth
;
2179 ctx
->Driver
.LogicOpcode
= r200LogicOpCode
;
2180 ctx
->Driver
.PolygonMode
= r200PolygonMode
;
2181 ctx
->Driver
.PolygonOffset
= r200PolygonOffset
;
2182 ctx
->Driver
.PolygonStipple
= r200PolygonStipple
;
2183 ctx
->Driver
.PointSize
= r200PointSize
;
2184 ctx
->Driver
.RenderMode
= r200RenderMode
;
2185 ctx
->Driver
.Scissor
= r200Scissor
;
2186 ctx
->Driver
.ShadeModel
= r200ShadeModel
;
2187 ctx
->Driver
.StencilFunc
= r200StencilFunc
;
2188 ctx
->Driver
.StencilMask
= r200StencilMask
;
2189 ctx
->Driver
.StencilOp
= r200StencilOp
;
2190 ctx
->Driver
.Viewport
= r200Viewport
;
2192 /* Swrast hooks for imaging extensions:
2194 ctx
->Driver
.CopyColorTable
= _swrast_CopyColorTable
;
2195 ctx
->Driver
.CopyColorSubTable
= _swrast_CopyColorSubTable
;
2196 ctx
->Driver
.CopyConvolutionFilter1D
= _swrast_CopyConvolutionFilter1D
;
2197 ctx
->Driver
.CopyConvolutionFilter2D
= _swrast_CopyConvolutionFilter2D
;
2199 TNL_CONTEXT(ctx
)->Driver
.NotifyMaterialChange
= r200UpdateMaterial
;
2200 TNL_CONTEXT(ctx
)->Driver
.RunPipeline
= r200WrapRunPipeline
;