Call UpdateMaterial() unconditionally on GL_COLOR_MATERIAL state change
[mesa.git] / src / mesa / drivers / dri / r200 / r200_state.c
1 /* $XFree86$ */
2 /**************************************************************************
3
4 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
5
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.
9
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:
17
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.
21
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.
29
30 **************************************************************************/
31
32 /*
33 * Authors:
34 * Keith Whitwell <keith@tungstengraphics.com>
35 */
36
37 #include "glheader.h"
38 #include "imports.h"
39 #include "api_arrayelt.h"
40 #include "enums.h"
41 #include "colormac.h"
42 #include "light.h"
43
44 #include "swrast/swrast.h"
45 #include "array_cache/acache.h"
46 #include "tnl/tnl.h"
47 #include "tnl/t_pipeline.h"
48 #include "swrast_setup/swrast_setup.h"
49
50
51 #include "r200_context.h"
52 #include "r200_ioctl.h"
53 #include "r200_state.h"
54 #include "r200_tcl.h"
55 #include "r200_tex.h"
56 #include "r200_swtcl.h"
57 #include "r200_vtxfmt.h"
58
59
60 /* =============================================================
61 * Alpha blending
62 */
63
64 static void r200AlphaFunc( GLcontext *ctx, GLenum func, GLfloat ref )
65 {
66 r200ContextPtr rmesa = R200_CONTEXT(ctx);
67 int pp_misc = rmesa->hw.ctx.cmd[CTX_PP_MISC];
68 GLubyte refByte;
69
70 CLAMPED_FLOAT_TO_UBYTE(refByte, ref);
71
72 R200_STATECHANGE( rmesa, ctx );
73
74 pp_misc &= ~(R200_ALPHA_TEST_OP_MASK | R200_REF_ALPHA_MASK);
75 pp_misc |= (refByte & R200_REF_ALPHA_MASK);
76
77 switch ( func ) {
78 case GL_NEVER:
79 pp_misc |= R200_ALPHA_TEST_FAIL;
80 break;
81 case GL_LESS:
82 pp_misc |= R200_ALPHA_TEST_LESS;
83 break;
84 case GL_EQUAL:
85 pp_misc |= R200_ALPHA_TEST_EQUAL;
86 break;
87 case GL_LEQUAL:
88 pp_misc |= R200_ALPHA_TEST_LEQUAL;
89 break;
90 case GL_GREATER:
91 pp_misc |= R200_ALPHA_TEST_GREATER;
92 break;
93 case GL_NOTEQUAL:
94 pp_misc |= R200_ALPHA_TEST_NEQUAL;
95 break;
96 case GL_GEQUAL:
97 pp_misc |= R200_ALPHA_TEST_GEQUAL;
98 break;
99 case GL_ALWAYS:
100 pp_misc |= R200_ALPHA_TEST_PASS;
101 break;
102 }
103
104 rmesa->hw.ctx.cmd[CTX_PP_MISC] = pp_misc;
105 }
106
107 static void r200BlendEquation( GLcontext *ctx, GLenum mode )
108 {
109 r200ContextPtr rmesa = R200_CONTEXT(ctx);
110 GLuint b = rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] & ~R200_COMB_FCN_MASK;
111
112 switch ( mode ) {
113 case GL_FUNC_ADD:
114 case GL_LOGIC_OP:
115 b |= R200_COMB_FCN_ADD_CLAMP;
116 break;
117
118 case GL_FUNC_SUBTRACT:
119 b |= R200_COMB_FCN_SUB_CLAMP;
120 break;
121
122 case GL_FUNC_REVERSE_SUBTRACT:
123 b |= R200_COMB_FCN_RSUB_CLAMP;
124 break;
125
126 case GL_MIN:
127 b |= R200_COMB_FCN_MIN;
128 break;
129
130 case GL_MAX:
131 b |= R200_COMB_FCN_MAX;
132 break;
133
134 default:
135 break;
136 }
137
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;
142 } else {
143 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_ROP_ENABLE;
144 }
145 }
146
147 static void r200BlendFuncSeparate( GLcontext *ctx,
148 GLenum sfactorRGB, GLenum dfactorRGB,
149 GLenum sfactorA, GLenum dfactorA )
150 {
151 r200ContextPtr rmesa = R200_CONTEXT(ctx);
152 GLuint b = rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] &
153 ~(R200_SRC_BLEND_MASK | R200_DST_BLEND_MASK);
154
155 switch ( ctx->Color.BlendSrcRGB ) {
156 case GL_ZERO:
157 b |= R200_SRC_BLEND_GL_ZERO;
158 break;
159 case GL_ONE:
160 b |= R200_SRC_BLEND_GL_ONE;
161 break;
162 case GL_DST_COLOR:
163 b |= R200_SRC_BLEND_GL_DST_COLOR;
164 break;
165 case GL_ONE_MINUS_DST_COLOR:
166 b |= R200_SRC_BLEND_GL_ONE_MINUS_DST_COLOR;
167 break;
168 case GL_SRC_COLOR:
169 b |= R200_SRC_BLEND_GL_SRC_COLOR;
170 break;
171 case GL_ONE_MINUS_SRC_COLOR:
172 b |= R200_SRC_BLEND_GL_ONE_MINUS_SRC_COLOR;
173 break;
174 case GL_SRC_ALPHA:
175 b |= R200_SRC_BLEND_GL_SRC_ALPHA;
176 break;
177 case GL_ONE_MINUS_SRC_ALPHA:
178 b |= R200_SRC_BLEND_GL_ONE_MINUS_SRC_ALPHA;
179 break;
180 case GL_DST_ALPHA:
181 b |= R200_SRC_BLEND_GL_DST_ALPHA;
182 break;
183 case GL_ONE_MINUS_DST_ALPHA:
184 b |= R200_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA;
185 break;
186 case GL_SRC_ALPHA_SATURATE:
187 b |= R200_SRC_BLEND_GL_SRC_ALPHA_SATURATE;
188 break;
189 case GL_CONSTANT_COLOR:
190 b |= R200_SRC_BLEND_GL_CONST_COLOR;
191 break;
192 case GL_ONE_MINUS_CONSTANT_COLOR:
193 b |= R200_SRC_BLEND_GL_ONE_MINUS_CONST_COLOR;
194 break;
195 case GL_CONSTANT_ALPHA:
196 b |= R200_SRC_BLEND_GL_CONST_ALPHA;
197 break;
198 case GL_ONE_MINUS_CONSTANT_ALPHA:
199 b |= R200_SRC_BLEND_GL_ONE_MINUS_CONST_ALPHA;
200 break;
201 default:
202 break;
203 }
204
205 switch ( ctx->Color.BlendDstRGB ) {
206 case GL_ZERO:
207 b |= R200_DST_BLEND_GL_ZERO;
208 break;
209 case GL_ONE:
210 b |= R200_DST_BLEND_GL_ONE;
211 break;
212 case GL_SRC_COLOR:
213 b |= R200_DST_BLEND_GL_SRC_COLOR;
214 break;
215 case GL_ONE_MINUS_SRC_COLOR:
216 b |= R200_DST_BLEND_GL_ONE_MINUS_SRC_COLOR;
217 break;
218 case GL_SRC_ALPHA:
219 b |= R200_DST_BLEND_GL_SRC_ALPHA;
220 break;
221 case GL_ONE_MINUS_SRC_ALPHA:
222 b |= R200_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA;
223 break;
224 case GL_DST_COLOR:
225 b |= R200_DST_BLEND_GL_DST_COLOR;
226 break;
227 case GL_ONE_MINUS_DST_COLOR:
228 b |= R200_DST_BLEND_GL_ONE_MINUS_DST_COLOR;
229 break;
230 case GL_DST_ALPHA:
231 b |= R200_DST_BLEND_GL_DST_ALPHA;
232 break;
233 case GL_ONE_MINUS_DST_ALPHA:
234 b |= R200_DST_BLEND_GL_ONE_MINUS_DST_ALPHA;
235 break;
236 case GL_CONSTANT_COLOR:
237 b |= R200_DST_BLEND_GL_CONST_COLOR;
238 break;
239 case GL_ONE_MINUS_CONSTANT_COLOR:
240 b |= R200_DST_BLEND_GL_ONE_MINUS_CONST_COLOR;
241 break;
242 case GL_CONSTANT_ALPHA:
243 b |= R200_DST_BLEND_GL_CONST_ALPHA;
244 break;
245 case GL_ONE_MINUS_CONSTANT_ALPHA:
246 b |= R200_DST_BLEND_GL_ONE_MINUS_CONST_ALPHA;
247 break;
248 default:
249 break;
250 }
251
252 R200_STATECHANGE( rmesa, ctx );
253 rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = b;
254 }
255
256
257 /* =============================================================
258 * Depth testing
259 */
260
261 static void r200DepthFunc( GLcontext *ctx, GLenum func )
262 {
263 r200ContextPtr rmesa = R200_CONTEXT(ctx);
264
265 R200_STATECHANGE( rmesa, ctx );
266 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_Z_TEST_MASK;
267
268 switch ( ctx->Depth.Func ) {
269 case GL_NEVER:
270 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_NEVER;
271 break;
272 case GL_LESS:
273 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_LESS;
274 break;
275 case GL_EQUAL:
276 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_EQUAL;
277 break;
278 case GL_LEQUAL:
279 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_LEQUAL;
280 break;
281 case GL_GREATER:
282 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_GREATER;
283 break;
284 case GL_NOTEQUAL:
285 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_NEQUAL;
286 break;
287 case GL_GEQUAL:
288 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_GEQUAL;
289 break;
290 case GL_ALWAYS:
291 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_ALWAYS;
292 break;
293 }
294 }
295
296
297 static void r200DepthMask( GLcontext *ctx, GLboolean flag )
298 {
299 r200ContextPtr rmesa = R200_CONTEXT(ctx);
300 R200_STATECHANGE( rmesa, ctx );
301
302 if ( ctx->Depth.Mask ) {
303 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_WRITE_ENABLE;
304 } else {
305 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_Z_WRITE_ENABLE;
306 }
307 }
308
309
310 /* =============================================================
311 * Fog
312 */
313
314
315 static void r200Fogfv( GLcontext *ctx, GLenum pname, const GLfloat *param )
316 {
317 r200ContextPtr rmesa = R200_CONTEXT(ctx);
318 union { int i; float f; } c, d;
319 GLchan col[4];
320 GLuint i;
321
322 c.i = rmesa->hw.fog.cmd[FOG_C];
323 d.i = rmesa->hw.fog.cmd[FOG_D];
324
325 switch (pname) {
326 case GL_FOG_MODE:
327 if (!ctx->Fog.Enabled)
328 return;
329 R200_STATECHANGE(rmesa, tcl);
330 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_TCL_FOG_MASK;
331 switch (ctx->Fog.Mode) {
332 case GL_LINEAR:
333 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_TCL_FOG_LINEAR;
334 if (ctx->Fog.Start == ctx->Fog.End) {
335 c.f = 1.0F;
336 d.f = 1.0F;
337 }
338 else {
339 c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start);
340 d.f = -1.0/(ctx->Fog.End-ctx->Fog.Start);
341 }
342 break;
343 case GL_EXP:
344 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_TCL_FOG_EXP;
345 c.f = 0.0;
346 d.f = -ctx->Fog.Density;
347 break;
348 case GL_EXP2:
349 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_TCL_FOG_EXP2;
350 c.f = 0.0;
351 d.f = -(ctx->Fog.Density * ctx->Fog.Density);
352 break;
353 default:
354 return;
355 }
356 break;
357 case GL_FOG_DENSITY:
358 switch (ctx->Fog.Mode) {
359 case GL_EXP:
360 c.f = 0.0;
361 d.f = -ctx->Fog.Density;
362 break;
363 case GL_EXP2:
364 c.f = 0.0;
365 d.f = -(ctx->Fog.Density * ctx->Fog.Density);
366 break;
367 default:
368 break;
369 }
370 break;
371 case GL_FOG_START:
372 case GL_FOG_END:
373 if (ctx->Fog.Mode == GL_LINEAR) {
374 if (ctx->Fog.Start == ctx->Fog.End) {
375 c.f = 1.0F;
376 d.f = 1.0F;
377 } else {
378 c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start);
379 d.f = -1.0/(ctx->Fog.End-ctx->Fog.Start);
380 }
381 }
382 break;
383 case GL_FOG_COLOR:
384 R200_STATECHANGE( rmesa, ctx );
385 UNCLAMPED_FLOAT_TO_RGB_CHAN( col, ctx->Fog.Color );
386 i = r200PackColor( 4, col[0], col[1], col[2], 0 );
387 rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] &= ~R200_FOG_COLOR_MASK;
388 rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] |= i;
389 break;
390 case GL_FOG_COORDINATE_SOURCE_EXT:
391 /* What to do?
392 */
393 break;
394 default:
395 return;
396 }
397
398 if (c.i != rmesa->hw.fog.cmd[FOG_C] || d.i != rmesa->hw.fog.cmd[FOG_D]) {
399 R200_STATECHANGE( rmesa, fog );
400 rmesa->hw.fog.cmd[FOG_C] = c.i;
401 rmesa->hw.fog.cmd[FOG_D] = d.i;
402 }
403 }
404
405
406 /* =============================================================
407 * Scissoring
408 */
409
410
411 static GLboolean intersect_rect( XF86DRIClipRectPtr out,
412 XF86DRIClipRectPtr a,
413 XF86DRIClipRectPtr b )
414 {
415 *out = *a;
416 if ( b->x1 > out->x1 ) out->x1 = b->x1;
417 if ( b->y1 > out->y1 ) out->y1 = b->y1;
418 if ( b->x2 < out->x2 ) out->x2 = b->x2;
419 if ( b->y2 < out->y2 ) out->y2 = b->y2;
420 if ( out->x1 >= out->x2 ) return GL_FALSE;
421 if ( out->y1 >= out->y2 ) return GL_FALSE;
422 return GL_TRUE;
423 }
424
425
426 void r200RecalcScissorRects( r200ContextPtr rmesa )
427 {
428 XF86DRIClipRectPtr out;
429 int i;
430
431 /* Grow cliprect store?
432 */
433 if (rmesa->state.scissor.numAllocedClipRects < rmesa->numClipRects) {
434 while (rmesa->state.scissor.numAllocedClipRects < rmesa->numClipRects) {
435 rmesa->state.scissor.numAllocedClipRects += 1; /* zero case */
436 rmesa->state.scissor.numAllocedClipRects *= 2;
437 }
438
439 if (rmesa->state.scissor.pClipRects)
440 FREE(rmesa->state.scissor.pClipRects);
441
442 rmesa->state.scissor.pClipRects =
443 MALLOC( rmesa->state.scissor.numAllocedClipRects *
444 sizeof(XF86DRIClipRectRec) );
445
446 if ( rmesa->state.scissor.pClipRects == NULL ) {
447 rmesa->state.scissor.numAllocedClipRects = 0;
448 return;
449 }
450 }
451
452 out = rmesa->state.scissor.pClipRects;
453 rmesa->state.scissor.numClipRects = 0;
454
455 for ( i = 0 ; i < rmesa->numClipRects ; i++ ) {
456 if ( intersect_rect( out,
457 &rmesa->pClipRects[i],
458 &rmesa->state.scissor.rect ) ) {
459 rmesa->state.scissor.numClipRects++;
460 out++;
461 }
462 }
463 }
464
465
466 static void r200UpdateScissor( GLcontext *ctx )
467 {
468 r200ContextPtr rmesa = R200_CONTEXT(ctx);
469
470 if ( rmesa->dri.drawable ) {
471 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
472
473 int x = ctx->Scissor.X;
474 int y = dPriv->h - ctx->Scissor.Y - ctx->Scissor.Height;
475 int w = ctx->Scissor.X + ctx->Scissor.Width - 1;
476 int h = dPriv->h - ctx->Scissor.Y - 1;
477
478 rmesa->state.scissor.rect.x1 = x + dPriv->x;
479 rmesa->state.scissor.rect.y1 = y + dPriv->y;
480 rmesa->state.scissor.rect.x2 = w + dPriv->x + 1;
481 rmesa->state.scissor.rect.y2 = h + dPriv->y + 1;
482
483 r200RecalcScissorRects( rmesa );
484 }
485 }
486
487
488 static void r200Scissor( GLcontext *ctx,
489 GLint x, GLint y, GLsizei w, GLsizei h )
490 {
491 r200ContextPtr rmesa = R200_CONTEXT(ctx);
492
493 if ( ctx->Scissor.Enabled ) {
494 R200_FIREVERTICES( rmesa ); /* don't pipeline cliprect changes */
495 r200UpdateScissor( ctx );
496 }
497
498 }
499
500
501 /* =============================================================
502 * Culling
503 */
504
505 static void r200CullFace( GLcontext *ctx, GLenum unused )
506 {
507 r200ContextPtr rmesa = R200_CONTEXT(ctx);
508 GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL];
509 GLuint t = rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL];
510
511 s |= R200_FFACE_SOLID | R200_BFACE_SOLID;
512 t &= ~(R200_CULL_FRONT | R200_CULL_BACK);
513
514 if ( ctx->Polygon.CullFlag ) {
515 switch ( ctx->Polygon.CullFaceMode ) {
516 case GL_FRONT:
517 s &= ~R200_FFACE_SOLID;
518 t |= R200_CULL_FRONT;
519 break;
520 case GL_BACK:
521 s &= ~R200_BFACE_SOLID;
522 t |= R200_CULL_BACK;
523 break;
524 case GL_FRONT_AND_BACK:
525 s &= ~(R200_FFACE_SOLID | R200_BFACE_SOLID);
526 t |= (R200_CULL_FRONT | R200_CULL_BACK);
527 break;
528 }
529 }
530
531 if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) {
532 R200_STATECHANGE(rmesa, set );
533 rmesa->hw.set.cmd[SET_SE_CNTL] = s;
534 }
535
536 if ( rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] != t ) {
537 R200_STATECHANGE(rmesa, tcl );
538 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] = t;
539 }
540 }
541
542 static void r200FrontFace( GLcontext *ctx, GLenum mode )
543 {
544 r200ContextPtr rmesa = R200_CONTEXT(ctx);
545
546 R200_STATECHANGE( rmesa, set );
547 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_FFACE_CULL_DIR_MASK;
548
549 R200_STATECHANGE( rmesa, tcl );
550 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_CULL_FRONT_IS_CCW;
551
552 switch ( mode ) {
553 case GL_CW:
554 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_FFACE_CULL_CW;
555 break;
556 case GL_CCW:
557 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_FFACE_CULL_CCW;
558 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_CULL_FRONT_IS_CCW;
559 break;
560 }
561 }
562
563 /* =============================================================
564 * Point state
565 */
566 static void r200PointSize( GLcontext *ctx, GLfloat size )
567 {
568 if (0) fprintf(stderr, "%s: %f\n", __FUNCTION__, size );
569 }
570
571 /* =============================================================
572 * Line state
573 */
574 static void r200LineWidth( GLcontext *ctx, GLfloat widthf )
575 {
576 r200ContextPtr rmesa = R200_CONTEXT(ctx);
577
578 R200_STATECHANGE( rmesa, lin );
579 R200_STATECHANGE( rmesa, set );
580
581 /* Line width is stored in U6.4 format.
582 */
583 rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] &= ~0xffff;
584 rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] |= (GLuint)(ctx->Line._Width * 16.0);
585
586 if ( widthf > 1.0 ) {
587 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_WIDELINE_ENABLE;
588 } else {
589 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_WIDELINE_ENABLE;
590 }
591 }
592
593 static void r200LineStipple( GLcontext *ctx, GLint factor, GLushort pattern )
594 {
595 r200ContextPtr rmesa = R200_CONTEXT(ctx);
596
597 R200_STATECHANGE( rmesa, lin );
598 rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] =
599 ((((GLuint)factor & 0xff) << 16) | ((GLuint)pattern));
600 }
601
602
603 /* =============================================================
604 * Masks
605 */
606 static void r200ColorMask( GLcontext *ctx,
607 GLboolean r, GLboolean g,
608 GLboolean b, GLboolean a )
609 {
610 r200ContextPtr rmesa = R200_CONTEXT(ctx);
611 GLuint mask = r200PackColor( rmesa->r200Screen->cpp,
612 ctx->Color.ColorMask[RCOMP],
613 ctx->Color.ColorMask[GCOMP],
614 ctx->Color.ColorMask[BCOMP],
615 ctx->Color.ColorMask[ACOMP] );
616
617 GLuint flag = rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] & ~R200_PLANE_MASK_ENABLE;
618
619 if (!(r && g && b && a))
620 flag |= R200_PLANE_MASK_ENABLE;
621
622 if ( rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] != flag ) {
623 R200_STATECHANGE( rmesa, ctx );
624 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = flag;
625 }
626
627 if ( rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] != mask ) {
628 R200_STATECHANGE( rmesa, msk );
629 rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] = mask;
630 }
631 }
632
633
634 /* =============================================================
635 * Polygon state
636 */
637
638 static void r200PolygonOffset( GLcontext *ctx,
639 GLfloat factor, GLfloat units )
640 {
641 r200ContextPtr rmesa = R200_CONTEXT(ctx);
642 GLfloat constant = units * rmesa->state.depth.scale;
643
644 /* factor *= 2; */
645 /* constant *= 2; */
646
647 /* fprintf(stderr, "%s f:%f u:%f\n", __FUNCTION__, factor, constant); */
648
649 R200_STATECHANGE( rmesa, zbs );
650 rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_FACTOR] = *(GLuint *)&factor;
651 rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_CONSTANT] = *(GLuint *)&constant;
652 }
653
654 static void r200PolygonStipple( GLcontext *ctx, const GLubyte *mask )
655 {
656 r200ContextPtr rmesa = R200_CONTEXT(ctx);
657 GLuint i;
658 drmRadeonStipple stipple;
659
660 /* Must flip pattern upside down.
661 */
662 for ( i = 0 ; i < 32 ; i++ ) {
663 rmesa->state.stipple.mask[31 - i] = ((GLuint *) mask)[i];
664 }
665
666 /* TODO: push this into cmd mechanism
667 */
668 R200_FIREVERTICES( rmesa );
669 LOCK_HARDWARE( rmesa );
670
671 /* FIXME: Use window x,y offsets into stipple RAM.
672 */
673 stipple.mask = rmesa->state.stipple.mask;
674 drmCommandWrite( rmesa->dri.fd, DRM_RADEON_STIPPLE,
675 &stipple, sizeof(drmRadeonStipple) );
676 UNLOCK_HARDWARE( rmesa );
677 }
678
679 static void r200PolygonMode( GLcontext *ctx, GLenum face, GLenum mode )
680 {
681 r200ContextPtr rmesa = R200_CONTEXT(ctx);
682 GLboolean flag = (ctx->_TriangleCaps & DD_TRI_UNFILLED) != 0;
683
684 /* Can't generally do unfilled via tcl, but some good special
685 * cases work.
686 */
687 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_UNFILLED, flag);
688 if (rmesa->TclFallback) {
689 r200ChooseRenderState( ctx );
690 r200ChooseVertexState( ctx );
691 }
692 }
693
694
695 /* =============================================================
696 * Rendering attributes
697 *
698 * We really don't want to recalculate all this every time we bind a
699 * texture. These things shouldn't change all that often, so it makes
700 * sense to break them out of the core texture state update routines.
701 */
702
703 /* Examine lighting and texture state to determine if separate specular
704 * should be enabled.
705 */
706 static void r200UpdateSpecular( GLcontext *ctx )
707 {
708 r200ContextPtr rmesa = R200_CONTEXT(ctx);
709 CARD32 p = rmesa->hw.ctx.cmd[CTX_PP_CNTL];
710
711 R200_STATECHANGE( rmesa, tcl );
712 R200_STATECHANGE( rmesa, vtx );
713
714 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] &= ~(3<<R200_VTX_COLOR_0_SHIFT);
715 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] &= ~(3<<R200_VTX_COLOR_1_SHIFT);
716 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] &= ~R200_OUTPUT_COLOR_0;
717 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] &= ~R200_OUTPUT_COLOR_1;
718 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_LIGHTING_ENABLE;
719
720 p &= ~R200_SPECULAR_ENABLE;
721
722 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_DIFFUSE_SPECULAR_COMBINE;
723
724
725 if (ctx->Light.Enabled &&
726 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) {
727 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
728 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT) |
729 (R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT));
730 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_0;
731 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_1;
732 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHTING_ENABLE;
733 p |= R200_SPECULAR_ENABLE;
734 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &=
735 ~R200_DIFFUSE_SPECULAR_COMBINE;
736 }
737 else if (ctx->Light.Enabled) {
738 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
739 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT));
740 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_0;
741 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHTING_ENABLE;
742 } else if (ctx->Fog.ColorSumEnabled ) {
743 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
744 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT) |
745 (R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT));
746 p |= R200_SPECULAR_ENABLE;
747 } else {
748 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
749 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT));
750 }
751
752 if (ctx->Fog.Enabled) {
753 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
754 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT));
755 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_1;
756 }
757
758 if ( rmesa->hw.ctx.cmd[CTX_PP_CNTL] != p ) {
759 R200_STATECHANGE( rmesa, ctx );
760 rmesa->hw.ctx.cmd[CTX_PP_CNTL] = p;
761 }
762
763 /* Update vertex/render formats
764 */
765 if (rmesa->TclFallback) {
766 r200ChooseRenderState( ctx );
767 r200ChooseVertexState( ctx );
768 }
769 }
770
771
772 /* =============================================================
773 * Materials
774 */
775
776
777 /* Update on colormaterial, material emmissive/ambient,
778 * lightmodel.globalambient
779 */
780 static void update_global_ambient( GLcontext *ctx )
781 {
782 r200ContextPtr rmesa = R200_CONTEXT(ctx);
783 float *fcmd = (float *)R200_DB_STATE( glt );
784
785 /* Need to do more if both emmissive & ambient are PREMULT:
786 */
787 if ((rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1] &
788 ((3 << R200_FRONT_EMISSIVE_SOURCE_SHIFT) |
789 (3 << R200_FRONT_AMBIENT_SOURCE_SHIFT))) == 0)
790 {
791 COPY_3V( &fcmd[GLT_RED],
792 ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION]);
793 ACC_SCALE_3V( &fcmd[GLT_RED],
794 ctx->Light.Model.Ambient,
795 ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT]);
796 }
797 else
798 {
799 COPY_3V( &fcmd[GLT_RED], ctx->Light.Model.Ambient );
800 }
801
802 R200_DB_STATECHANGE(rmesa, &rmesa->hw.glt);
803 }
804
805 /* Update on change to
806 * - light[p].colors
807 * - light[p].enabled
808 * - material,
809 * - colormaterial enabled
810 * - colormaterial bitmask
811 */
812 static void update_light_colors( GLcontext *ctx, GLuint p )
813 {
814 struct gl_light *l = &ctx->Light.Light[p];
815
816 /* fprintf(stderr, "%s\n", __FUNCTION__); */
817
818 if (l->Enabled) {
819 r200ContextPtr rmesa = R200_CONTEXT(ctx);
820 float *fcmd = (float *)R200_DB_STATE( lit[p] );
821 GLuint bitmask = ctx->Light.ColorMaterialBitmask;
822 GLfloat (*mat)[4] = ctx->Light.Material.Attrib;
823
824 COPY_4V( &fcmd[LIT_AMBIENT_RED], l->Ambient );
825 COPY_4V( &fcmd[LIT_DIFFUSE_RED], l->Diffuse );
826 COPY_4V( &fcmd[LIT_SPECULAR_RED], l->Specular );
827
828 if (!ctx->Light.ColorMaterialEnabled)
829 bitmask = 0;
830
831 if ((bitmask & MAT_BIT_FRONT_AMBIENT) == 0)
832 SELF_SCALE_3V( &fcmd[LIT_AMBIENT_RED], mat[MAT_ATTRIB_FRONT_AMBIENT] );
833
834 if ((bitmask & MAT_BIT_FRONT_DIFFUSE) == 0)
835 SELF_SCALE_3V( &fcmd[LIT_DIFFUSE_RED], mat[MAT_ATTRIB_FRONT_DIFFUSE] );
836
837 if ((bitmask & MAT_BIT_FRONT_SPECULAR) == 0)
838 SELF_SCALE_3V( &fcmd[LIT_SPECULAR_RED], mat[MAT_ATTRIB_FRONT_SPECULAR] );
839
840 R200_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
841 }
842 }
843
844 /* Also fallback for asym colormaterial mode in twoside lighting...
845 */
846 static void check_twoside_fallback( GLcontext *ctx )
847 {
848 GLboolean fallback = GL_FALSE;
849 GLint i;
850
851 if (ctx->Light.Enabled && ctx->Light.Model.TwoSide) {
852 if (ctx->Light.ColorMaterialEnabled &&
853 (ctx->Light.ColorMaterialBitmask & BACK_MATERIAL_BITS) !=
854 ((ctx->Light.ColorMaterialBitmask & FRONT_MATERIAL_BITS)<<1))
855 fallback = GL_TRUE;
856 else {
857 for (i = MAT_ATTRIB_FRONT_AMBIENT; i < MAT_ATTRIB_FRONT_INDEXES; i+=2)
858 if (memcmp( ctx->Light.Material.Attrib[i],
859 ctx->Light.Material.Attrib[i+1],
860 sizeof(GLfloat)*4) != 0) {
861 fallback = GL_TRUE;
862 break;
863 }
864 }
865 }
866
867 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_LIGHT_TWOSIDE, fallback );
868 }
869
870 static void r200ColorMaterial( GLcontext *ctx, GLenum face, GLenum mode )
871 {
872 if (ctx->Light.ColorMaterialEnabled) {
873 r200ContextPtr rmesa = R200_CONTEXT(ctx);
874 GLuint light_model_ctl1 = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1];
875 GLuint mask = ctx->Light.ColorMaterialBitmask;
876
877 /* Default to PREMULT:
878 */
879 light_model_ctl1 &= ~((0xf << R200_FRONT_EMISSIVE_SOURCE_SHIFT) |
880 (0xf << R200_FRONT_AMBIENT_SOURCE_SHIFT) |
881 (0xf << R200_FRONT_DIFFUSE_SOURCE_SHIFT) |
882 (0xf << R200_FRONT_SPECULAR_SOURCE_SHIFT));
883
884 if (mask & MAT_BIT_FRONT_EMISSION) {
885 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
886 R200_FRONT_EMISSIVE_SOURCE_SHIFT);
887 }
888
889 if (mask & MAT_BIT_FRONT_AMBIENT) {
890 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
891 R200_FRONT_AMBIENT_SOURCE_SHIFT);
892 }
893
894 if (mask & MAT_BIT_FRONT_DIFFUSE) {
895 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
896 R200_FRONT_DIFFUSE_SOURCE_SHIFT);
897 }
898
899 if (mask & MAT_BIT_FRONT_SPECULAR) {
900 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
901 R200_FRONT_SPECULAR_SOURCE_SHIFT);
902 }
903
904 if (light_model_ctl1 != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1]) {
905 GLuint p;
906
907 R200_STATECHANGE( rmesa, tcl );
908 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1] = light_model_ctl1;
909
910 for (p = 0 ; p < MAX_LIGHTS; p++)
911 update_light_colors( ctx, p );
912 update_global_ambient( ctx );
913 }
914 }
915
916 check_twoside_fallback( ctx );
917 }
918
919 void r200UpdateMaterial( GLcontext *ctx )
920 {
921 r200ContextPtr rmesa = R200_CONTEXT(ctx);
922 GLfloat (*mat)[4] = ctx->Light.Material.Attrib;
923 GLfloat *fcmd = (GLfloat *)R200_DB_STATE( mtl[0] );
924 GLuint p;
925 GLuint mask = ~0;
926
927 if (ctx->Light.ColorMaterialEnabled)
928 mask &= ~ctx->Light.ColorMaterialBitmask;
929
930 if (R200_DEBUG & DEBUG_STATE)
931 fprintf(stderr, "%s\n", __FUNCTION__);
932
933
934 if (mask & MAT_BIT_FRONT_EMISSION) {
935 fcmd[MTL_EMMISSIVE_RED] = mat[MAT_ATTRIB_FRONT_EMISSION][0];
936 fcmd[MTL_EMMISSIVE_GREEN] = mat[MAT_ATTRIB_FRONT_EMISSION][1];
937 fcmd[MTL_EMMISSIVE_BLUE] = mat[MAT_ATTRIB_FRONT_EMISSION][2];
938 fcmd[MTL_EMMISSIVE_ALPHA] = mat[MAT_ATTRIB_FRONT_EMISSION][3];
939 }
940 if (mask & MAT_BIT_FRONT_AMBIENT) {
941 fcmd[MTL_AMBIENT_RED] = mat[MAT_ATTRIB_FRONT_AMBIENT][0];
942 fcmd[MTL_AMBIENT_GREEN] = mat[MAT_ATTRIB_FRONT_AMBIENT][1];
943 fcmd[MTL_AMBIENT_BLUE] = mat[MAT_ATTRIB_FRONT_AMBIENT][2];
944 fcmd[MTL_AMBIENT_ALPHA] = mat[MAT_ATTRIB_FRONT_AMBIENT][3];
945 }
946 if (mask & MAT_BIT_FRONT_DIFFUSE) {
947 fcmd[MTL_DIFFUSE_RED] = mat[MAT_ATTRIB_FRONT_DIFFUSE][0];
948 fcmd[MTL_DIFFUSE_GREEN] = mat[MAT_ATTRIB_FRONT_DIFFUSE][1];
949 fcmd[MTL_DIFFUSE_BLUE] = mat[MAT_ATTRIB_FRONT_DIFFUSE][2];
950 fcmd[MTL_DIFFUSE_ALPHA] = mat[MAT_ATTRIB_FRONT_DIFFUSE][3];
951 }
952 if (mask & MAT_BIT_FRONT_SPECULAR) {
953 fcmd[MTL_SPECULAR_RED] = mat[MAT_ATTRIB_FRONT_SPECULAR][0];
954 fcmd[MTL_SPECULAR_GREEN] = mat[MAT_ATTRIB_FRONT_SPECULAR][1];
955 fcmd[MTL_SPECULAR_BLUE] = mat[MAT_ATTRIB_FRONT_SPECULAR][2];
956 fcmd[MTL_SPECULAR_ALPHA] = mat[MAT_ATTRIB_FRONT_SPECULAR][3];
957 }
958 if (mask & MAT_BIT_FRONT_SHININESS) {
959 fcmd[MTL_SHININESS] = mat[MAT_ATTRIB_FRONT_SHININESS][0];
960 }
961
962 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mtl[0] );
963
964 for (p = 0 ; p < MAX_LIGHTS; p++)
965 update_light_colors( ctx, p );
966
967 check_twoside_fallback( ctx );
968 update_global_ambient( ctx );
969 }
970
971 /* _NEW_LIGHT
972 * _NEW_MODELVIEW
973 * _MESA_NEW_NEED_EYE_COORDS
974 *
975 * Uses derived state from mesa:
976 * _VP_inf_norm
977 * _h_inf_norm
978 * _Position
979 * _NormDirection
980 * _ModelViewInvScale
981 * _NeedEyeCoords
982 * _EyeZDir
983 *
984 * which are calculated in light.c and are correct for the current
985 * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
986 * and _MESA_NEW_NEED_EYE_COORDS.
987 */
988 static void update_light( GLcontext *ctx )
989 {
990 r200ContextPtr rmesa = R200_CONTEXT(ctx);
991
992 /* Have to check these, or have an automatic shortcircuit mechanism
993 * to remove noop statechanges. (Or just do a better job on the
994 * front end).
995 */
996 {
997 GLuint tmp = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0];
998
999 if (ctx->_NeedEyeCoords)
1000 tmp &= ~R200_LIGHT_IN_MODELSPACE;
1001 else
1002 tmp |= R200_LIGHT_IN_MODELSPACE;
1003
1004 if (tmp != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0])
1005 {
1006 R200_STATECHANGE( rmesa, tcl );
1007 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] = tmp;
1008 }
1009 }
1010
1011 {
1012 GLfloat *fcmd = (GLfloat *)R200_DB_STATE( eye );
1013 fcmd[EYE_X] = ctx->_EyeZDir[0];
1014 fcmd[EYE_Y] = ctx->_EyeZDir[1];
1015 fcmd[EYE_Z] = - ctx->_EyeZDir[2];
1016 fcmd[EYE_RESCALE_FACTOR] = ctx->_ModelViewInvScale;
1017 R200_DB_STATECHANGE( rmesa, &rmesa->hw.eye );
1018 }
1019
1020
1021
1022 if (ctx->Light.Enabled) {
1023 GLint p;
1024 for (p = 0 ; p < MAX_LIGHTS; p++) {
1025 if (ctx->Light.Light[p].Enabled) {
1026 struct gl_light *l = &ctx->Light.Light[p];
1027 GLfloat *fcmd = (GLfloat *)R200_DB_STATE( lit[p] );
1028
1029 if (l->EyePosition[3] == 0.0) {
1030 COPY_3FV( &fcmd[LIT_POSITION_X], l->_VP_inf_norm );
1031 COPY_3FV( &fcmd[LIT_DIRECTION_X], l->_h_inf_norm );
1032 fcmd[LIT_POSITION_W] = 0;
1033 fcmd[LIT_DIRECTION_W] = 0;
1034 } else {
1035 COPY_4V( &fcmd[LIT_POSITION_X], l->_Position );
1036 fcmd[LIT_DIRECTION_X] = -l->_NormDirection[0];
1037 fcmd[LIT_DIRECTION_Y] = -l->_NormDirection[1];
1038 fcmd[LIT_DIRECTION_Z] = -l->_NormDirection[2];
1039 fcmd[LIT_DIRECTION_W] = 0;
1040 }
1041
1042 R200_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
1043 }
1044 }
1045 }
1046 }
1047
1048 static void r200Lightfv( GLcontext *ctx, GLenum light,
1049 GLenum pname, const GLfloat *params )
1050 {
1051 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1052 GLint p = light - GL_LIGHT0;
1053 struct gl_light *l = &ctx->Light.Light[p];
1054 GLfloat *fcmd = (GLfloat *)rmesa->hw.lit[p].cmd;
1055
1056
1057 switch (pname) {
1058 case GL_AMBIENT:
1059 case GL_DIFFUSE:
1060 case GL_SPECULAR:
1061 update_light_colors( ctx, p );
1062 break;
1063
1064 case GL_SPOT_DIRECTION:
1065 /* picked up in update_light */
1066 break;
1067
1068 case GL_POSITION: {
1069 /* positions picked up in update_light, but can do flag here */
1070 GLuint flag = (p&1)? R200_LIGHT_1_IS_LOCAL : R200_LIGHT_0_IS_LOCAL;
1071 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1072
1073 R200_STATECHANGE(rmesa, tcl);
1074 if (l->EyePosition[3] != 0.0F)
1075 rmesa->hw.tcl.cmd[idx] |= flag;
1076 else
1077 rmesa->hw.tcl.cmd[idx] &= ~flag;
1078 break;
1079 }
1080
1081 case GL_SPOT_EXPONENT:
1082 R200_STATECHANGE(rmesa, lit[p]);
1083 fcmd[LIT_SPOT_EXPONENT] = params[0];
1084 break;
1085
1086 case GL_SPOT_CUTOFF: {
1087 GLuint flag = (p&1) ? R200_LIGHT_1_IS_SPOT : R200_LIGHT_0_IS_SPOT;
1088 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1089
1090 R200_STATECHANGE(rmesa, lit[p]);
1091 fcmd[LIT_SPOT_CUTOFF] = l->_CosCutoff;
1092
1093 R200_STATECHANGE(rmesa, tcl);
1094 if (l->SpotCutoff != 180.0F)
1095 rmesa->hw.tcl.cmd[idx] |= flag;
1096 else
1097 rmesa->hw.tcl.cmd[idx] &= ~flag;
1098
1099 break;
1100 }
1101
1102 case GL_CONSTANT_ATTENUATION:
1103 R200_STATECHANGE(rmesa, lit[p]);
1104 fcmd[LIT_ATTEN_CONST] = params[0];
1105 if ( params[0] == 0.0 )
1106 fcmd[LIT_ATTEN_CONST_INV] = FLT_MAX;
1107 else
1108 fcmd[LIT_ATTEN_CONST_INV] = 1.0 / params[0];
1109 break;
1110 case GL_LINEAR_ATTENUATION:
1111 R200_STATECHANGE(rmesa, lit[p]);
1112 fcmd[LIT_ATTEN_LINEAR] = params[0];
1113 break;
1114 case GL_QUADRATIC_ATTENUATION:
1115 R200_STATECHANGE(rmesa, lit[p]);
1116 fcmd[LIT_ATTEN_QUADRATIC] = params[0];
1117 break;
1118 default:
1119 return;
1120 }
1121
1122 /* Set RANGE_ATTEN only when needed */
1123 switch (pname) {
1124 case GL_POSITION:
1125 case GL_CONSTANT_ATTENUATION:
1126 case GL_LINEAR_ATTENUATION:
1127 case GL_QUADRATIC_ATTENUATION: {
1128 GLuint *icmd = (GLuint *)R200_DB_STATE( tcl );
1129 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1130 GLuint atten_flag = ( p&1 ) ? R200_LIGHT_1_ENABLE_RANGE_ATTEN
1131 : R200_LIGHT_0_ENABLE_RANGE_ATTEN;
1132 GLuint atten_const_flag = ( p&1 ) ? R200_LIGHT_1_CONSTANT_RANGE_ATTEN
1133 : R200_LIGHT_0_CONSTANT_RANGE_ATTEN;
1134
1135 if ( l->EyePosition[3] == 0.0F ||
1136 ( ( fcmd[LIT_ATTEN_CONST] == 0.0 || fcmd[LIT_ATTEN_CONST] == 1.0 ) &&
1137 fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) ) {
1138 /* Disable attenuation */
1139 icmd[idx] &= ~atten_flag;
1140 } else {
1141 if ( fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) {
1142 /* Enable only constant portion of attenuation calculation */
1143 icmd[idx] |= ( atten_flag | atten_const_flag );
1144 } else {
1145 /* Enable full attenuation calculation */
1146 icmd[idx] &= ~atten_const_flag;
1147 icmd[idx] |= atten_flag;
1148 }
1149 }
1150
1151 R200_DB_STATECHANGE( rmesa, &rmesa->hw.tcl );
1152 break;
1153 }
1154 default:
1155 break;
1156 }
1157 }
1158
1159
1160
1161
1162 static void r200LightModelfv( GLcontext *ctx, GLenum pname,
1163 const GLfloat *param )
1164 {
1165 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1166
1167 switch (pname) {
1168 case GL_LIGHT_MODEL_AMBIENT:
1169 update_global_ambient( ctx );
1170 break;
1171
1172 case GL_LIGHT_MODEL_LOCAL_VIEWER:
1173 R200_STATECHANGE( rmesa, tcl );
1174 if (ctx->Light.Model.LocalViewer)
1175 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LOCAL_VIEWER;
1176 else
1177 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_LOCAL_VIEWER;
1178 break;
1179
1180 case GL_LIGHT_MODEL_TWO_SIDE:
1181 R200_STATECHANGE( rmesa, tcl );
1182 if (ctx->Light.Model.TwoSide)
1183 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHT_TWOSIDE;
1184 else
1185 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_LIGHT_TWOSIDE;
1186
1187 check_twoside_fallback( ctx );
1188
1189 if (rmesa->TclFallback) {
1190 r200ChooseRenderState( ctx );
1191 r200ChooseVertexState( ctx );
1192 }
1193 break;
1194
1195 case GL_LIGHT_MODEL_COLOR_CONTROL:
1196 r200UpdateSpecular(ctx);
1197 break;
1198
1199 default:
1200 break;
1201 }
1202 }
1203
1204 static void r200ShadeModel( GLcontext *ctx, GLenum mode )
1205 {
1206 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1207 GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL];
1208
1209 s &= ~(R200_DIFFUSE_SHADE_MASK |
1210 R200_ALPHA_SHADE_MASK |
1211 R200_SPECULAR_SHADE_MASK |
1212 R200_FOG_SHADE_MASK);
1213
1214 switch ( mode ) {
1215 case GL_FLAT:
1216 s |= (R200_DIFFUSE_SHADE_FLAT |
1217 R200_ALPHA_SHADE_FLAT |
1218 R200_SPECULAR_SHADE_FLAT |
1219 R200_FOG_SHADE_FLAT);
1220 break;
1221 case GL_SMOOTH:
1222 s |= (R200_DIFFUSE_SHADE_GOURAUD |
1223 R200_ALPHA_SHADE_GOURAUD |
1224 R200_SPECULAR_SHADE_GOURAUD |
1225 R200_FOG_SHADE_GOURAUD);
1226 break;
1227 default:
1228 return;
1229 }
1230
1231 if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) {
1232 R200_STATECHANGE( rmesa, set );
1233 rmesa->hw.set.cmd[SET_SE_CNTL] = s;
1234 }
1235 }
1236
1237
1238 /* =============================================================
1239 * User clip planes
1240 */
1241
1242 static void r200ClipPlane( GLcontext *ctx, GLenum plane, const GLfloat *eq )
1243 {
1244 GLint p = (GLint) plane - (GLint) GL_CLIP_PLANE0;
1245 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1246 GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
1247
1248 R200_STATECHANGE( rmesa, ucp[p] );
1249 rmesa->hw.ucp[p].cmd[UCP_X] = ip[0];
1250 rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1];
1251 rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2];
1252 rmesa->hw.ucp[p].cmd[UCP_W] = ip[3];
1253 }
1254
1255 static void r200UpdateClipPlanes( GLcontext *ctx )
1256 {
1257 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1258 GLuint p;
1259
1260 for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
1261 if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
1262 GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
1263
1264 R200_STATECHANGE( rmesa, ucp[p] );
1265 rmesa->hw.ucp[p].cmd[UCP_X] = ip[0];
1266 rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1];
1267 rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2];
1268 rmesa->hw.ucp[p].cmd[UCP_W] = ip[3];
1269 }
1270 }
1271 }
1272
1273
1274 /* =============================================================
1275 * Stencil
1276 */
1277
1278 static void r200StencilFunc( GLcontext *ctx, GLenum func,
1279 GLint ref, GLuint mask )
1280 {
1281 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1282 GLuint refmask = ((ctx->Stencil.Ref[0] << R200_STENCIL_REF_SHIFT) |
1283 (ctx->Stencil.ValueMask[0] << R200_STENCIL_MASK_SHIFT));
1284
1285 R200_STATECHANGE( rmesa, ctx );
1286 R200_STATECHANGE( rmesa, msk );
1287
1288 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_STENCIL_TEST_MASK;
1289 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~(R200_STENCIL_REF_MASK|
1290 R200_STENCIL_VALUE_MASK);
1291
1292 switch ( ctx->Stencil.Function[0] ) {
1293 case GL_NEVER:
1294 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_NEVER;
1295 break;
1296 case GL_LESS:
1297 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_LESS;
1298 break;
1299 case GL_EQUAL:
1300 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_EQUAL;
1301 break;
1302 case GL_LEQUAL:
1303 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_LEQUAL;
1304 break;
1305 case GL_GREATER:
1306 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_GREATER;
1307 break;
1308 case GL_NOTEQUAL:
1309 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_NEQUAL;
1310 break;
1311 case GL_GEQUAL:
1312 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_GEQUAL;
1313 break;
1314 case GL_ALWAYS:
1315 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_ALWAYS;
1316 break;
1317 }
1318
1319 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |= refmask;
1320 }
1321
1322 static void r200StencilMask( GLcontext *ctx, GLuint mask )
1323 {
1324 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1325
1326 R200_STATECHANGE( rmesa, msk );
1327 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~R200_STENCIL_WRITE_MASK;
1328 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |=
1329 (ctx->Stencil.WriteMask[0] << R200_STENCIL_WRITEMASK_SHIFT);
1330 }
1331
1332 static void r200StencilOp( GLcontext *ctx, GLenum fail,
1333 GLenum zfail, GLenum zpass )
1334 {
1335 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1336
1337 R200_STATECHANGE( rmesa, ctx );
1338 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~(R200_STENCIL_FAIL_MASK |
1339 R200_STENCIL_ZFAIL_MASK |
1340 R200_STENCIL_ZPASS_MASK);
1341
1342 switch ( ctx->Stencil.FailFunc[0] ) {
1343 case GL_KEEP:
1344 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_KEEP;
1345 break;
1346 case GL_ZERO:
1347 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_ZERO;
1348 break;
1349 case GL_REPLACE:
1350 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_REPLACE;
1351 break;
1352 case GL_INCR:
1353 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INC;
1354 break;
1355 case GL_DECR:
1356 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_DEC;
1357 break;
1358 case GL_INCR_WRAP_EXT:
1359 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INC_WRAP;
1360 break;
1361 case GL_DECR_WRAP_EXT:
1362 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_DEC_WRAP;
1363 break;
1364 case GL_INVERT:
1365 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INVERT;
1366 break;
1367 }
1368
1369 switch ( ctx->Stencil.ZFailFunc[0] ) {
1370 case GL_KEEP:
1371 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_KEEP;
1372 break;
1373 case GL_ZERO:
1374 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_ZERO;
1375 break;
1376 case GL_REPLACE:
1377 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_REPLACE;
1378 break;
1379 case GL_INCR:
1380 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INC;
1381 break;
1382 case GL_DECR:
1383 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_DEC;
1384 break;
1385 case GL_INCR_WRAP_EXT:
1386 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INC_WRAP;
1387 break;
1388 case GL_DECR_WRAP_EXT:
1389 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_DEC_WRAP;
1390 break;
1391 case GL_INVERT:
1392 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INVERT;
1393 break;
1394 }
1395
1396 switch ( ctx->Stencil.ZPassFunc[0] ) {
1397 case GL_KEEP:
1398 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_KEEP;
1399 break;
1400 case GL_ZERO:
1401 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_ZERO;
1402 break;
1403 case GL_REPLACE:
1404 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_REPLACE;
1405 break;
1406 case GL_INCR:
1407 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INC;
1408 break;
1409 case GL_DECR:
1410 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_DEC;
1411 break;
1412 case GL_INCR_WRAP_EXT:
1413 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INC_WRAP;
1414 break;
1415 case GL_DECR_WRAP_EXT:
1416 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_DEC_WRAP;
1417 break;
1418 case GL_INVERT:
1419 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INVERT;
1420 break;
1421 }
1422 }
1423
1424 static void r200ClearStencil( GLcontext *ctx, GLint s )
1425 {
1426 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1427
1428 rmesa->state.stencil.clear =
1429 ((GLuint) ctx->Stencil.Clear |
1430 (0xff << R200_STENCIL_MASK_SHIFT) |
1431 (ctx->Stencil.WriteMask[0] << R200_STENCIL_WRITEMASK_SHIFT));
1432 }
1433
1434
1435 /* =============================================================
1436 * Window position and viewport transformation
1437 */
1438
1439 /*
1440 * To correctly position primitives:
1441 */
1442 #define SUBPIXEL_X 0.125
1443 #define SUBPIXEL_Y 0.125
1444
1445 void r200UpdateWindow( GLcontext *ctx )
1446 {
1447 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1448 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
1449 GLfloat xoffset = (GLfloat)dPriv->x;
1450 GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h;
1451 const GLfloat *v = ctx->Viewport._WindowMap.m;
1452
1453 GLfloat sx = v[MAT_SX];
1454 GLfloat tx = v[MAT_TX] + xoffset + SUBPIXEL_X;
1455 GLfloat sy = - v[MAT_SY];
1456 GLfloat ty = (- v[MAT_TY]) + yoffset + SUBPIXEL_Y;
1457 GLfloat sz = v[MAT_SZ] * rmesa->state.depth.scale;
1458 GLfloat tz = v[MAT_TZ] * rmesa->state.depth.scale;
1459
1460 R200_FIREVERTICES( rmesa );
1461 R200_STATECHANGE( rmesa, vpt );
1462
1463 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XSCALE] = *(GLuint *)&sx;
1464 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = *(GLuint *)&tx;
1465 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YSCALE] = *(GLuint *)&sy;
1466 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = *(GLuint *)&ty;
1467 rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZSCALE] = *(GLuint *)&sz;
1468 rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZOFFSET] = *(GLuint *)&tz;
1469 }
1470
1471
1472
1473 static void r200Viewport( GLcontext *ctx, GLint x, GLint y,
1474 GLsizei width, GLsizei height )
1475 {
1476 /* Don't pipeline viewport changes, conflict with window offset
1477 * setting below. Could apply deltas to rescue pipelined viewport
1478 * values, or keep the originals hanging around.
1479 */
1480 R200_FIREVERTICES( R200_CONTEXT(ctx) );
1481 r200UpdateWindow( ctx );
1482 }
1483
1484 static void r200DepthRange( GLcontext *ctx, GLclampd nearval,
1485 GLclampd farval )
1486 {
1487 r200UpdateWindow( ctx );
1488 }
1489
1490 void r200UpdateViewportOffset( GLcontext *ctx )
1491 {
1492 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1493 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
1494 GLfloat xoffset = (GLfloat)dPriv->x;
1495 GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h;
1496 const GLfloat *v = ctx->Viewport._WindowMap.m;
1497
1498 GLfloat tx = v[MAT_TX] + xoffset;
1499 GLfloat ty = (- v[MAT_TY]) + yoffset;
1500
1501 if ( rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] != *(GLuint *)&tx ||
1502 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] != *(GLuint *)&ty )
1503 {
1504 /* Note: this should also modify whatever data the context reset
1505 * code uses...
1506 */
1507 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = *(GLuint *)&tx;
1508 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = *(GLuint *)&ty;
1509
1510 /* update polygon stipple x/y screen offset */
1511 {
1512 GLuint stx, sty;
1513 GLuint m = rmesa->hw.msc.cmd[MSC_RE_MISC];
1514
1515 m &= ~(R200_STIPPLE_X_OFFSET_MASK |
1516 R200_STIPPLE_Y_OFFSET_MASK);
1517
1518 /* add magic offsets, then invert */
1519 stx = 31 - ((rmesa->dri.drawable->x - 1) & R200_STIPPLE_COORD_MASK);
1520 sty = 31 - ((rmesa->dri.drawable->y + rmesa->dri.drawable->h - 1)
1521 & R200_STIPPLE_COORD_MASK);
1522
1523 m |= ((stx << R200_STIPPLE_X_OFFSET_SHIFT) |
1524 (sty << R200_STIPPLE_Y_OFFSET_SHIFT));
1525
1526 if ( rmesa->hw.msc.cmd[MSC_RE_MISC] != m ) {
1527 R200_STATECHANGE( rmesa, msc );
1528 rmesa->hw.msc.cmd[MSC_RE_MISC] = m;
1529 }
1530 }
1531 }
1532
1533 r200UpdateScissor( ctx );
1534 }
1535
1536
1537
1538 /* =============================================================
1539 * Miscellaneous
1540 */
1541
1542 static void r200ClearColor( GLcontext *ctx, const GLfloat c[4] )
1543 {
1544 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1545 GLubyte color[4];
1546 CLAMPED_FLOAT_TO_UBYTE(color[0], c[0]);
1547 CLAMPED_FLOAT_TO_UBYTE(color[1], c[1]);
1548 CLAMPED_FLOAT_TO_UBYTE(color[2], c[2]);
1549 CLAMPED_FLOAT_TO_UBYTE(color[3], c[3]);
1550 rmesa->state.color.clear = r200PackColor( rmesa->r200Screen->cpp,
1551 color[0], color[1],
1552 color[2], color[3] );
1553 }
1554
1555
1556 static void r200RenderMode( GLcontext *ctx, GLenum mode )
1557 {
1558 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1559 FALLBACK( rmesa, R200_FALLBACK_RENDER_MODE, (mode != GL_RENDER) );
1560 }
1561
1562
1563 static GLuint r200_rop_tab[] = {
1564 R200_ROP_CLEAR,
1565 R200_ROP_AND,
1566 R200_ROP_AND_REVERSE,
1567 R200_ROP_COPY,
1568 R200_ROP_AND_INVERTED,
1569 R200_ROP_NOOP,
1570 R200_ROP_XOR,
1571 R200_ROP_OR,
1572 R200_ROP_NOR,
1573 R200_ROP_EQUIV,
1574 R200_ROP_INVERT,
1575 R200_ROP_OR_REVERSE,
1576 R200_ROP_COPY_INVERTED,
1577 R200_ROP_OR_INVERTED,
1578 R200_ROP_NAND,
1579 R200_ROP_SET,
1580 };
1581
1582 static void r200LogicOpCode( GLcontext *ctx, GLenum opcode )
1583 {
1584 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1585 GLuint rop = (GLuint)opcode - GL_CLEAR;
1586
1587 ASSERT( rop < 16 );
1588
1589 R200_STATECHANGE( rmesa, msk );
1590 rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = r200_rop_tab[rop];
1591 }
1592
1593
1594 void r200SetCliprects( r200ContextPtr rmesa, GLenum mode )
1595 {
1596 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
1597
1598 switch ( mode ) {
1599 case GL_FRONT_LEFT:
1600 rmesa->numClipRects = dPriv->numClipRects;
1601 rmesa->pClipRects = (XF86DRIClipRectPtr)dPriv->pClipRects;
1602 break;
1603 case GL_BACK_LEFT:
1604 /* Can't ignore 2d windows if we are page flipping.
1605 */
1606 if ( dPriv->numBackClipRects == 0 || rmesa->doPageFlip ) {
1607 rmesa->numClipRects = dPriv->numClipRects;
1608 rmesa->pClipRects = (XF86DRIClipRectPtr)dPriv->pClipRects;
1609 }
1610 else {
1611 rmesa->numClipRects = dPriv->numBackClipRects;
1612 rmesa->pClipRects = (XF86DRIClipRectPtr)dPriv->pBackClipRects;
1613 }
1614 break;
1615 default:
1616 fprintf(stderr, "bad mode in r200SetCliprects\n");
1617 return;
1618 }
1619
1620 if (rmesa->state.scissor.enabled)
1621 r200RecalcScissorRects( rmesa );
1622 }
1623
1624
1625 static void r200DrawBuffer( GLcontext *ctx, GLenum mode )
1626 {
1627 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1628
1629 if (R200_DEBUG & DEBUG_DRI)
1630 fprintf(stderr, "%s %s\n", __FUNCTION__,
1631 _mesa_lookup_enum_by_nr( mode ));
1632
1633 R200_FIREVERTICES(rmesa); /* don't pipeline cliprect changes */
1634
1635 /*
1636 * _DrawDestMask is easier to cope with than <mode>.
1637 */
1638 switch ( ctx->Color._DrawDestMask ) {
1639 case FRONT_LEFT_BIT:
1640 FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_FALSE );
1641 r200SetCliprects( rmesa, GL_FRONT_LEFT );
1642 break;
1643 case BACK_LEFT_BIT:
1644 FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_FALSE );
1645 r200SetCliprects( rmesa, GL_BACK_LEFT );
1646 break;
1647 default:
1648 /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */
1649 FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_TRUE );
1650 return;
1651 }
1652
1653 /* We want to update the s/w rast state too so that r200SetBuffer()
1654 * gets called.
1655 */
1656 _swrast_DrawBuffer(ctx, mode);
1657
1658 R200_STATECHANGE( rmesa, ctx );
1659 rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = ((rmesa->state.color.drawOffset +
1660 rmesa->r200Screen->fbLocation)
1661 & R200_COLOROFFSET_MASK);
1662 rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = rmesa->state.color.drawPitch;
1663 }
1664
1665
1666 static void r200ReadBuffer( GLcontext *ctx, GLenum mode )
1667 {
1668 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
1669 }
1670
1671 /* =============================================================
1672 * State enable/disable
1673 */
1674
1675 static void r200Enable( GLcontext *ctx, GLenum cap, GLboolean state )
1676 {
1677 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1678 GLuint p, flag;
1679
1680 if ( R200_DEBUG & DEBUG_STATE )
1681 fprintf( stderr, "%s( %s = %s )\n", __FUNCTION__,
1682 _mesa_lookup_enum_by_nr( cap ),
1683 state ? "GL_TRUE" : "GL_FALSE" );
1684
1685 switch ( cap ) {
1686 /* Fast track this one...
1687 */
1688 case GL_TEXTURE_1D:
1689 case GL_TEXTURE_2D:
1690 case GL_TEXTURE_3D:
1691 break;
1692
1693 case GL_ALPHA_TEST:
1694 R200_STATECHANGE( rmesa, ctx );
1695 if (state) {
1696 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ALPHA_TEST_ENABLE;
1697 } else {
1698 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ALPHA_TEST_ENABLE;
1699 }
1700 break;
1701
1702 case GL_BLEND:
1703 R200_STATECHANGE( rmesa, ctx );
1704 if (state) {
1705 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_ALPHA_BLEND_ENABLE;
1706 } else {
1707 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_ALPHA_BLEND_ENABLE;
1708 }
1709 if ( ctx->Color.ColorLogicOpEnabled ) {
1710 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_ROP_ENABLE;
1711 } else {
1712 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_ROP_ENABLE;
1713 }
1714 break;
1715
1716 case GL_CLIP_PLANE0:
1717 case GL_CLIP_PLANE1:
1718 case GL_CLIP_PLANE2:
1719 case GL_CLIP_PLANE3:
1720 case GL_CLIP_PLANE4:
1721 case GL_CLIP_PLANE5:
1722 p = cap-GL_CLIP_PLANE0;
1723 R200_STATECHANGE( rmesa, tcl );
1724 if (state) {
1725 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (R200_UCP_ENABLE_0<<p);
1726 r200ClipPlane( ctx, cap, NULL );
1727 }
1728 else {
1729 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0<<p);
1730 }
1731 break;
1732
1733 case GL_COLOR_MATERIAL:
1734 r200ColorMaterial( ctx, 0, 0 );
1735 r200UpdateMaterial( ctx );
1736 break;
1737
1738 case GL_CULL_FACE:
1739 r200CullFace( ctx, 0 );
1740 break;
1741
1742 case GL_DEPTH_TEST:
1743 R200_STATECHANGE(rmesa, ctx );
1744 if ( state ) {
1745 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_Z_ENABLE;
1746 } else {
1747 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_Z_ENABLE;
1748 }
1749 break;
1750
1751 case GL_DITHER:
1752 R200_STATECHANGE(rmesa, ctx );
1753 if ( state ) {
1754 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_DITHER_ENABLE;
1755 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~rmesa->state.color.roundEnable;
1756 } else {
1757 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_DITHER_ENABLE;
1758 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= rmesa->state.color.roundEnable;
1759 }
1760 break;
1761
1762 case GL_FOG:
1763 R200_STATECHANGE(rmesa, ctx );
1764 if ( state ) {
1765 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_FOG_ENABLE;
1766 r200Fogfv( ctx, GL_FOG_MODE, 0 );
1767 } else {
1768 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_FOG_ENABLE;
1769 R200_STATECHANGE(rmesa, tcl);
1770 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_TCL_FOG_MASK;
1771 }
1772 r200UpdateSpecular( ctx ); /* for PK_SPEC */
1773 if (rmesa->TclFallback)
1774 r200ChooseVertexState( ctx );
1775 _mesa_allow_light_in_model( ctx, !state );
1776 break;
1777
1778 case GL_LIGHT0:
1779 case GL_LIGHT1:
1780 case GL_LIGHT2:
1781 case GL_LIGHT3:
1782 case GL_LIGHT4:
1783 case GL_LIGHT5:
1784 case GL_LIGHT6:
1785 case GL_LIGHT7:
1786 R200_STATECHANGE(rmesa, tcl);
1787 p = cap - GL_LIGHT0;
1788 if (p&1)
1789 flag = (R200_LIGHT_1_ENABLE |
1790 R200_LIGHT_1_ENABLE_AMBIENT |
1791 R200_LIGHT_1_ENABLE_SPECULAR);
1792 else
1793 flag = (R200_LIGHT_0_ENABLE |
1794 R200_LIGHT_0_ENABLE_AMBIENT |
1795 R200_LIGHT_0_ENABLE_SPECULAR);
1796
1797 if (state)
1798 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] |= flag;
1799 else
1800 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] &= ~flag;
1801
1802 /*
1803 */
1804 update_light_colors( ctx, p );
1805 break;
1806
1807 case GL_LIGHTING:
1808 r200UpdateSpecular(ctx);
1809 check_twoside_fallback( ctx );
1810 break;
1811
1812 case GL_LINE_SMOOTH:
1813 R200_STATECHANGE( rmesa, ctx );
1814 if ( state ) {
1815 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ANTI_ALIAS_LINE;
1816 } else {
1817 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_LINE;
1818 }
1819 break;
1820
1821 case GL_LINE_STIPPLE:
1822 R200_STATECHANGE( rmesa, set );
1823 if ( state ) {
1824 rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_PATTERN_ENABLE;
1825 } else {
1826 rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_PATTERN_ENABLE;
1827 }
1828 break;
1829
1830 case GL_COLOR_LOGIC_OP:
1831 R200_STATECHANGE( rmesa, ctx );
1832 if ( state ) {
1833 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_ROP_ENABLE;
1834 } else {
1835 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_ROP_ENABLE;
1836 }
1837 break;
1838
1839 case GL_NORMALIZE:
1840 R200_STATECHANGE( rmesa, tcl );
1841 if ( state ) {
1842 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_NORMALIZE_NORMALS;
1843 } else {
1844 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_NORMALIZE_NORMALS;
1845 }
1846 break;
1847
1848 /* Pointsize registers on r200 don't seem to do anything. Maybe
1849 * have to pass pointsizes as vertex parameters? In any case,
1850 * setting pointmin == pointsizemax == 1.0, and doing nothing
1851 * for aa is enough to satisfy conform.
1852 */
1853 case GL_POINT_SMOOTH:
1854 break;
1855
1856 /* These don't really do anything, as we don't use the 3vtx
1857 * primitives yet.
1858 */
1859 #if 0
1860 case GL_POLYGON_OFFSET_POINT:
1861 R200_STATECHANGE( rmesa, set );
1862 if ( state ) {
1863 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_POINT;
1864 } else {
1865 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_POINT;
1866 }
1867 break;
1868
1869 case GL_POLYGON_OFFSET_LINE:
1870 R200_STATECHANGE( rmesa, set );
1871 if ( state ) {
1872 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_LINE;
1873 } else {
1874 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_LINE;
1875 }
1876 break;
1877 #endif
1878
1879 case GL_POLYGON_OFFSET_FILL:
1880 R200_STATECHANGE( rmesa, set );
1881 if ( state ) {
1882 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_TRI;
1883 } else {
1884 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_TRI;
1885 }
1886 break;
1887
1888 case GL_POLYGON_SMOOTH:
1889 R200_STATECHANGE( rmesa, ctx );
1890 if ( state ) {
1891 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ANTI_ALIAS_POLY;
1892 } else {
1893 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_POLY;
1894 }
1895 break;
1896
1897 case GL_POLYGON_STIPPLE:
1898 R200_STATECHANGE(rmesa, set );
1899 if ( state ) {
1900 rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_STIPPLE_ENABLE;
1901 } else {
1902 rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_STIPPLE_ENABLE;
1903 }
1904 break;
1905
1906 case GL_RESCALE_NORMAL_EXT: {
1907 GLboolean tmp = ctx->_NeedEyeCoords ? state : !state;
1908 R200_STATECHANGE( rmesa, tcl );
1909 if ( tmp ) {
1910 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_RESCALE_NORMALS;
1911 } else {
1912 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS;
1913 }
1914 break;
1915 }
1916
1917 case GL_SCISSOR_TEST:
1918 R200_FIREVERTICES( rmesa );
1919 rmesa->state.scissor.enabled = state;
1920 r200UpdateScissor( ctx );
1921 break;
1922
1923 case GL_STENCIL_TEST:
1924 if ( rmesa->state.stencil.hwBuffer ) {
1925 R200_STATECHANGE( rmesa, ctx );
1926 if ( state ) {
1927 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_STENCIL_ENABLE;
1928 } else {
1929 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_STENCIL_ENABLE;
1930 }
1931 } else {
1932 FALLBACK( rmesa, R200_FALLBACK_STENCIL, state );
1933 }
1934 break;
1935
1936 case GL_TEXTURE_GEN_Q:
1937 case GL_TEXTURE_GEN_R:
1938 case GL_TEXTURE_GEN_S:
1939 case GL_TEXTURE_GEN_T:
1940 /* Picked up in r200UpdateTextureState.
1941 */
1942 rmesa->recheck_texgen[ctx->Texture.CurrentUnit] = GL_TRUE;
1943 break;
1944
1945 case GL_COLOR_SUM_EXT:
1946 r200UpdateSpecular ( ctx );
1947 break;
1948
1949 default:
1950 return;
1951 }
1952 }
1953
1954
1955 void r200LightingSpaceChange( GLcontext *ctx )
1956 {
1957 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1958 GLboolean tmp;
1959
1960 if (R200_DEBUG & DEBUG_STATE)
1961 fprintf(stderr, "%s %d BEFORE %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
1962 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]);
1963
1964 if (ctx->_NeedEyeCoords)
1965 tmp = ctx->Transform.RescaleNormals;
1966 else
1967 tmp = !ctx->Transform.RescaleNormals;
1968
1969 R200_STATECHANGE( rmesa, tcl );
1970 if ( tmp ) {
1971 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_RESCALE_NORMALS;
1972 } else {
1973 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS;
1974 }
1975
1976 if (R200_DEBUG & DEBUG_STATE)
1977 fprintf(stderr, "%s %d AFTER %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
1978 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]);
1979 }
1980
1981 /* =============================================================
1982 * Deferred state management - matrices, textures, other?
1983 */
1984
1985
1986
1987
1988 static void upload_matrix( r200ContextPtr rmesa, GLfloat *src, int idx )
1989 {
1990 float *dest = ((float *)R200_DB_STATE( mat[idx] ))+MAT_ELT_0;
1991 int i;
1992
1993
1994 for (i = 0 ; i < 4 ; i++) {
1995 *dest++ = src[i];
1996 *dest++ = src[i+4];
1997 *dest++ = src[i+8];
1998 *dest++ = src[i+12];
1999 }
2000
2001 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2002 }
2003
2004 static void upload_matrix_t( r200ContextPtr rmesa, const GLfloat *src, int idx )
2005 {
2006 float *dest = ((float *)R200_DB_STATE( mat[idx] ))+MAT_ELT_0;
2007 memcpy(dest, src, 16*sizeof(float));
2008 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2009 }
2010
2011
2012 static void update_texturematrix( GLcontext *ctx )
2013 {
2014 r200ContextPtr rmesa = R200_CONTEXT( ctx );
2015 GLuint tpc = rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0];
2016 GLuint compsel = rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL];
2017 int unit;
2018
2019 if (R200_DEBUG & DEBUG_STATE)
2020 fprintf(stderr, "%s before COMPSEL: %x\n", __FUNCTION__,
2021 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]);
2022
2023 rmesa->TexMatEnabled = 0;
2024 rmesa->TexMatCompSel = 0;
2025
2026 for (unit = 0 ; unit < 2; unit++) {
2027 if (!ctx->Texture.Unit[unit]._ReallyEnabled)
2028 continue;
2029
2030 if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY) {
2031 rmesa->TexMatEnabled |= (R200_TEXGEN_TEXMAT_0_ENABLE|
2032 R200_TEXMAT_0_ENABLE) << unit;
2033
2034 rmesa->TexMatCompSel |= R200_OUTPUT_TEX_0 << unit;
2035
2036 if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) {
2037 /* Need to preconcatenate any active texgen
2038 * obj/eyeplane matrices:
2039 */
2040 _math_matrix_mul_matrix( &rmesa->tmpmat,
2041 &rmesa->TexGenMatrix[unit],
2042 ctx->TextureMatrixStack[unit].Top );
2043 upload_matrix( rmesa, rmesa->tmpmat.m, R200_MTX_TEX0+unit );
2044 }
2045 else {
2046 upload_matrix( rmesa, ctx->TextureMatrixStack[unit].Top->m,
2047 R200_MTX_TEX0+unit );
2048 }
2049 }
2050 else if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) {
2051 upload_matrix( rmesa, rmesa->TexGenMatrix[unit].m,
2052 R200_MTX_TEX0+unit );
2053 }
2054 }
2055
2056 tpc = (rmesa->TexMatEnabled | rmesa->TexGenEnabled);
2057 if (tpc != rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0] ||
2058 rmesa->TexGenInputs != rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_1]) {
2059 R200_STATECHANGE(rmesa, tcg);
2060 rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0] = tpc;
2061 rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_1] = rmesa->TexGenInputs;
2062 }
2063
2064 compsel &= ~R200_OUTPUT_TEX_MASK;
2065 compsel |= rmesa->TexMatCompSel | rmesa->TexGenCompSel;
2066 if (compsel != rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]) {
2067 R200_STATECHANGE(rmesa, vtx);
2068 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] = compsel;
2069 }
2070 }
2071
2072
2073
2074 void r200ValidateState( GLcontext *ctx )
2075 {
2076 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2077 GLuint new_state = rmesa->NewGLState;
2078
2079 if (new_state & _NEW_TEXTURE) {
2080 r200UpdateTextureState( ctx );
2081 new_state |= rmesa->NewGLState; /* may add TEXTURE_MATRIX */
2082 }
2083
2084 /* Need an event driven matrix update?
2085 */
2086 if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION))
2087 upload_matrix( rmesa, ctx->_ModelProjectMatrix.m, R200_MTX_MVP );
2088
2089 /* Need these for lighting (shouldn't upload otherwise)
2090 */
2091 if (new_state & (_NEW_MODELVIEW)) {
2092 upload_matrix( rmesa, ctx->ModelviewMatrixStack.Top->m, R200_MTX_MV );
2093 upload_matrix_t( rmesa, ctx->ModelviewMatrixStack.Top->inv, R200_MTX_IMV );
2094 }
2095
2096 /* Does this need to be triggered on eg. modelview for
2097 * texgen-derived objplane/eyeplane matrices?
2098 */
2099 if (new_state & (_NEW_TEXTURE|_NEW_TEXTURE_MATRIX)) {
2100 update_texturematrix( ctx );
2101 }
2102
2103 if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW|_MESA_NEW_NEED_EYE_COORDS)) {
2104 update_light( ctx );
2105 }
2106
2107 /* emit all active clip planes if projection matrix changes.
2108 */
2109 if (new_state & (_NEW_PROJECTION)) {
2110 if (ctx->Transform.ClipPlanesEnabled)
2111 r200UpdateClipPlanes( ctx );
2112 }
2113
2114
2115 rmesa->NewGLState = 0;
2116 }
2117
2118
2119 static void r200InvalidateState( GLcontext *ctx, GLuint new_state )
2120 {
2121 _swrast_InvalidateState( ctx, new_state );
2122 _swsetup_InvalidateState( ctx, new_state );
2123 _ac_InvalidateState( ctx, new_state );
2124 _tnl_InvalidateState( ctx, new_state );
2125 _ae_invalidate_state( ctx, new_state );
2126 R200_CONTEXT(ctx)->NewGLState |= new_state;
2127 r200VtxfmtInvalidate( ctx );
2128 }
2129
2130 /* A hack. The r200 can actually cope just fine with materials
2131 * between begin/ends, so fix this.
2132 */
2133 static GLboolean check_material( GLcontext *ctx )
2134 {
2135 TNLcontext *tnl = TNL_CONTEXT(ctx);
2136 GLint i;
2137
2138 for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT;
2139 i < _TNL_ATTRIB_MAT_BACK_INDEXES;
2140 i++)
2141 if (tnl->vb.AttribPtr[i] &&
2142 tnl->vb.AttribPtr[i]->stride)
2143 return GL_TRUE;
2144
2145 return GL_FALSE;
2146 }
2147
2148
2149 static void r200WrapRunPipeline( GLcontext *ctx )
2150 {
2151 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2152 GLboolean has_material;
2153
2154 if (0)
2155 fprintf(stderr, "%s, newstate: %x\n", __FUNCTION__, rmesa->NewGLState);
2156
2157 /* Validate state:
2158 */
2159 if (rmesa->NewGLState)
2160 r200ValidateState( ctx );
2161
2162 has_material = (ctx->Light.Enabled && check_material( ctx ));
2163
2164 if (has_material) {
2165 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_TRUE );
2166 }
2167
2168 /* Run the pipeline.
2169 */
2170 _tnl_run_pipeline( ctx );
2171
2172 if (has_material) {
2173 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_FALSE );
2174 }
2175 }
2176
2177
2178 /* Initialize the driver's state functions.
2179 */
2180 void r200InitStateFuncs( struct dd_function_table *functions )
2181 {
2182 functions->UpdateState = r200InvalidateState;
2183 functions->LightingSpaceChange = r200LightingSpaceChange;
2184
2185 functions->DrawBuffer = r200DrawBuffer;
2186 functions->ReadBuffer = r200ReadBuffer;
2187
2188 functions->AlphaFunc = r200AlphaFunc;
2189 functions->BlendEquation = r200BlendEquation;
2190 functions->BlendFuncSeparate = r200BlendFuncSeparate;
2191 functions->ClearColor = r200ClearColor;
2192 functions->ClearDepth = NULL;
2193 functions->ClearIndex = NULL;
2194 functions->ClearStencil = r200ClearStencil;
2195 functions->ClipPlane = r200ClipPlane;
2196 functions->ColorMask = r200ColorMask;
2197 functions->CullFace = r200CullFace;
2198 functions->DepthFunc = r200DepthFunc;
2199 functions->DepthMask = r200DepthMask;
2200 functions->DepthRange = r200DepthRange;
2201 functions->Enable = r200Enable;
2202 functions->Fogfv = r200Fogfv;
2203 functions->FrontFace = r200FrontFace;
2204 functions->Hint = NULL;
2205 functions->IndexMask = NULL;
2206 functions->LightModelfv = r200LightModelfv;
2207 functions->Lightfv = r200Lightfv;
2208 functions->LineStipple = r200LineStipple;
2209 functions->LineWidth = r200LineWidth;
2210 functions->LogicOpcode = r200LogicOpCode;
2211 functions->PolygonMode = r200PolygonMode;
2212 functions->PolygonOffset = r200PolygonOffset;
2213 functions->PolygonStipple = r200PolygonStipple;
2214 functions->PointSize = r200PointSize;
2215 functions->RenderMode = r200RenderMode;
2216 functions->Scissor = r200Scissor;
2217 functions->ShadeModel = r200ShadeModel;
2218 functions->StencilFunc = r200StencilFunc;
2219 functions->StencilMask = r200StencilMask;
2220 functions->StencilOp = r200StencilOp;
2221 functions->Viewport = r200Viewport;
2222
2223 /* Swrast hooks for imaging extensions:
2224 */
2225 functions->CopyColorTable = _swrast_CopyColorTable;
2226 functions->CopyColorSubTable = _swrast_CopyColorSubTable;
2227 functions->CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
2228 functions->CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
2229 }
2230
2231
2232 void r200InitTnlFuncs( GLcontext *ctx )
2233 {
2234 TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange = r200UpdateMaterial;
2235 TNL_CONTEXT(ctx)->Driver.RunPipeline = r200WrapRunPipeline;
2236 }