Don't allow lighting in model coordinates when fog is active,
[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
43 #include "swrast/swrast.h"
44 #include "array_cache/acache.h"
45 #include "tnl/tnl.h"
46 #include "tnl/t_pipeline.h"
47 #include "swrast_setup/swrast_setup.h"
48
49
50 #include "r200_context.h"
51 #include "r200_ioctl.h"
52 #include "r200_state.h"
53 #include "r200_tcl.h"
54 #include "r200_tex.h"
55 #include "r200_swtcl.h"
56 #include "r200_vtxfmt.h"
57
58
59 /* =============================================================
60 * Alpha blending
61 */
62
63 static void r200AlphaFunc( GLcontext *ctx, GLenum func, GLfloat ref )
64 {
65 r200ContextPtr rmesa = R200_CONTEXT(ctx);
66 int pp_misc = rmesa->hw.ctx.cmd[CTX_PP_MISC];
67 GLubyte refByte;
68
69 CLAMPED_FLOAT_TO_UBYTE(refByte, ref);
70
71 R200_STATECHANGE( rmesa, ctx );
72
73 pp_misc &= ~(R200_ALPHA_TEST_OP_MASK | R200_REF_ALPHA_MASK);
74 pp_misc |= (refByte & R200_REF_ALPHA_MASK);
75
76 switch ( func ) {
77 case GL_NEVER:
78 pp_misc |= R200_ALPHA_TEST_FAIL;
79 break;
80 case GL_LESS:
81 pp_misc |= R200_ALPHA_TEST_LESS;
82 break;
83 case GL_EQUAL:
84 pp_misc |= R200_ALPHA_TEST_EQUAL;
85 break;
86 case GL_LEQUAL:
87 pp_misc |= R200_ALPHA_TEST_LEQUAL;
88 break;
89 case GL_GREATER:
90 pp_misc |= R200_ALPHA_TEST_GREATER;
91 break;
92 case GL_NOTEQUAL:
93 pp_misc |= R200_ALPHA_TEST_NEQUAL;
94 break;
95 case GL_GEQUAL:
96 pp_misc |= R200_ALPHA_TEST_GEQUAL;
97 break;
98 case GL_ALWAYS:
99 pp_misc |= R200_ALPHA_TEST_PASS;
100 break;
101 }
102
103 rmesa->hw.ctx.cmd[CTX_PP_MISC] = pp_misc;
104 }
105
106 static void r200BlendEquation( GLcontext *ctx, GLenum mode )
107 {
108 r200ContextPtr rmesa = R200_CONTEXT(ctx);
109 GLuint b = rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] & ~R200_COMB_FCN_MASK;
110
111 switch ( mode ) {
112 case GL_FUNC_ADD:
113 case GL_LOGIC_OP:
114 b |= R200_COMB_FCN_ADD_CLAMP;
115 break;
116
117 case GL_FUNC_SUBTRACT:
118 b |= R200_COMB_FCN_SUB_CLAMP;
119 break;
120
121 case GL_FUNC_REVERSE_SUBTRACT:
122 b |= R200_COMB_FCN_RSUB_CLAMP;
123 break;
124
125 case GL_MIN:
126 b |= R200_COMB_FCN_MIN;
127 break;
128
129 case GL_MAX:
130 b |= R200_COMB_FCN_MAX;
131 break;
132
133 default:
134 break;
135 }
136
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;
141 } else {
142 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_ROP_ENABLE;
143 }
144 }
145
146 static void r200BlendFunc( GLcontext *ctx, GLenum sfactor, GLenum dfactor )
147 {
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);
151
152 switch ( ctx->Color.BlendSrcRGB ) {
153 case GL_ZERO:
154 b |= R200_SRC_BLEND_GL_ZERO;
155 break;
156 case GL_ONE:
157 b |= R200_SRC_BLEND_GL_ONE;
158 break;
159 case GL_DST_COLOR:
160 b |= R200_SRC_BLEND_GL_DST_COLOR;
161 break;
162 case GL_ONE_MINUS_DST_COLOR:
163 b |= R200_SRC_BLEND_GL_ONE_MINUS_DST_COLOR;
164 break;
165 case GL_SRC_COLOR:
166 b |= R200_SRC_BLEND_GL_SRC_COLOR;
167 break;
168 case GL_ONE_MINUS_SRC_COLOR:
169 b |= R200_SRC_BLEND_GL_ONE_MINUS_SRC_COLOR;
170 break;
171 case GL_SRC_ALPHA:
172 b |= R200_SRC_BLEND_GL_SRC_ALPHA;
173 break;
174 case GL_ONE_MINUS_SRC_ALPHA:
175 b |= R200_SRC_BLEND_GL_ONE_MINUS_SRC_ALPHA;
176 break;
177 case GL_DST_ALPHA:
178 b |= R200_SRC_BLEND_GL_DST_ALPHA;
179 break;
180 case GL_ONE_MINUS_DST_ALPHA:
181 b |= R200_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA;
182 break;
183 case GL_SRC_ALPHA_SATURATE:
184 b |= R200_SRC_BLEND_GL_SRC_ALPHA_SATURATE;
185 break;
186 case GL_CONSTANT_COLOR:
187 b |= R200_SRC_BLEND_GL_CONST_COLOR;
188 break;
189 case GL_ONE_MINUS_CONSTANT_COLOR:
190 b |= R200_SRC_BLEND_GL_ONE_MINUS_CONST_COLOR;
191 break;
192 case GL_CONSTANT_ALPHA:
193 b |= R200_SRC_BLEND_GL_CONST_ALPHA;
194 break;
195 case GL_ONE_MINUS_CONSTANT_ALPHA:
196 b |= R200_SRC_BLEND_GL_ONE_MINUS_CONST_ALPHA;
197 break;
198 default:
199 break;
200 }
201
202 switch ( ctx->Color.BlendDstRGB ) {
203 case GL_ZERO:
204 b |= R200_DST_BLEND_GL_ZERO;
205 break;
206 case GL_ONE:
207 b |= R200_DST_BLEND_GL_ONE;
208 break;
209 case GL_SRC_COLOR:
210 b |= R200_DST_BLEND_GL_SRC_COLOR;
211 break;
212 case GL_ONE_MINUS_SRC_COLOR:
213 b |= R200_DST_BLEND_GL_ONE_MINUS_SRC_COLOR;
214 break;
215 case GL_SRC_ALPHA:
216 b |= R200_DST_BLEND_GL_SRC_ALPHA;
217 break;
218 case GL_ONE_MINUS_SRC_ALPHA:
219 b |= R200_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA;
220 break;
221 case GL_DST_COLOR:
222 b |= R200_DST_BLEND_GL_DST_COLOR;
223 break;
224 case GL_ONE_MINUS_DST_COLOR:
225 b |= R200_DST_BLEND_GL_ONE_MINUS_DST_COLOR;
226 break;
227 case GL_DST_ALPHA:
228 b |= R200_DST_BLEND_GL_DST_ALPHA;
229 break;
230 case GL_ONE_MINUS_DST_ALPHA:
231 b |= R200_DST_BLEND_GL_ONE_MINUS_DST_ALPHA;
232 break;
233 case GL_CONSTANT_COLOR:
234 b |= R200_DST_BLEND_GL_CONST_COLOR;
235 break;
236 case GL_ONE_MINUS_CONSTANT_COLOR:
237 b |= R200_DST_BLEND_GL_ONE_MINUS_CONST_COLOR;
238 break;
239 case GL_CONSTANT_ALPHA:
240 b |= R200_DST_BLEND_GL_CONST_ALPHA;
241 break;
242 case GL_ONE_MINUS_CONSTANT_ALPHA:
243 b |= R200_DST_BLEND_GL_ONE_MINUS_CONST_ALPHA;
244 break;
245 default:
246 break;
247 }
248
249 R200_STATECHANGE( rmesa, ctx );
250 rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = b;
251 }
252
253 static void r200BlendFuncSeparate( GLcontext *ctx,
254 GLenum sfactorRGB, GLenum dfactorRGB,
255 GLenum sfactorA, GLenum dfactorA )
256 {
257 r200BlendFunc( ctx, sfactorRGB, dfactorRGB );
258 }
259
260
261 /* =============================================================
262 * Depth testing
263 */
264
265 static void r200DepthFunc( GLcontext *ctx, GLenum func )
266 {
267 r200ContextPtr rmesa = R200_CONTEXT(ctx);
268
269 R200_STATECHANGE( rmesa, ctx );
270 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_Z_TEST_MASK;
271
272 switch ( ctx->Depth.Func ) {
273 case GL_NEVER:
274 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_NEVER;
275 break;
276 case GL_LESS:
277 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_LESS;
278 break;
279 case GL_EQUAL:
280 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_EQUAL;
281 break;
282 case GL_LEQUAL:
283 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_LEQUAL;
284 break;
285 case GL_GREATER:
286 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_GREATER;
287 break;
288 case GL_NOTEQUAL:
289 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_NEQUAL;
290 break;
291 case GL_GEQUAL:
292 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_GEQUAL;
293 break;
294 case GL_ALWAYS:
295 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_ALWAYS;
296 break;
297 }
298 }
299
300
301 static void r200DepthMask( GLcontext *ctx, GLboolean flag )
302 {
303 r200ContextPtr rmesa = R200_CONTEXT(ctx);
304 R200_STATECHANGE( rmesa, ctx );
305
306 if ( ctx->Depth.Mask ) {
307 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_WRITE_ENABLE;
308 } else {
309 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_Z_WRITE_ENABLE;
310 }
311 }
312
313
314 /* =============================================================
315 * Fog
316 */
317
318
319 static void r200Fogfv( GLcontext *ctx, GLenum pname, const GLfloat *param )
320 {
321 r200ContextPtr rmesa = R200_CONTEXT(ctx);
322 union { int i; float f; } c, d;
323 GLchan col[4];
324 GLuint i;
325
326 c.i = rmesa->hw.fog.cmd[FOG_C];
327 d.i = rmesa->hw.fog.cmd[FOG_D];
328
329 switch (pname) {
330 case GL_FOG_MODE:
331 if (!ctx->Fog.Enabled)
332 return;
333 R200_STATECHANGE(rmesa, tcl);
334 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_TCL_FOG_MASK;
335 switch (ctx->Fog.Mode) {
336 case GL_LINEAR:
337 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_TCL_FOG_LINEAR;
338 if (ctx->Fog.Start == ctx->Fog.End) {
339 c.f = 1.0F;
340 d.f = 1.0F;
341 }
342 else {
343 c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start);
344 d.f = -1.0/(ctx->Fog.End-ctx->Fog.Start);
345 }
346 break;
347 case GL_EXP:
348 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_TCL_FOG_EXP;
349 c.f = 0.0;
350 d.f = -ctx->Fog.Density;
351 break;
352 case GL_EXP2:
353 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_TCL_FOG_EXP2;
354 c.f = 0.0;
355 d.f = -(ctx->Fog.Density * ctx->Fog.Density);
356 break;
357 default:
358 return;
359 }
360 break;
361 case GL_FOG_DENSITY:
362 switch (ctx->Fog.Mode) {
363 case GL_EXP:
364 c.f = 0.0;
365 d.f = -ctx->Fog.Density;
366 break;
367 case GL_EXP2:
368 c.f = 0.0;
369 d.f = -(ctx->Fog.Density * ctx->Fog.Density);
370 break;
371 default:
372 break;
373 }
374 break;
375 case GL_FOG_START:
376 case GL_FOG_END:
377 if (ctx->Fog.Mode == GL_LINEAR) {
378 if (ctx->Fog.Start == ctx->Fog.End) {
379 c.f = 1.0F;
380 d.f = 1.0F;
381 } else {
382 c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start);
383 d.f = -1.0/(ctx->Fog.End-ctx->Fog.Start);
384 }
385 }
386 break;
387 case GL_FOG_COLOR:
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;
393 break;
394 case GL_FOG_COORDINATE_SOURCE_EXT:
395 /* What to do?
396 */
397 break;
398 default:
399 return;
400 }
401
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;
406 }
407 }
408
409
410 /* =============================================================
411 * Scissoring
412 */
413
414
415 static GLboolean intersect_rect( XF86DRIClipRectPtr out,
416 XF86DRIClipRectPtr a,
417 XF86DRIClipRectPtr b )
418 {
419 *out = *a;
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;
426 return GL_TRUE;
427 }
428
429
430 void r200RecalcScissorRects( r200ContextPtr rmesa )
431 {
432 XF86DRIClipRectPtr out;
433 int i;
434
435 /* Grow cliprect store?
436 */
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;
441 }
442
443 if (rmesa->state.scissor.pClipRects)
444 FREE(rmesa->state.scissor.pClipRects);
445
446 rmesa->state.scissor.pClipRects =
447 MALLOC( rmesa->state.scissor.numAllocedClipRects *
448 sizeof(XF86DRIClipRectRec) );
449
450 if ( rmesa->state.scissor.pClipRects == NULL ) {
451 rmesa->state.scissor.numAllocedClipRects = 0;
452 return;
453 }
454 }
455
456 out = rmesa->state.scissor.pClipRects;
457 rmesa->state.scissor.numClipRects = 0;
458
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++;
464 out++;
465 }
466 }
467 }
468
469
470 static void r200UpdateScissor( GLcontext *ctx )
471 {
472 r200ContextPtr rmesa = R200_CONTEXT(ctx);
473
474 if ( rmesa->dri.drawable ) {
475 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
476
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;
481
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;
486
487 r200RecalcScissorRects( rmesa );
488 }
489 }
490
491
492 static void r200Scissor( GLcontext *ctx,
493 GLint x, GLint y, GLsizei w, GLsizei h )
494 {
495 r200ContextPtr rmesa = R200_CONTEXT(ctx);
496
497 if ( ctx->Scissor.Enabled ) {
498 R200_FIREVERTICES( rmesa ); /* don't pipeline cliprect changes */
499 r200UpdateScissor( ctx );
500 }
501
502 }
503
504
505 /* =============================================================
506 * Culling
507 */
508
509 static void r200CullFace( GLcontext *ctx, GLenum unused )
510 {
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];
514
515 s |= R200_FFACE_SOLID | R200_BFACE_SOLID;
516 t &= ~(R200_CULL_FRONT | R200_CULL_BACK);
517
518 if ( ctx->Polygon.CullFlag ) {
519 switch ( ctx->Polygon.CullFaceMode ) {
520 case GL_FRONT:
521 s &= ~R200_FFACE_SOLID;
522 t |= R200_CULL_FRONT;
523 break;
524 case GL_BACK:
525 s &= ~R200_BFACE_SOLID;
526 t |= R200_CULL_BACK;
527 break;
528 case GL_FRONT_AND_BACK:
529 s &= ~(R200_FFACE_SOLID | R200_BFACE_SOLID);
530 t |= (R200_CULL_FRONT | R200_CULL_BACK);
531 break;
532 }
533 }
534
535 if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) {
536 R200_STATECHANGE(rmesa, set );
537 rmesa->hw.set.cmd[SET_SE_CNTL] = s;
538 }
539
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;
543 }
544 }
545
546 static void r200FrontFace( GLcontext *ctx, GLenum mode )
547 {
548 r200ContextPtr rmesa = R200_CONTEXT(ctx);
549
550 R200_STATECHANGE( rmesa, set );
551 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_FFACE_CULL_DIR_MASK;
552
553 R200_STATECHANGE( rmesa, tcl );
554 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_CULL_FRONT_IS_CCW;
555
556 switch ( mode ) {
557 case GL_CW:
558 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_FFACE_CULL_CW;
559 break;
560 case GL_CCW:
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;
563 break;
564 }
565 }
566
567 /* =============================================================
568 * Point state
569 */
570 static void r200PointSize( GLcontext *ctx, GLfloat size )
571 {
572 if (0) fprintf(stderr, "%s: %f\n", __FUNCTION__, size );
573 }
574
575 /* =============================================================
576 * Line state
577 */
578 static void r200LineWidth( GLcontext *ctx, GLfloat widthf )
579 {
580 r200ContextPtr rmesa = R200_CONTEXT(ctx);
581
582 R200_STATECHANGE( rmesa, lin );
583 R200_STATECHANGE( rmesa, set );
584
585 /* Line width is stored in U6.4 format.
586 */
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);
589
590 if ( widthf > 1.0 ) {
591 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_WIDELINE_ENABLE;
592 } else {
593 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_WIDELINE_ENABLE;
594 }
595 }
596
597 static void r200LineStipple( GLcontext *ctx, GLint factor, GLushort pattern )
598 {
599 r200ContextPtr rmesa = R200_CONTEXT(ctx);
600
601 R200_STATECHANGE( rmesa, lin );
602 rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] =
603 ((((GLuint)factor & 0xff) << 16) | ((GLuint)pattern));
604 }
605
606
607 /* =============================================================
608 * Masks
609 */
610 static void r200ColorMask( GLcontext *ctx,
611 GLboolean r, GLboolean g,
612 GLboolean b, GLboolean a )
613 {
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] );
620
621 GLuint flag = rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] & ~R200_PLANE_MASK_ENABLE;
622
623 if (!(r && g && b && a))
624 flag |= R200_PLANE_MASK_ENABLE;
625
626 if ( rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] != flag ) {
627 R200_STATECHANGE( rmesa, ctx );
628 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = flag;
629 }
630
631 if ( rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] != mask ) {
632 R200_STATECHANGE( rmesa, msk );
633 rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] = mask;
634 }
635 }
636
637
638 /* =============================================================
639 * Polygon state
640 */
641
642 static void r200PolygonOffset( GLcontext *ctx,
643 GLfloat factor, GLfloat units )
644 {
645 r200ContextPtr rmesa = R200_CONTEXT(ctx);
646 GLfloat constant = units * rmesa->state.depth.scale;
647
648 /* factor *= 2; */
649 /* constant *= 2; */
650
651 /* fprintf(stderr, "%s f:%f u:%f\n", __FUNCTION__, factor, constant); */
652
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;
656 }
657
658 static void r200PolygonStipple( GLcontext *ctx, const GLubyte *mask )
659 {
660 r200ContextPtr rmesa = R200_CONTEXT(ctx);
661 GLuint i;
662 drmRadeonStipple stipple;
663
664 /* Must flip pattern upside down.
665 */
666 for ( i = 0 ; i < 32 ; i++ ) {
667 rmesa->state.stipple.mask[31 - i] = ((GLuint *) mask)[i];
668 }
669
670 /* TODO: push this into cmd mechanism
671 */
672 R200_FIREVERTICES( rmesa );
673 LOCK_HARDWARE( rmesa );
674
675 /* FIXME: Use window x,y offsets into stipple RAM.
676 */
677 stipple.mask = rmesa->state.stipple.mask;
678 drmCommandWrite( rmesa->dri.fd, DRM_RADEON_STIPPLE,
679 &stipple, sizeof(drmRadeonStipple) );
680 UNLOCK_HARDWARE( rmesa );
681 }
682
683 static void r200PolygonMode( GLcontext *ctx, GLenum face, GLenum mode )
684 {
685 r200ContextPtr rmesa = R200_CONTEXT(ctx);
686 GLboolean flag = (ctx->_TriangleCaps & DD_TRI_UNFILLED) != 0;
687
688 /* Can't generally do unfilled via tcl, but some good special
689 * cases work.
690 */
691 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_UNFILLED, flag);
692 if (rmesa->TclFallback) {
693 r200ChooseRenderState( ctx );
694 r200ChooseVertexState( ctx );
695 }
696 }
697
698
699 /* =============================================================
700 * Rendering attributes
701 *
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.
705 */
706
707 /* Examine lighting and texture state to determine if separate specular
708 * should be enabled.
709 */
710 static void r200UpdateSpecular( GLcontext *ctx )
711 {
712 r200ContextPtr rmesa = R200_CONTEXT(ctx);
713 CARD32 p = rmesa->hw.ctx.cmd[CTX_PP_CNTL];
714
715 R200_STATECHANGE( rmesa, tcl );
716 R200_STATECHANGE( rmesa, vtx );
717
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;
723
724 p &= ~R200_SPECULAR_ENABLE;
725
726 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_DIFFUSE_SPECULAR_COMBINE;
727
728
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;
740 }
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;
751 } else {
752 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
753 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT));
754 }
755
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;
760 }
761
762 if ( rmesa->hw.ctx.cmd[CTX_PP_CNTL] != p ) {
763 R200_STATECHANGE( rmesa, ctx );
764 rmesa->hw.ctx.cmd[CTX_PP_CNTL] = p;
765 }
766
767 /* Update vertex/render formats
768 */
769 if (rmesa->TclFallback) {
770 r200ChooseRenderState( ctx );
771 r200ChooseVertexState( ctx );
772 }
773 }
774
775
776 /* =============================================================
777 * Materials
778 */
779
780
781 /* Update on colormaterial, material emmissive/ambient,
782 * lightmodel.globalambient
783 */
784 static void update_global_ambient( GLcontext *ctx )
785 {
786 r200ContextPtr rmesa = R200_CONTEXT(ctx);
787 float *fcmd = (float *)R200_DB_STATE( glt );
788
789 /* Need to do more if both emmissive & ambient are PREMULT:
790 */
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)
794 {
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]);
800 }
801 else
802 {
803 COPY_3V( &fcmd[GLT_RED], ctx->Light.Model.Ambient );
804 }
805
806 R200_DB_STATECHANGE(rmesa, &rmesa->hw.glt);
807 }
808
809 /* Update on change to
810 * - light[p].colors
811 * - light[p].enabled
812 * - material,
813 * - colormaterial enabled
814 * - colormaterial bitmask
815 */
816 static void update_light_colors( GLcontext *ctx, GLuint p )
817 {
818 struct gl_light *l = &ctx->Light.Light[p];
819
820 /* fprintf(stderr, "%s\n", __FUNCTION__); */
821
822 if (l->Enabled) {
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;
827
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 );
831
832 if (!ctx->Light.ColorMaterialEnabled)
833 bitmask = 0;
834
835 if ((bitmask & MAT_BIT_FRONT_AMBIENT) == 0)
836 SELF_SCALE_3V( &fcmd[LIT_AMBIENT_RED], mat[MAT_ATTRIB_FRONT_AMBIENT] );
837
838 if ((bitmask & MAT_BIT_FRONT_DIFFUSE) == 0)
839 SELF_SCALE_3V( &fcmd[LIT_DIFFUSE_RED], mat[MAT_ATTRIB_FRONT_DIFFUSE] );
840
841 if ((bitmask & MAT_BIT_FRONT_SPECULAR) == 0)
842 SELF_SCALE_3V( &fcmd[LIT_SPECULAR_RED], mat[MAT_ATTRIB_FRONT_SPECULAR] );
843
844 R200_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
845 }
846 }
847
848 /* Also fallback for asym colormaterial mode in twoside lighting...
849 */
850 static void check_twoside_fallback( GLcontext *ctx )
851 {
852 GLboolean fallback = GL_FALSE;
853 GLint i;
854
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))
859 fallback = GL_TRUE;
860 else {
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) {
865 fallback = GL_TRUE;
866 break;
867 }
868 }
869 }
870
871 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_LIGHT_TWOSIDE, fallback );
872 }
873
874 static void r200ColorMaterial( GLcontext *ctx, GLenum face, GLenum mode )
875 {
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;
880
881 /* Default to PREMULT:
882 */
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));
887
888 if (mask & MAT_BIT_FRONT_EMISSION) {
889 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
890 R200_FRONT_EMISSIVE_SOURCE_SHIFT);
891 }
892
893 if (mask & MAT_BIT_FRONT_AMBIENT) {
894 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
895 R200_FRONT_AMBIENT_SOURCE_SHIFT);
896 }
897
898 if (mask & MAT_BIT_FRONT_DIFFUSE) {
899 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
900 R200_FRONT_DIFFUSE_SOURCE_SHIFT);
901 }
902
903 if (mask & MAT_BIT_FRONT_SPECULAR) {
904 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
905 R200_FRONT_SPECULAR_SOURCE_SHIFT);
906 }
907
908 if (light_model_ctl1 != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1]) {
909 GLuint p;
910
911 R200_STATECHANGE( rmesa, tcl );
912 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1] = light_model_ctl1;
913
914 for (p = 0 ; p < MAX_LIGHTS; p++)
915 update_light_colors( ctx, p );
916 update_global_ambient( ctx );
917 }
918 }
919
920 check_twoside_fallback( ctx );
921 }
922
923 void r200UpdateMaterial( GLcontext *ctx )
924 {
925 r200ContextPtr rmesa = R200_CONTEXT(ctx);
926 GLfloat (*mat)[4] = ctx->Light.Material.Attrib;
927 GLfloat *fcmd = (GLfloat *)R200_DB_STATE( mtl[0] );
928 GLuint p;
929 GLuint mask = ~0;
930
931 if (ctx->Light.ColorMaterialEnabled)
932 mask &= ~ctx->Light.ColorMaterialBitmask;
933
934 if (R200_DEBUG & DEBUG_STATE)
935 fprintf(stderr, "%s\n", __FUNCTION__);
936
937
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];
943 }
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];
949 }
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];
955 }
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];
961 }
962 if (mask & MAT_BIT_FRONT_SHININESS) {
963 fcmd[MTL_SHININESS] = mat[MAT_ATTRIB_FRONT_SHININESS][0];
964 }
965
966 if (R200_DB_STATECHANGE( rmesa, &rmesa->hw.mtl[0] )) {
967 for (p = 0 ; p < MAX_LIGHTS; p++)
968 update_light_colors( ctx, p );
969
970 check_twoside_fallback( ctx );
971 update_global_ambient( ctx );
972 }
973 else if (R200_DEBUG & (DEBUG_PRIMS|DEBUG_STATE))
974 fprintf(stderr, "%s: Elided noop material call\n", __FUNCTION__);
975 }
976
977 /* _NEW_LIGHT
978 * _NEW_MODELVIEW
979 * _MESA_NEW_NEED_EYE_COORDS
980 *
981 * Uses derived state from mesa:
982 * _VP_inf_norm
983 * _h_inf_norm
984 * _Position
985 * _NormDirection
986 * _ModelViewInvScale
987 * _NeedEyeCoords
988 * _EyeZDir
989 *
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.
993 */
994 static void update_light( GLcontext *ctx )
995 {
996 r200ContextPtr rmesa = R200_CONTEXT(ctx);
997
998 /* Have to check these, or have an automatic shortcircuit mechanism
999 * to remove noop statechanges. (Or just do a better job on the
1000 * front end).
1001 */
1002 {
1003 GLuint tmp = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0];
1004
1005 if (ctx->_NeedEyeCoords)
1006 tmp &= ~R200_LIGHT_IN_MODELSPACE;
1007 else
1008 tmp |= R200_LIGHT_IN_MODELSPACE;
1009
1010 if (tmp != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0])
1011 {
1012 R200_STATECHANGE( rmesa, tcl );
1013 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] = tmp;
1014 }
1015 }
1016
1017 {
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 );
1024 }
1025
1026
1027
1028 if (ctx->Light.Enabled) {
1029 GLint p;
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] );
1034
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;
1040 } else {
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;
1046 }
1047
1048 R200_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
1049 }
1050 }
1051 }
1052 }
1053
1054 static void r200Lightfv( GLcontext *ctx, GLenum light,
1055 GLenum pname, const GLfloat *params )
1056 {
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;
1061
1062
1063 switch (pname) {
1064 case GL_AMBIENT:
1065 case GL_DIFFUSE:
1066 case GL_SPECULAR:
1067 update_light_colors( ctx, p );
1068 break;
1069
1070 case GL_SPOT_DIRECTION:
1071 /* picked up in update_light */
1072 break;
1073
1074 case GL_POSITION: {
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;
1078
1079 R200_STATECHANGE(rmesa, tcl);
1080 if (l->EyePosition[3] != 0.0F)
1081 rmesa->hw.tcl.cmd[idx] |= flag;
1082 else
1083 rmesa->hw.tcl.cmd[idx] &= ~flag;
1084 break;
1085 }
1086
1087 case GL_SPOT_EXPONENT:
1088 R200_STATECHANGE(rmesa, lit[p]);
1089 fcmd[LIT_SPOT_EXPONENT] = params[0];
1090 break;
1091
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;
1095
1096 R200_STATECHANGE(rmesa, lit[p]);
1097 fcmd[LIT_SPOT_CUTOFF] = l->_CosCutoff;
1098
1099 R200_STATECHANGE(rmesa, tcl);
1100 if (l->SpotCutoff != 180.0F)
1101 rmesa->hw.tcl.cmd[idx] |= flag;
1102 else
1103 rmesa->hw.tcl.cmd[idx] &= ~flag;
1104
1105 break;
1106 }
1107
1108 case GL_CONSTANT_ATTENUATION:
1109 R200_STATECHANGE(rmesa, lit[p]);
1110 fcmd[LIT_ATTEN_CONST] = params[0];
1111 break;
1112 case GL_LINEAR_ATTENUATION:
1113 R200_STATECHANGE(rmesa, lit[p]);
1114 fcmd[LIT_ATTEN_LINEAR] = params[0];
1115 break;
1116 case GL_QUADRATIC_ATTENUATION:
1117 R200_STATECHANGE(rmesa, lit[p]);
1118 fcmd[LIT_ATTEN_QUADRATIC] = params[0];
1119 break;
1120 default:
1121 return;
1122 }
1123
1124 }
1125
1126
1127
1128
1129 static void r200LightModelfv( GLcontext *ctx, GLenum pname,
1130 const GLfloat *param )
1131 {
1132 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1133
1134 switch (pname) {
1135 case GL_LIGHT_MODEL_AMBIENT:
1136 update_global_ambient( ctx );
1137 break;
1138
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;
1143 else
1144 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_LOCAL_VIEWER;
1145 break;
1146
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;
1151 else
1152 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_LIGHT_TWOSIDE;
1153
1154 check_twoside_fallback( ctx );
1155
1156 if (rmesa->TclFallback) {
1157 r200ChooseRenderState( ctx );
1158 r200ChooseVertexState( ctx );
1159 }
1160 break;
1161
1162 case GL_LIGHT_MODEL_COLOR_CONTROL:
1163 r200UpdateSpecular(ctx);
1164 break;
1165
1166 default:
1167 break;
1168 }
1169 }
1170
1171 static void r200ShadeModel( GLcontext *ctx, GLenum mode )
1172 {
1173 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1174 GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL];
1175
1176 s &= ~(R200_DIFFUSE_SHADE_MASK |
1177 R200_ALPHA_SHADE_MASK |
1178 R200_SPECULAR_SHADE_MASK |
1179 R200_FOG_SHADE_MASK);
1180
1181 switch ( mode ) {
1182 case GL_FLAT:
1183 s |= (R200_DIFFUSE_SHADE_FLAT |
1184 R200_ALPHA_SHADE_FLAT |
1185 R200_SPECULAR_SHADE_FLAT |
1186 R200_FOG_SHADE_FLAT);
1187 break;
1188 case GL_SMOOTH:
1189 s |= (R200_DIFFUSE_SHADE_GOURAUD |
1190 R200_ALPHA_SHADE_GOURAUD |
1191 R200_SPECULAR_SHADE_GOURAUD |
1192 R200_FOG_SHADE_GOURAUD);
1193 break;
1194 default:
1195 return;
1196 }
1197
1198 if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) {
1199 R200_STATECHANGE( rmesa, set );
1200 rmesa->hw.set.cmd[SET_SE_CNTL] = s;
1201 }
1202 }
1203
1204
1205 /* =============================================================
1206 * User clip planes
1207 */
1208
1209 static void r200ClipPlane( GLcontext *ctx, GLenum plane, const GLfloat *eq )
1210 {
1211 GLint p = (GLint) plane - (GLint) GL_CLIP_PLANE0;
1212 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1213 GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
1214
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];
1220 }
1221
1222 static void r200UpdateClipPlanes( GLcontext *ctx )
1223 {
1224 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1225 GLuint p;
1226
1227 for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
1228 if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
1229 GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
1230
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];
1236 }
1237 }
1238 }
1239
1240
1241 /* =============================================================
1242 * Stencil
1243 */
1244
1245 static void r200StencilFunc( GLcontext *ctx, GLenum func,
1246 GLint ref, GLuint mask )
1247 {
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));
1251
1252 R200_STATECHANGE( rmesa, ctx );
1253 R200_STATECHANGE( rmesa, msk );
1254
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);
1258
1259 switch ( ctx->Stencil.Function[0] ) {
1260 case GL_NEVER:
1261 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_NEVER;
1262 break;
1263 case GL_LESS:
1264 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_LESS;
1265 break;
1266 case GL_EQUAL:
1267 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_EQUAL;
1268 break;
1269 case GL_LEQUAL:
1270 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_LEQUAL;
1271 break;
1272 case GL_GREATER:
1273 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_GREATER;
1274 break;
1275 case GL_NOTEQUAL:
1276 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_NEQUAL;
1277 break;
1278 case GL_GEQUAL:
1279 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_GEQUAL;
1280 break;
1281 case GL_ALWAYS:
1282 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_ALWAYS;
1283 break;
1284 }
1285
1286 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |= refmask;
1287 }
1288
1289 static void r200StencilMask( GLcontext *ctx, GLuint mask )
1290 {
1291 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1292
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);
1297 }
1298
1299 static void r200StencilOp( GLcontext *ctx, GLenum fail,
1300 GLenum zfail, GLenum zpass )
1301 {
1302 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1303
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);
1308
1309 switch ( ctx->Stencil.FailFunc[0] ) {
1310 case GL_KEEP:
1311 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_KEEP;
1312 break;
1313 case GL_ZERO:
1314 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_ZERO;
1315 break;
1316 case GL_REPLACE:
1317 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_REPLACE;
1318 break;
1319 case GL_INCR:
1320 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INC;
1321 break;
1322 case GL_DECR:
1323 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_DEC;
1324 break;
1325 case GL_INCR_WRAP_EXT:
1326 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INC_WRAP;
1327 break;
1328 case GL_DECR_WRAP_EXT:
1329 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_DEC_WRAP;
1330 break;
1331 case GL_INVERT:
1332 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INVERT;
1333 break;
1334 }
1335
1336 switch ( ctx->Stencil.ZFailFunc[0] ) {
1337 case GL_KEEP:
1338 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_KEEP;
1339 break;
1340 case GL_ZERO:
1341 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_ZERO;
1342 break;
1343 case GL_REPLACE:
1344 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_REPLACE;
1345 break;
1346 case GL_INCR:
1347 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INC;
1348 break;
1349 case GL_DECR:
1350 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_DEC;
1351 break;
1352 case GL_INCR_WRAP_EXT:
1353 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INC_WRAP;
1354 break;
1355 case GL_DECR_WRAP_EXT:
1356 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_DEC_WRAP;
1357 break;
1358 case GL_INVERT:
1359 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INVERT;
1360 break;
1361 }
1362
1363 switch ( ctx->Stencil.ZPassFunc[0] ) {
1364 case GL_KEEP:
1365 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_KEEP;
1366 break;
1367 case GL_ZERO:
1368 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_ZERO;
1369 break;
1370 case GL_REPLACE:
1371 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_REPLACE;
1372 break;
1373 case GL_INCR:
1374 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INC;
1375 break;
1376 case GL_DECR:
1377 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_DEC;
1378 break;
1379 case GL_INCR_WRAP_EXT:
1380 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INC_WRAP;
1381 break;
1382 case GL_DECR_WRAP_EXT:
1383 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_DEC_WRAP;
1384 break;
1385 case GL_INVERT:
1386 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INVERT;
1387 break;
1388 }
1389 }
1390
1391 static void r200ClearStencil( GLcontext *ctx, GLint s )
1392 {
1393 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1394
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));
1399 }
1400
1401
1402 /* =============================================================
1403 * Window position and viewport transformation
1404 */
1405
1406 /*
1407 * To correctly position primitives:
1408 */
1409 #define SUBPIXEL_X 0.125
1410 #define SUBPIXEL_Y 0.125
1411
1412 void r200UpdateWindow( GLcontext *ctx )
1413 {
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;
1419
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;
1426
1427 R200_FIREVERTICES( rmesa );
1428 R200_STATECHANGE( rmesa, vpt );
1429
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;
1436 }
1437
1438
1439
1440 static void r200Viewport( GLcontext *ctx, GLint x, GLint y,
1441 GLsizei width, GLsizei height )
1442 {
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.
1446 */
1447 R200_FIREVERTICES( R200_CONTEXT(ctx) );
1448 r200UpdateWindow( ctx );
1449 }
1450
1451 static void r200DepthRange( GLcontext *ctx, GLclampd nearval,
1452 GLclampd farval )
1453 {
1454 r200UpdateWindow( ctx );
1455 }
1456
1457 void r200UpdateViewportOffset( GLcontext *ctx )
1458 {
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;
1464
1465 GLfloat tx = v[MAT_TX] + xoffset;
1466 GLfloat ty = (- v[MAT_TY]) + yoffset;
1467
1468 if ( rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] != *(GLuint *)&tx ||
1469 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] != *(GLuint *)&ty )
1470 {
1471 /* Note: this should also modify whatever data the context reset
1472 * code uses...
1473 */
1474 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = *(GLuint *)&tx;
1475 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = *(GLuint *)&ty;
1476
1477 /* update polygon stipple x/y screen offset */
1478 {
1479 GLuint stx, sty;
1480 GLuint m = rmesa->hw.msc.cmd[MSC_RE_MISC];
1481
1482 m &= ~(R200_STIPPLE_X_OFFSET_MASK |
1483 R200_STIPPLE_Y_OFFSET_MASK);
1484
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);
1489
1490 m |= ((stx << R200_STIPPLE_X_OFFSET_SHIFT) |
1491 (sty << R200_STIPPLE_Y_OFFSET_SHIFT));
1492
1493 if ( rmesa->hw.msc.cmd[MSC_RE_MISC] != m ) {
1494 R200_STATECHANGE( rmesa, msc );
1495 rmesa->hw.msc.cmd[MSC_RE_MISC] = m;
1496 }
1497 }
1498 }
1499
1500 r200UpdateScissor( ctx );
1501 }
1502
1503
1504
1505 /* =============================================================
1506 * Miscellaneous
1507 */
1508
1509 static void r200ClearColor( GLcontext *ctx, const GLfloat c[4] )
1510 {
1511 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1512 GLubyte color[4];
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,
1518 color[0], color[1],
1519 color[2], color[3] );
1520 }
1521
1522
1523 static void r200RenderMode( GLcontext *ctx, GLenum mode )
1524 {
1525 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1526 FALLBACK( rmesa, R200_FALLBACK_RENDER_MODE, (mode != GL_RENDER) );
1527 }
1528
1529
1530 static GLuint r200_rop_tab[] = {
1531 R200_ROP_CLEAR,
1532 R200_ROP_AND,
1533 R200_ROP_AND_REVERSE,
1534 R200_ROP_COPY,
1535 R200_ROP_AND_INVERTED,
1536 R200_ROP_NOOP,
1537 R200_ROP_XOR,
1538 R200_ROP_OR,
1539 R200_ROP_NOR,
1540 R200_ROP_EQUIV,
1541 R200_ROP_INVERT,
1542 R200_ROP_OR_REVERSE,
1543 R200_ROP_COPY_INVERTED,
1544 R200_ROP_OR_INVERTED,
1545 R200_ROP_NAND,
1546 R200_ROP_SET,
1547 };
1548
1549 static void r200LogicOpCode( GLcontext *ctx, GLenum opcode )
1550 {
1551 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1552 GLuint rop = (GLuint)opcode - GL_CLEAR;
1553
1554 ASSERT( rop < 16 );
1555
1556 R200_STATECHANGE( rmesa, msk );
1557 rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = r200_rop_tab[rop];
1558 }
1559
1560
1561 void r200SetCliprects( r200ContextPtr rmesa, GLenum mode )
1562 {
1563 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
1564
1565 switch ( mode ) {
1566 case GL_FRONT_LEFT:
1567 rmesa->numClipRects = dPriv->numClipRects;
1568 rmesa->pClipRects = (XF86DRIClipRectPtr)dPriv->pClipRects;
1569 break;
1570 case GL_BACK_LEFT:
1571 /* Can't ignore 2d windows if we are page flipping.
1572 */
1573 if ( dPriv->numBackClipRects == 0 || rmesa->doPageFlip ) {
1574 rmesa->numClipRects = dPriv->numClipRects;
1575 rmesa->pClipRects = (XF86DRIClipRectPtr)dPriv->pClipRects;
1576 }
1577 else {
1578 rmesa->numClipRects = dPriv->numBackClipRects;
1579 rmesa->pClipRects = (XF86DRIClipRectPtr)dPriv->pBackClipRects;
1580 }
1581 break;
1582 default:
1583 fprintf(stderr, "bad mode in r200SetCliprects\n");
1584 return;
1585 }
1586
1587 if (rmesa->state.scissor.enabled)
1588 r200RecalcScissorRects( rmesa );
1589 }
1590
1591
1592 static void r200DrawBuffer( GLcontext *ctx, GLenum mode )
1593 {
1594 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1595
1596 if (R200_DEBUG & DEBUG_DRI)
1597 fprintf(stderr, "%s %s\n", __FUNCTION__,
1598 _mesa_lookup_enum_by_nr( mode ));
1599
1600 R200_FIREVERTICES(rmesa); /* don't pipeline cliprect changes */
1601
1602 /*
1603 * _DrawDestMask is easier to cope with than <mode>.
1604 */
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 );
1609 break;
1610 case BACK_LEFT_BIT:
1611 FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_FALSE );
1612 r200SetCliprects( rmesa, GL_BACK_LEFT );
1613 break;
1614 default:
1615 /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */
1616 FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_TRUE );
1617 return;
1618 }
1619
1620 /* We want to update the s/w rast state too so that r200SetBuffer()
1621 * gets called.
1622 */
1623 _swrast_DrawBuffer(ctx, mode);
1624
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;
1630 }
1631
1632
1633 static void r200ReadBuffer( GLcontext *ctx, GLenum mode )
1634 {
1635 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
1636 }
1637
1638 /* =============================================================
1639 * State enable/disable
1640 */
1641
1642 static void r200Enable( GLcontext *ctx, GLenum cap, GLboolean state )
1643 {
1644 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1645 GLuint p, flag;
1646
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" );
1651
1652 switch ( cap ) {
1653 /* Fast track this one...
1654 */
1655 case GL_TEXTURE_1D:
1656 case GL_TEXTURE_2D:
1657 case GL_TEXTURE_3D:
1658 break;
1659
1660 case GL_ALPHA_TEST:
1661 R200_STATECHANGE( rmesa, ctx );
1662 if (state) {
1663 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ALPHA_TEST_ENABLE;
1664 } else {
1665 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ALPHA_TEST_ENABLE;
1666 }
1667 break;
1668
1669 case GL_BLEND:
1670 R200_STATECHANGE( rmesa, ctx );
1671 if (state) {
1672 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_ALPHA_BLEND_ENABLE;
1673 } else {
1674 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_ALPHA_BLEND_ENABLE;
1675 }
1676 if ( ctx->Color.ColorLogicOpEnabled ) {
1677 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_ROP_ENABLE;
1678 } else {
1679 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_ROP_ENABLE;
1680 }
1681 break;
1682
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 );
1691 if (state) {
1692 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (R200_UCP_ENABLE_0<<p);
1693 r200ClipPlane( ctx, cap, NULL );
1694 }
1695 else {
1696 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0<<p);
1697 }
1698 break;
1699
1700 case GL_COLOR_MATERIAL:
1701 r200ColorMaterial( ctx, 0, 0 );
1702 if (!state)
1703 r200UpdateMaterial( ctx );
1704 break;
1705
1706 case GL_CULL_FACE:
1707 r200CullFace( ctx, 0 );
1708 break;
1709
1710 case GL_DEPTH_TEST:
1711 R200_STATECHANGE(rmesa, ctx );
1712 if ( state ) {
1713 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_Z_ENABLE;
1714 } else {
1715 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_Z_ENABLE;
1716 }
1717 break;
1718
1719 case GL_DITHER:
1720 R200_STATECHANGE(rmesa, ctx );
1721 if ( state ) {
1722 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_DITHER_ENABLE;
1723 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~rmesa->state.color.roundEnable;
1724 } else {
1725 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_DITHER_ENABLE;
1726 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= rmesa->state.color.roundEnable;
1727 }
1728 break;
1729
1730 case GL_FOG:
1731 R200_STATECHANGE(rmesa, ctx );
1732 if ( state ) {
1733 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_FOG_ENABLE;
1734 r200Fogfv( ctx, GL_FOG_MODE, 0 );
1735 } else {
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;
1739 }
1740 r200UpdateSpecular( ctx ); /* for PK_SPEC */
1741 if (rmesa->TclFallback)
1742 r200ChooseVertexState( ctx );
1743 _mesa_allow_light_in_model( ctx, !state );
1744 break;
1745
1746 case GL_LIGHT0:
1747 case GL_LIGHT1:
1748 case GL_LIGHT2:
1749 case GL_LIGHT3:
1750 case GL_LIGHT4:
1751 case GL_LIGHT5:
1752 case GL_LIGHT6:
1753 case GL_LIGHT7:
1754 R200_STATECHANGE(rmesa, tcl);
1755 p = cap - GL_LIGHT0;
1756 if (p&1)
1757 flag = (R200_LIGHT_1_ENABLE |
1758 R200_LIGHT_1_ENABLE_AMBIENT |
1759 R200_LIGHT_1_ENABLE_SPECULAR);
1760 else
1761 flag = (R200_LIGHT_0_ENABLE |
1762 R200_LIGHT_0_ENABLE_AMBIENT |
1763 R200_LIGHT_0_ENABLE_SPECULAR);
1764
1765 if (state)
1766 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] |= flag;
1767 else
1768 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] &= ~flag;
1769
1770 /*
1771 */
1772 update_light_colors( ctx, p );
1773 break;
1774
1775 case GL_LIGHTING:
1776 r200UpdateSpecular(ctx);
1777 check_twoside_fallback( ctx );
1778 break;
1779
1780 case GL_LINE_SMOOTH:
1781 R200_STATECHANGE( rmesa, ctx );
1782 if ( state ) {
1783 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ANTI_ALIAS_LINE;
1784 } else {
1785 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_LINE;
1786 }
1787 break;
1788
1789 case GL_LINE_STIPPLE:
1790 R200_STATECHANGE( rmesa, set );
1791 if ( state ) {
1792 rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_PATTERN_ENABLE;
1793 } else {
1794 rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_PATTERN_ENABLE;
1795 }
1796 break;
1797
1798 case GL_COLOR_LOGIC_OP:
1799 R200_STATECHANGE( rmesa, ctx );
1800 if ( state ) {
1801 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_ROP_ENABLE;
1802 } else {
1803 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_ROP_ENABLE;
1804 }
1805 break;
1806
1807 case GL_NORMALIZE:
1808 R200_STATECHANGE( rmesa, tcl );
1809 if ( state ) {
1810 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_NORMALIZE_NORMALS;
1811 } else {
1812 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_NORMALIZE_NORMALS;
1813 }
1814 break;
1815
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.
1820 */
1821 case GL_POINT_SMOOTH:
1822 break;
1823
1824 /* These don't really do anything, as we don't use the 3vtx
1825 * primitives yet.
1826 */
1827 #if 0
1828 case GL_POLYGON_OFFSET_POINT:
1829 R200_STATECHANGE( rmesa, set );
1830 if ( state ) {
1831 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_POINT;
1832 } else {
1833 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_POINT;
1834 }
1835 break;
1836
1837 case GL_POLYGON_OFFSET_LINE:
1838 R200_STATECHANGE( rmesa, set );
1839 if ( state ) {
1840 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_LINE;
1841 } else {
1842 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_LINE;
1843 }
1844 break;
1845 #endif
1846
1847 case GL_POLYGON_OFFSET_FILL:
1848 R200_STATECHANGE( rmesa, set );
1849 if ( state ) {
1850 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_TRI;
1851 } else {
1852 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_TRI;
1853 }
1854 break;
1855
1856 case GL_POLYGON_SMOOTH:
1857 R200_STATECHANGE( rmesa, ctx );
1858 if ( state ) {
1859 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ANTI_ALIAS_POLY;
1860 } else {
1861 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_POLY;
1862 }
1863 break;
1864
1865 case GL_POLYGON_STIPPLE:
1866 R200_STATECHANGE(rmesa, set );
1867 if ( state ) {
1868 rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_STIPPLE_ENABLE;
1869 } else {
1870 rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_STIPPLE_ENABLE;
1871 }
1872 break;
1873
1874 case GL_RESCALE_NORMAL_EXT: {
1875 GLboolean tmp = ctx->_NeedEyeCoords ? state : !state;
1876 R200_STATECHANGE( rmesa, tcl );
1877 if ( tmp ) {
1878 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_RESCALE_NORMALS;
1879 } else {
1880 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS;
1881 }
1882 break;
1883 }
1884
1885 case GL_SCISSOR_TEST:
1886 R200_FIREVERTICES( rmesa );
1887 rmesa->state.scissor.enabled = state;
1888 r200UpdateScissor( ctx );
1889 break;
1890
1891 case GL_STENCIL_TEST:
1892 if ( rmesa->state.stencil.hwBuffer ) {
1893 R200_STATECHANGE( rmesa, ctx );
1894 if ( state ) {
1895 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_STENCIL_ENABLE;
1896 } else {
1897 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_STENCIL_ENABLE;
1898 }
1899 } else {
1900 FALLBACK( rmesa, R200_FALLBACK_STENCIL, state );
1901 }
1902 break;
1903
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.
1909 */
1910 rmesa->recheck_texgen[ctx->Texture.CurrentUnit] = GL_TRUE;
1911 break;
1912
1913 case GL_COLOR_SUM_EXT:
1914 r200UpdateSpecular ( ctx );
1915 break;
1916
1917 default:
1918 return;
1919 }
1920 }
1921
1922
1923 void r200LightingSpaceChange( GLcontext *ctx )
1924 {
1925 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1926 GLboolean tmp;
1927
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]);
1931
1932 if (ctx->_NeedEyeCoords)
1933 tmp = ctx->Transform.RescaleNormals;
1934 else
1935 tmp = !ctx->Transform.RescaleNormals;
1936
1937 R200_STATECHANGE( rmesa, tcl );
1938 if ( tmp ) {
1939 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_RESCALE_NORMALS;
1940 } else {
1941 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS;
1942 }
1943
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]);
1947 }
1948
1949 /* =============================================================
1950 * Deferred state management - matrices, textures, other?
1951 */
1952
1953
1954
1955
1956 static void upload_matrix( r200ContextPtr rmesa, GLfloat *src, int idx )
1957 {
1958 float *dest = ((float *)R200_DB_STATE( mat[idx] ))+MAT_ELT_0;
1959 int i;
1960
1961
1962 for (i = 0 ; i < 4 ; i++) {
1963 *dest++ = src[i];
1964 *dest++ = src[i+4];
1965 *dest++ = src[i+8];
1966 *dest++ = src[i+12];
1967 }
1968
1969 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
1970 }
1971
1972 static void upload_matrix_t( r200ContextPtr rmesa, const GLfloat *src, int idx )
1973 {
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] );
1977 }
1978
1979
1980 static void update_texturematrix( GLcontext *ctx )
1981 {
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];
1985 int unit;
1986
1987 if (R200_DEBUG & DEBUG_STATE)
1988 fprintf(stderr, "%s before COMPSEL: %x\n", __FUNCTION__,
1989 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]);
1990
1991 rmesa->TexMatEnabled = 0;
1992 rmesa->TexMatCompSel = 0;
1993
1994 for (unit = 0 ; unit < 2; unit++) {
1995 if (!ctx->Texture.Unit[unit]._ReallyEnabled)
1996 continue;
1997
1998 if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY) {
1999 rmesa->TexMatEnabled |= (R200_TEXGEN_TEXMAT_0_ENABLE|
2000 R200_TEXMAT_0_ENABLE) << unit;
2001
2002 rmesa->TexMatCompSel |= R200_OUTPUT_TEX_0 << unit;
2003
2004 if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) {
2005 /* Need to preconcatenate any active texgen
2006 * obj/eyeplane matrices:
2007 */
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 );
2012 }
2013 else {
2014 upload_matrix( rmesa, ctx->TextureMatrixStack[unit].Top->m,
2015 R200_MTX_TEX0+unit );
2016 }
2017 }
2018 else if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) {
2019 upload_matrix( rmesa, rmesa->TexGenMatrix[unit].m,
2020 R200_MTX_TEX0+unit );
2021 }
2022 }
2023
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;
2030 }
2031
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;
2037 }
2038 }
2039
2040
2041
2042 void r200ValidateState( GLcontext *ctx )
2043 {
2044 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2045 GLuint new_state = rmesa->NewGLState;
2046
2047 if (new_state & _NEW_TEXTURE) {
2048 r200UpdateTextureState( ctx );
2049 new_state |= rmesa->NewGLState; /* may add TEXTURE_MATRIX */
2050 }
2051
2052 /* Need an event driven matrix update?
2053 */
2054 if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION))
2055 upload_matrix( rmesa, ctx->_ModelProjectMatrix.m, R200_MTX_MVP );
2056
2057 /* Need these for lighting (shouldn't upload otherwise)
2058 */
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 );
2062 }
2063
2064 /* Does this need to be triggered on eg. modelview for
2065 * texgen-derived objplane/eyeplane matrices?
2066 */
2067 if (new_state & (_NEW_TEXTURE|_NEW_TEXTURE_MATRIX)) {
2068 update_texturematrix( ctx );
2069 }
2070
2071 if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW|_MESA_NEW_NEED_EYE_COORDS)) {
2072 update_light( ctx );
2073 }
2074
2075 /* emit all active clip planes if projection matrix changes.
2076 */
2077 if (new_state & (_NEW_PROJECTION)) {
2078 if (ctx->Transform.ClipPlanesEnabled)
2079 r200UpdateClipPlanes( ctx );
2080 }
2081
2082
2083 rmesa->NewGLState = 0;
2084 }
2085
2086
2087 static void r200InvalidateState( GLcontext *ctx, GLuint new_state )
2088 {
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 );
2096 }
2097
2098 /* A hack. The r200 can actually cope just fine with materials
2099 * between begin/ends, so fix this.
2100 */
2101 static GLboolean check_material( GLcontext *ctx )
2102 {
2103 TNLcontext *tnl = TNL_CONTEXT(ctx);
2104 GLint i;
2105
2106 for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT;
2107 i < _TNL_ATTRIB_MAT_BACK_INDEXES;
2108 i++)
2109 if (tnl->vb.AttribPtr[i] &&
2110 tnl->vb.AttribPtr[i]->stride)
2111 return GL_TRUE;
2112
2113 return GL_FALSE;
2114 }
2115
2116
2117 static void r200WrapRunPipeline( GLcontext *ctx )
2118 {
2119 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2120 GLboolean has_material;
2121
2122 if (0)
2123 fprintf(stderr, "%s, newstate: %x\n", __FUNCTION__, rmesa->NewGLState);
2124
2125 /* Validate state:
2126 */
2127 if (rmesa->NewGLState)
2128 r200ValidateState( ctx );
2129
2130 has_material = (ctx->Light.Enabled && check_material( ctx ));
2131
2132 if (has_material) {
2133 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_TRUE );
2134 }
2135
2136 /* Run the pipeline.
2137 */
2138 _tnl_run_pipeline( ctx );
2139
2140 if (has_material) {
2141 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_FALSE );
2142 }
2143 }
2144
2145
2146 /* Initialize the driver's state functions.
2147 */
2148 void r200InitStateFuncs( GLcontext *ctx )
2149 {
2150 ctx->Driver.UpdateState = r200InvalidateState;
2151 ctx->Driver.LightingSpaceChange = r200LightingSpaceChange;
2152
2153 ctx->Driver.DrawBuffer = r200DrawBuffer;
2154 ctx->Driver.ReadBuffer = r200ReadBuffer;
2155
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;
2191
2192 /* Swrast hooks for imaging extensions:
2193 */
2194 ctx->Driver.CopyColorTable = _swrast_CopyColorTable;
2195 ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable;
2196 ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
2197 ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
2198
2199 TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange = r200UpdateMaterial;
2200 TNL_CONTEXT(ctx)->Driver.RunPipeline = r200WrapRunPipeline;
2201 }