Update DRI drivers to current DRI CVS and make them work.
[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[0].Emission);
797 ACC_SCALE_3V( &fcmd[GLT_RED],
798 ctx->Light.Model.Ambient,
799 ctx->Light.Material[0].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 struct gl_material *mat = &ctx->Light.Material[0];
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 & FRONT_AMBIENT_BIT) == 0)
836 SELF_SCALE_3V( &fcmd[LIT_AMBIENT_RED], mat->Ambient );
837
838 if ((bitmask & FRONT_DIFFUSE_BIT) == 0)
839 SELF_SCALE_3V( &fcmd[LIT_DIFFUSE_RED], mat->Diffuse );
840
841 if ((bitmask & FRONT_SPECULAR_BIT) == 0)
842 SELF_SCALE_3V( &fcmd[LIT_SPECULAR_RED], mat->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
854 if (ctx->Light.Enabled && ctx->Light.Model.TwoSide) {
855 if (memcmp( &ctx->Light.Material[0],
856 &ctx->Light.Material[1],
857 sizeof(struct gl_material)) != 0)
858 fallback = GL_TRUE;
859 else if (ctx->Light.ColorMaterialEnabled &&
860 (ctx->Light.ColorMaterialBitmask & BACK_MATERIAL_BITS) !=
861 ((ctx->Light.ColorMaterialBitmask & FRONT_MATERIAL_BITS)<<1))
862 fallback = GL_TRUE;
863 }
864
865 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_LIGHT_TWOSIDE, fallback );
866 }
867
868 static void r200ColorMaterial( GLcontext *ctx, GLenum face, GLenum mode )
869 {
870 if (ctx->Light.ColorMaterialEnabled) {
871 r200ContextPtr rmesa = R200_CONTEXT(ctx);
872 GLuint light_model_ctl1 = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1];
873 GLuint mask = ctx->Light.ColorMaterialBitmask;
874
875 /* Default to PREMULT:
876 */
877 light_model_ctl1 &= ~((0xf << R200_FRONT_EMISSIVE_SOURCE_SHIFT) |
878 (0xf << R200_FRONT_AMBIENT_SOURCE_SHIFT) |
879 (0xf << R200_FRONT_DIFFUSE_SOURCE_SHIFT) |
880 (0xf << R200_FRONT_SPECULAR_SOURCE_SHIFT));
881
882 if (mask & FRONT_EMISSION_BIT) {
883 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
884 R200_FRONT_EMISSIVE_SOURCE_SHIFT);
885 }
886
887 if (mask & FRONT_AMBIENT_BIT) {
888 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
889 R200_FRONT_AMBIENT_SOURCE_SHIFT);
890 }
891
892 if (mask & FRONT_DIFFUSE_BIT) {
893 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
894 R200_FRONT_DIFFUSE_SOURCE_SHIFT);
895 }
896
897 if (mask & FRONT_SPECULAR_BIT) {
898 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
899 R200_FRONT_SPECULAR_SOURCE_SHIFT);
900 }
901
902 if (light_model_ctl1 != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1]) {
903 GLuint p;
904
905 R200_STATECHANGE( rmesa, tcl );
906 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1] = light_model_ctl1;
907
908 for (p = 0 ; p < MAX_LIGHTS; p++)
909 update_light_colors( ctx, p );
910 update_global_ambient( ctx );
911 }
912 }
913
914 check_twoside_fallback( ctx );
915 }
916
917 void r200UpdateMaterial( GLcontext *ctx )
918 {
919 r200ContextPtr rmesa = R200_CONTEXT(ctx);
920 GLfloat *fcmd = (GLfloat *)R200_DB_STATE( mtl[0] );
921 GLuint p;
922 GLuint mask = ~0;
923
924 if (ctx->Light.ColorMaterialEnabled)
925 mask &= ~ctx->Light.ColorMaterialBitmask;
926
927 if (R200_DEBUG & DEBUG_STATE)
928 fprintf(stderr, "%s\n", __FUNCTION__);
929
930
931 if (mask & FRONT_EMISSION_BIT) {
932 fcmd[MTL_EMMISSIVE_RED] = ctx->Light.Material[0].Emission[0];
933 fcmd[MTL_EMMISSIVE_GREEN] = ctx->Light.Material[0].Emission[1];
934 fcmd[MTL_EMMISSIVE_BLUE] = ctx->Light.Material[0].Emission[2];
935 fcmd[MTL_EMMISSIVE_ALPHA] = ctx->Light.Material[0].Emission[3];
936 }
937 if (mask & FRONT_AMBIENT_BIT) {
938 fcmd[MTL_AMBIENT_RED] = ctx->Light.Material[0].Ambient[0];
939 fcmd[MTL_AMBIENT_GREEN] = ctx->Light.Material[0].Ambient[1];
940 fcmd[MTL_AMBIENT_BLUE] = ctx->Light.Material[0].Ambient[2];
941 fcmd[MTL_AMBIENT_ALPHA] = ctx->Light.Material[0].Ambient[3];
942 }
943 if (mask & FRONT_DIFFUSE_BIT) {
944 fcmd[MTL_DIFFUSE_RED] = ctx->Light.Material[0].Diffuse[0];
945 fcmd[MTL_DIFFUSE_GREEN] = ctx->Light.Material[0].Diffuse[1];
946 fcmd[MTL_DIFFUSE_BLUE] = ctx->Light.Material[0].Diffuse[2];
947 fcmd[MTL_DIFFUSE_ALPHA] = ctx->Light.Material[0].Diffuse[3];
948 }
949 if (mask & FRONT_SPECULAR_BIT) {
950 fcmd[MTL_SPECULAR_RED] = ctx->Light.Material[0].Specular[0];
951 fcmd[MTL_SPECULAR_GREEN] = ctx->Light.Material[0].Specular[1];
952 fcmd[MTL_SPECULAR_BLUE] = ctx->Light.Material[0].Specular[2];
953 fcmd[MTL_SPECULAR_ALPHA] = ctx->Light.Material[0].Specular[3];
954 }
955 if (mask & FRONT_SHININESS_BIT) {
956 fcmd[MTL_SHININESS] = ctx->Light.Material[0].Shininess;
957 }
958
959 if (R200_DB_STATECHANGE( rmesa, &rmesa->hw.mtl[0] )) {
960 for (p = 0 ; p < MAX_LIGHTS; p++)
961 update_light_colors( ctx, p );
962
963 check_twoside_fallback( ctx );
964 update_global_ambient( ctx );
965 }
966 else if (R200_DEBUG & (DEBUG_PRIMS|DEBUG_STATE))
967 fprintf(stderr, "%s: Elided noop material call\n", __FUNCTION__);
968 }
969
970 /* _NEW_LIGHT
971 * _NEW_MODELVIEW
972 * _MESA_NEW_NEED_EYE_COORDS
973 *
974 * Uses derived state from mesa:
975 * _VP_inf_norm
976 * _h_inf_norm
977 * _Position
978 * _NormDirection
979 * _ModelViewInvScale
980 * _NeedEyeCoords
981 * _EyeZDir
982 *
983 * which are calculated in light.c and are correct for the current
984 * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
985 * and _MESA_NEW_NEED_EYE_COORDS.
986 */
987 static void update_light( GLcontext *ctx )
988 {
989 r200ContextPtr rmesa = R200_CONTEXT(ctx);
990
991 /* Have to check these, or have an automatic shortcircuit mechanism
992 * to remove noop statechanges. (Or just do a better job on the
993 * front end).
994 */
995 {
996 GLuint tmp = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0];
997
998 if (ctx->_NeedEyeCoords)
999 tmp &= ~R200_LIGHT_IN_MODELSPACE;
1000 else
1001 tmp |= R200_LIGHT_IN_MODELSPACE;
1002
1003 if (tmp != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0])
1004 {
1005 R200_STATECHANGE( rmesa, tcl );
1006 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] = tmp;
1007 }
1008 }
1009
1010 {
1011 GLfloat *fcmd = (GLfloat *)R200_DB_STATE( eye );
1012 fcmd[EYE_X] = ctx->_EyeZDir[0];
1013 fcmd[EYE_Y] = ctx->_EyeZDir[1];
1014 fcmd[EYE_Z] = - ctx->_EyeZDir[2];
1015 fcmd[EYE_RESCALE_FACTOR] = ctx->_ModelViewInvScale;
1016 R200_DB_STATECHANGE( rmesa, &rmesa->hw.eye );
1017 }
1018
1019
1020
1021 if (ctx->Light.Enabled) {
1022 GLint p;
1023 for (p = 0 ; p < MAX_LIGHTS; p++) {
1024 if (ctx->Light.Light[p].Enabled) {
1025 struct gl_light *l = &ctx->Light.Light[p];
1026 GLfloat *fcmd = (GLfloat *)R200_DB_STATE( lit[p] );
1027
1028 if (l->EyePosition[3] == 0.0) {
1029 COPY_3FV( &fcmd[LIT_POSITION_X], l->_VP_inf_norm );
1030 COPY_3FV( &fcmd[LIT_DIRECTION_X], l->_h_inf_norm );
1031 fcmd[LIT_POSITION_W] = 0;
1032 fcmd[LIT_DIRECTION_W] = 0;
1033 } else {
1034 COPY_4V( &fcmd[LIT_POSITION_X], l->_Position );
1035 fcmd[LIT_DIRECTION_X] = -l->_NormDirection[0];
1036 fcmd[LIT_DIRECTION_Y] = -l->_NormDirection[1];
1037 fcmd[LIT_DIRECTION_Z] = -l->_NormDirection[2];
1038 fcmd[LIT_DIRECTION_W] = 0;
1039 }
1040
1041 R200_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
1042 }
1043 }
1044 }
1045 }
1046
1047 static void r200Lightfv( GLcontext *ctx, GLenum light,
1048 GLenum pname, const GLfloat *params )
1049 {
1050 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1051 GLint p = light - GL_LIGHT0;
1052 struct gl_light *l = &ctx->Light.Light[p];
1053 GLfloat *fcmd = (GLfloat *)rmesa->hw.lit[p].cmd;
1054
1055
1056 switch (pname) {
1057 case GL_AMBIENT:
1058 case GL_DIFFUSE:
1059 case GL_SPECULAR:
1060 update_light_colors( ctx, p );
1061 break;
1062
1063 case GL_SPOT_DIRECTION:
1064 /* picked up in update_light */
1065 break;
1066
1067 case GL_POSITION: {
1068 /* positions picked up in update_light, but can do flag here */
1069 GLuint flag = (p&1)? R200_LIGHT_1_IS_LOCAL : R200_LIGHT_0_IS_LOCAL;
1070 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1071
1072 R200_STATECHANGE(rmesa, tcl);
1073 if (l->EyePosition[3] != 0.0F)
1074 rmesa->hw.tcl.cmd[idx] |= flag;
1075 else
1076 rmesa->hw.tcl.cmd[idx] &= ~flag;
1077 break;
1078 }
1079
1080 case GL_SPOT_EXPONENT:
1081 R200_STATECHANGE(rmesa, lit[p]);
1082 fcmd[LIT_SPOT_EXPONENT] = params[0];
1083 break;
1084
1085 case GL_SPOT_CUTOFF: {
1086 GLuint flag = (p&1) ? R200_LIGHT_1_IS_SPOT : R200_LIGHT_0_IS_SPOT;
1087 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1088
1089 R200_STATECHANGE(rmesa, lit[p]);
1090 fcmd[LIT_SPOT_CUTOFF] = l->_CosCutoff;
1091
1092 R200_STATECHANGE(rmesa, tcl);
1093 if (l->SpotCutoff != 180.0F)
1094 rmesa->hw.tcl.cmd[idx] |= flag;
1095 else
1096 rmesa->hw.tcl.cmd[idx] &= ~flag;
1097
1098 break;
1099 }
1100
1101 case GL_CONSTANT_ATTENUATION:
1102 R200_STATECHANGE(rmesa, lit[p]);
1103 fcmd[LIT_ATTEN_CONST] = params[0];
1104 break;
1105 case GL_LINEAR_ATTENUATION:
1106 R200_STATECHANGE(rmesa, lit[p]);
1107 fcmd[LIT_ATTEN_LINEAR] = params[0];
1108 break;
1109 case GL_QUADRATIC_ATTENUATION:
1110 R200_STATECHANGE(rmesa, lit[p]);
1111 fcmd[LIT_ATTEN_QUADRATIC] = params[0];
1112 break;
1113 default:
1114 return;
1115 }
1116
1117 }
1118
1119
1120
1121
1122 static void r200LightModelfv( GLcontext *ctx, GLenum pname,
1123 const GLfloat *param )
1124 {
1125 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1126
1127 switch (pname) {
1128 case GL_LIGHT_MODEL_AMBIENT:
1129 update_global_ambient( ctx );
1130 break;
1131
1132 case GL_LIGHT_MODEL_LOCAL_VIEWER:
1133 R200_STATECHANGE( rmesa, tcl );
1134 if (ctx->Light.Model.LocalViewer)
1135 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LOCAL_VIEWER;
1136 else
1137 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_LOCAL_VIEWER;
1138 break;
1139
1140 case GL_LIGHT_MODEL_TWO_SIDE:
1141 R200_STATECHANGE( rmesa, tcl );
1142 if (ctx->Light.Model.TwoSide)
1143 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHT_TWOSIDE;
1144 else
1145 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_LIGHT_TWOSIDE;
1146
1147 check_twoside_fallback( ctx );
1148
1149 if (rmesa->TclFallback) {
1150 r200ChooseRenderState( ctx );
1151 r200ChooseVertexState( ctx );
1152 }
1153 break;
1154
1155 case GL_LIGHT_MODEL_COLOR_CONTROL:
1156 r200UpdateSpecular(ctx);
1157 break;
1158
1159 default:
1160 break;
1161 }
1162 }
1163
1164 static void r200ShadeModel( GLcontext *ctx, GLenum mode )
1165 {
1166 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1167 GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL];
1168
1169 s &= ~(R200_DIFFUSE_SHADE_MASK |
1170 R200_ALPHA_SHADE_MASK |
1171 R200_SPECULAR_SHADE_MASK |
1172 R200_FOG_SHADE_MASK);
1173
1174 switch ( mode ) {
1175 case GL_FLAT:
1176 s |= (R200_DIFFUSE_SHADE_FLAT |
1177 R200_ALPHA_SHADE_FLAT |
1178 R200_SPECULAR_SHADE_FLAT |
1179 R200_FOG_SHADE_FLAT);
1180 break;
1181 case GL_SMOOTH:
1182 s |= (R200_DIFFUSE_SHADE_GOURAUD |
1183 R200_ALPHA_SHADE_GOURAUD |
1184 R200_SPECULAR_SHADE_GOURAUD |
1185 R200_FOG_SHADE_GOURAUD);
1186 break;
1187 default:
1188 return;
1189 }
1190
1191 if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) {
1192 R200_STATECHANGE( rmesa, set );
1193 rmesa->hw.set.cmd[SET_SE_CNTL] = s;
1194 }
1195 }
1196
1197
1198 /* =============================================================
1199 * User clip planes
1200 */
1201
1202 static void r200ClipPlane( GLcontext *ctx, GLenum plane, const GLfloat *eq )
1203 {
1204 GLint p = (GLint) plane - (GLint) GL_CLIP_PLANE0;
1205 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1206 GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
1207
1208 R200_STATECHANGE( rmesa, ucp[p] );
1209 rmesa->hw.ucp[p].cmd[UCP_X] = ip[0];
1210 rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1];
1211 rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2];
1212 rmesa->hw.ucp[p].cmd[UCP_W] = ip[3];
1213 }
1214
1215 static void r200UpdateClipPlanes( GLcontext *ctx )
1216 {
1217 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1218 GLuint p;
1219
1220 for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
1221 if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
1222 GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
1223
1224 R200_STATECHANGE( rmesa, ucp[p] );
1225 rmesa->hw.ucp[p].cmd[UCP_X] = ip[0];
1226 rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1];
1227 rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2];
1228 rmesa->hw.ucp[p].cmd[UCP_W] = ip[3];
1229 }
1230 }
1231 }
1232
1233
1234 /* =============================================================
1235 * Stencil
1236 */
1237
1238 static void r200StencilFunc( GLcontext *ctx, GLenum func,
1239 GLint ref, GLuint mask )
1240 {
1241 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1242 GLuint refmask = ((ctx->Stencil.Ref[0] << R200_STENCIL_REF_SHIFT) |
1243 (ctx->Stencil.ValueMask[0] << R200_STENCIL_MASK_SHIFT));
1244
1245 R200_STATECHANGE( rmesa, ctx );
1246 R200_STATECHANGE( rmesa, msk );
1247
1248 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_STENCIL_TEST_MASK;
1249 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~(R200_STENCIL_REF_MASK|
1250 R200_STENCIL_VALUE_MASK);
1251
1252 switch ( ctx->Stencil.Function[0] ) {
1253 case GL_NEVER:
1254 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_NEVER;
1255 break;
1256 case GL_LESS:
1257 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_LESS;
1258 break;
1259 case GL_EQUAL:
1260 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_EQUAL;
1261 break;
1262 case GL_LEQUAL:
1263 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_LEQUAL;
1264 break;
1265 case GL_GREATER:
1266 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_GREATER;
1267 break;
1268 case GL_NOTEQUAL:
1269 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_NEQUAL;
1270 break;
1271 case GL_GEQUAL:
1272 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_GEQUAL;
1273 break;
1274 case GL_ALWAYS:
1275 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_ALWAYS;
1276 break;
1277 }
1278
1279 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |= refmask;
1280 }
1281
1282 static void r200StencilMask( GLcontext *ctx, GLuint mask )
1283 {
1284 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1285
1286 R200_STATECHANGE( rmesa, msk );
1287 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~R200_STENCIL_WRITE_MASK;
1288 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |=
1289 (ctx->Stencil.WriteMask[0] << R200_STENCIL_WRITEMASK_SHIFT);
1290 }
1291
1292 static void r200StencilOp( GLcontext *ctx, GLenum fail,
1293 GLenum zfail, GLenum zpass )
1294 {
1295 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1296
1297 R200_STATECHANGE( rmesa, ctx );
1298 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~(R200_STENCIL_FAIL_MASK |
1299 R200_STENCIL_ZFAIL_MASK |
1300 R200_STENCIL_ZPASS_MASK);
1301
1302 switch ( ctx->Stencil.FailFunc[0] ) {
1303 case GL_KEEP:
1304 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_KEEP;
1305 break;
1306 case GL_ZERO:
1307 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_ZERO;
1308 break;
1309 case GL_REPLACE:
1310 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_REPLACE;
1311 break;
1312 case GL_INCR:
1313 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INC;
1314 break;
1315 case GL_DECR:
1316 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_DEC;
1317 break;
1318 case GL_INCR_WRAP_EXT:
1319 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INC_WRAP;
1320 break;
1321 case GL_DECR_WRAP_EXT:
1322 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_DEC_WRAP;
1323 break;
1324 case GL_INVERT:
1325 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INVERT;
1326 break;
1327 }
1328
1329 switch ( ctx->Stencil.ZFailFunc[0] ) {
1330 case GL_KEEP:
1331 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_KEEP;
1332 break;
1333 case GL_ZERO:
1334 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_ZERO;
1335 break;
1336 case GL_REPLACE:
1337 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_REPLACE;
1338 break;
1339 case GL_INCR:
1340 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INC;
1341 break;
1342 case GL_DECR:
1343 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_DEC;
1344 break;
1345 case GL_INCR_WRAP_EXT:
1346 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INC_WRAP;
1347 break;
1348 case GL_DECR_WRAP_EXT:
1349 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_DEC_WRAP;
1350 break;
1351 case GL_INVERT:
1352 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INVERT;
1353 break;
1354 }
1355
1356 switch ( ctx->Stencil.ZPassFunc[0] ) {
1357 case GL_KEEP:
1358 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_KEEP;
1359 break;
1360 case GL_ZERO:
1361 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_ZERO;
1362 break;
1363 case GL_REPLACE:
1364 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_REPLACE;
1365 break;
1366 case GL_INCR:
1367 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INC;
1368 break;
1369 case GL_DECR:
1370 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_DEC;
1371 break;
1372 case GL_INCR_WRAP_EXT:
1373 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INC_WRAP;
1374 break;
1375 case GL_DECR_WRAP_EXT:
1376 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_DEC_WRAP;
1377 break;
1378 case GL_INVERT:
1379 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INVERT;
1380 break;
1381 }
1382 }
1383
1384 static void r200ClearStencil( GLcontext *ctx, GLint s )
1385 {
1386 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1387
1388 rmesa->state.stencil.clear =
1389 ((GLuint) ctx->Stencil.Clear |
1390 (0xff << R200_STENCIL_MASK_SHIFT) |
1391 (ctx->Stencil.WriteMask[0] << R200_STENCIL_WRITEMASK_SHIFT));
1392 }
1393
1394
1395 /* =============================================================
1396 * Window position and viewport transformation
1397 */
1398
1399 /*
1400 * To correctly position primitives:
1401 */
1402 #define SUBPIXEL_X 0.125
1403 #define SUBPIXEL_Y 0.125
1404
1405 void r200UpdateWindow( GLcontext *ctx )
1406 {
1407 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1408 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
1409 GLfloat xoffset = (GLfloat)dPriv->x;
1410 GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h;
1411 const GLfloat *v = ctx->Viewport._WindowMap.m;
1412
1413 GLfloat sx = v[MAT_SX];
1414 GLfloat tx = v[MAT_TX] + xoffset + SUBPIXEL_X;
1415 GLfloat sy = - v[MAT_SY];
1416 GLfloat ty = (- v[MAT_TY]) + yoffset + SUBPIXEL_Y;
1417 GLfloat sz = v[MAT_SZ] * rmesa->state.depth.scale;
1418 GLfloat tz = v[MAT_TZ] * rmesa->state.depth.scale;
1419
1420 R200_FIREVERTICES( rmesa );
1421 R200_STATECHANGE( rmesa, vpt );
1422
1423 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XSCALE] = *(GLuint *)&sx;
1424 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = *(GLuint *)&tx;
1425 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YSCALE] = *(GLuint *)&sy;
1426 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = *(GLuint *)&ty;
1427 rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZSCALE] = *(GLuint *)&sz;
1428 rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZOFFSET] = *(GLuint *)&tz;
1429 }
1430
1431
1432
1433 static void r200Viewport( GLcontext *ctx, GLint x, GLint y,
1434 GLsizei width, GLsizei height )
1435 {
1436 /* Don't pipeline viewport changes, conflict with window offset
1437 * setting below. Could apply deltas to rescue pipelined viewport
1438 * values, or keep the originals hanging around.
1439 */
1440 R200_FIREVERTICES( R200_CONTEXT(ctx) );
1441 r200UpdateWindow( ctx );
1442 }
1443
1444 static void r200DepthRange( GLcontext *ctx, GLclampd nearval,
1445 GLclampd farval )
1446 {
1447 r200UpdateWindow( ctx );
1448 }
1449
1450 void r200UpdateViewportOffset( GLcontext *ctx )
1451 {
1452 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1453 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
1454 GLfloat xoffset = (GLfloat)dPriv->x;
1455 GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h;
1456 const GLfloat *v = ctx->Viewport._WindowMap.m;
1457
1458 GLfloat tx = v[MAT_TX] + xoffset;
1459 GLfloat ty = (- v[MAT_TY]) + yoffset;
1460
1461 if ( rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] != *(GLuint *)&tx ||
1462 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] != *(GLuint *)&ty )
1463 {
1464 /* Note: this should also modify whatever data the context reset
1465 * code uses...
1466 */
1467 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = *(GLuint *)&tx;
1468 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = *(GLuint *)&ty;
1469
1470 /* update polygon stipple x/y screen offset */
1471 {
1472 GLuint stx, sty;
1473 GLuint m = rmesa->hw.msc.cmd[MSC_RE_MISC];
1474
1475 m &= ~(R200_STIPPLE_X_OFFSET_MASK |
1476 R200_STIPPLE_Y_OFFSET_MASK);
1477
1478 /* add magic offsets, then invert */
1479 stx = 31 - ((rmesa->dri.drawable->x - 1) & R200_STIPPLE_COORD_MASK);
1480 sty = 31 - ((rmesa->dri.drawable->y + rmesa->dri.drawable->h - 1)
1481 & R200_STIPPLE_COORD_MASK);
1482
1483 m |= ((stx << R200_STIPPLE_X_OFFSET_SHIFT) |
1484 (sty << R200_STIPPLE_Y_OFFSET_SHIFT));
1485
1486 if ( rmesa->hw.msc.cmd[MSC_RE_MISC] != m ) {
1487 R200_STATECHANGE( rmesa, msc );
1488 rmesa->hw.msc.cmd[MSC_RE_MISC] = m;
1489 }
1490 }
1491 }
1492
1493 r200UpdateScissor( ctx );
1494 }
1495
1496
1497
1498 /* =============================================================
1499 * Miscellaneous
1500 */
1501
1502 static void r200ClearColor( GLcontext *ctx, const GLfloat c[4] )
1503 {
1504 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1505 GLubyte color[4];
1506 CLAMPED_FLOAT_TO_UBYTE(color[0], c[0]);
1507 CLAMPED_FLOAT_TO_UBYTE(color[1], c[1]);
1508 CLAMPED_FLOAT_TO_UBYTE(color[2], c[2]);
1509 CLAMPED_FLOAT_TO_UBYTE(color[3], c[3]);
1510 rmesa->state.color.clear = r200PackColor( rmesa->r200Screen->cpp,
1511 color[0], color[1],
1512 color[2], color[3] );
1513 }
1514
1515
1516 static void r200RenderMode( GLcontext *ctx, GLenum mode )
1517 {
1518 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1519 FALLBACK( rmesa, R200_FALLBACK_RENDER_MODE, (mode != GL_RENDER) );
1520 }
1521
1522
1523 static GLuint r200_rop_tab[] = {
1524 R200_ROP_CLEAR,
1525 R200_ROP_AND,
1526 R200_ROP_AND_REVERSE,
1527 R200_ROP_COPY,
1528 R200_ROP_AND_INVERTED,
1529 R200_ROP_NOOP,
1530 R200_ROP_XOR,
1531 R200_ROP_OR,
1532 R200_ROP_NOR,
1533 R200_ROP_EQUIV,
1534 R200_ROP_INVERT,
1535 R200_ROP_OR_REVERSE,
1536 R200_ROP_COPY_INVERTED,
1537 R200_ROP_OR_INVERTED,
1538 R200_ROP_NAND,
1539 R200_ROP_SET,
1540 };
1541
1542 static void r200LogicOpCode( GLcontext *ctx, GLenum opcode )
1543 {
1544 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1545 GLuint rop = (GLuint)opcode - GL_CLEAR;
1546
1547 ASSERT( rop < 16 );
1548
1549 R200_STATECHANGE( rmesa, msk );
1550 rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = r200_rop_tab[rop];
1551 }
1552
1553
1554 void r200SetCliprects( r200ContextPtr rmesa, GLenum mode )
1555 {
1556 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
1557
1558 switch ( mode ) {
1559 case GL_FRONT_LEFT:
1560 rmesa->numClipRects = dPriv->numClipRects;
1561 rmesa->pClipRects = (XF86DRIClipRectPtr)dPriv->pClipRects;
1562 break;
1563 case GL_BACK_LEFT:
1564 /* Can't ignore 2d windows if we are page flipping.
1565 */
1566 if ( dPriv->numBackClipRects == 0 || rmesa->doPageFlip ) {
1567 rmesa->numClipRects = dPriv->numClipRects;
1568 rmesa->pClipRects = (XF86DRIClipRectPtr)dPriv->pClipRects;
1569 }
1570 else {
1571 rmesa->numClipRects = dPriv->numBackClipRects;
1572 rmesa->pClipRects = (XF86DRIClipRectPtr)dPriv->pBackClipRects;
1573 }
1574 break;
1575 default:
1576 fprintf(stderr, "bad mode in r200SetCliprects\n");
1577 return;
1578 }
1579
1580 if (rmesa->state.scissor.enabled)
1581 r200RecalcScissorRects( rmesa );
1582 }
1583
1584
1585 static void r200DrawBuffer( GLcontext *ctx, GLenum mode )
1586 {
1587 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1588
1589 if (R200_DEBUG & DEBUG_DRI)
1590 fprintf(stderr, "%s %s\n", __FUNCTION__,
1591 _mesa_lookup_enum_by_nr( mode ));
1592
1593 R200_FIREVERTICES(rmesa); /* don't pipeline cliprect changes */
1594
1595 /*
1596 * _DrawDestMask is easier to cope with than <mode>.
1597 */
1598 switch ( ctx->Color._DrawDestMask ) {
1599 case FRONT_LEFT_BIT:
1600 FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_FALSE );
1601 r200SetCliprects( rmesa, GL_FRONT_LEFT );
1602 break;
1603 case BACK_LEFT_BIT:
1604 FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_FALSE );
1605 r200SetCliprects( rmesa, GL_BACK_LEFT );
1606 break;
1607 default:
1608 /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */
1609 FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_TRUE );
1610 return;
1611 }
1612
1613 /* We want to update the s/w rast state too so that r200SetBuffer()
1614 * gets called.
1615 */
1616 _swrast_DrawBuffer(ctx, mode);
1617
1618 R200_STATECHANGE( rmesa, ctx );
1619 rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = (rmesa->state.color.drawOffset &
1620 R200_COLOROFFSET_MASK);
1621 rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = rmesa->state.color.drawPitch;
1622 }
1623
1624
1625 static void r200ReadBuffer( GLcontext *ctx, GLenum mode )
1626 {
1627 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
1628 }
1629
1630 /* =============================================================
1631 * State enable/disable
1632 */
1633
1634 static void r200Enable( GLcontext *ctx, GLenum cap, GLboolean state )
1635 {
1636 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1637 GLuint p, flag;
1638
1639 if ( R200_DEBUG & DEBUG_STATE )
1640 fprintf( stderr, "%s( %s = %s )\n", __FUNCTION__,
1641 _mesa_lookup_enum_by_nr( cap ),
1642 state ? "GL_TRUE" : "GL_FALSE" );
1643
1644 switch ( cap ) {
1645 /* Fast track this one...
1646 */
1647 case GL_TEXTURE_1D:
1648 case GL_TEXTURE_2D:
1649 case GL_TEXTURE_3D:
1650 break;
1651
1652 case GL_ALPHA_TEST:
1653 R200_STATECHANGE( rmesa, ctx );
1654 if (state) {
1655 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ALPHA_TEST_ENABLE;
1656 } else {
1657 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ALPHA_TEST_ENABLE;
1658 }
1659 break;
1660
1661 case GL_BLEND:
1662 R200_STATECHANGE( rmesa, ctx );
1663 if (state) {
1664 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_ALPHA_BLEND_ENABLE;
1665 } else {
1666 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_ALPHA_BLEND_ENABLE;
1667 }
1668 if ( ctx->Color.ColorLogicOpEnabled ) {
1669 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_ROP_ENABLE;
1670 } else {
1671 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_ROP_ENABLE;
1672 }
1673 break;
1674
1675 case GL_CLIP_PLANE0:
1676 case GL_CLIP_PLANE1:
1677 case GL_CLIP_PLANE2:
1678 case GL_CLIP_PLANE3:
1679 case GL_CLIP_PLANE4:
1680 case GL_CLIP_PLANE5:
1681 p = cap-GL_CLIP_PLANE0;
1682 R200_STATECHANGE( rmesa, tcl );
1683 if (state) {
1684 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (R200_UCP_ENABLE_0<<p);
1685 r200ClipPlane( ctx, cap, NULL );
1686 }
1687 else {
1688 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0<<p);
1689 }
1690 break;
1691
1692 case GL_COLOR_MATERIAL:
1693 r200ColorMaterial( ctx, 0, 0 );
1694 if (!state)
1695 r200UpdateMaterial( ctx );
1696 break;
1697
1698 case GL_CULL_FACE:
1699 r200CullFace( ctx, 0 );
1700 break;
1701
1702 case GL_DEPTH_TEST:
1703 R200_STATECHANGE(rmesa, ctx );
1704 if ( state ) {
1705 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_Z_ENABLE;
1706 } else {
1707 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_Z_ENABLE;
1708 }
1709 break;
1710
1711 case GL_DITHER:
1712 R200_STATECHANGE(rmesa, ctx );
1713 if ( state ) {
1714 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_DITHER_ENABLE;
1715 } else {
1716 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_DITHER_ENABLE;
1717 }
1718 break;
1719
1720 case GL_FOG:
1721 R200_STATECHANGE(rmesa, ctx );
1722 if ( state ) {
1723 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_FOG_ENABLE;
1724 r200Fogfv( ctx, GL_FOG_MODE, 0 );
1725 } else {
1726 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_FOG_ENABLE;
1727 R200_STATECHANGE(rmesa, tcl);
1728 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_TCL_FOG_MASK;
1729 }
1730 r200UpdateSpecular( ctx ); /* for PK_SPEC */
1731 break;
1732
1733 case GL_LIGHT0:
1734 case GL_LIGHT1:
1735 case GL_LIGHT2:
1736 case GL_LIGHT3:
1737 case GL_LIGHT4:
1738 case GL_LIGHT5:
1739 case GL_LIGHT6:
1740 case GL_LIGHT7:
1741 R200_STATECHANGE(rmesa, tcl);
1742 p = cap - GL_LIGHT0;
1743 if (p&1)
1744 flag = (R200_LIGHT_1_ENABLE |
1745 R200_LIGHT_1_ENABLE_AMBIENT |
1746 R200_LIGHT_1_ENABLE_SPECULAR);
1747 else
1748 flag = (R200_LIGHT_0_ENABLE |
1749 R200_LIGHT_0_ENABLE_AMBIENT |
1750 R200_LIGHT_0_ENABLE_SPECULAR);
1751
1752 if (state)
1753 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] |= flag;
1754 else
1755 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] &= ~flag;
1756
1757 /*
1758 */
1759 update_light_colors( ctx, p );
1760 break;
1761
1762 case GL_LIGHTING:
1763 r200UpdateSpecular(ctx);
1764 check_twoside_fallback( ctx );
1765 break;
1766
1767 case GL_LINE_SMOOTH:
1768 R200_STATECHANGE( rmesa, ctx );
1769 if ( state ) {
1770 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ANTI_ALIAS_LINE;
1771 } else {
1772 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_LINE;
1773 }
1774 break;
1775
1776 case GL_LINE_STIPPLE:
1777 R200_STATECHANGE( rmesa, set );
1778 if ( state ) {
1779 rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_PATTERN_ENABLE;
1780 } else {
1781 rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_PATTERN_ENABLE;
1782 }
1783 break;
1784
1785 case GL_COLOR_LOGIC_OP:
1786 R200_STATECHANGE( rmesa, ctx );
1787 if ( state ) {
1788 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_ROP_ENABLE;
1789 } else {
1790 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_ROP_ENABLE;
1791 }
1792 break;
1793
1794 case GL_NORMALIZE:
1795 R200_STATECHANGE( rmesa, tcl );
1796 if ( state ) {
1797 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_NORMALIZE_NORMALS;
1798 } else {
1799 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_NORMALIZE_NORMALS;
1800 }
1801 break;
1802
1803 /* Pointsize registers on r200 don't seem to do anything. Maybe
1804 * have to pass pointsizes as vertex parameters? In any case,
1805 * setting pointmin == pointsizemax == 1.0, and doing nothing
1806 * for aa is enough to satisfy conform.
1807 */
1808 case GL_POINT_SMOOTH:
1809 break;
1810
1811 /* These don't really do anything, as we don't use the 3vtx
1812 * primitives yet.
1813 */
1814 #if 0
1815 case GL_POLYGON_OFFSET_POINT:
1816 R200_STATECHANGE( rmesa, set );
1817 if ( state ) {
1818 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_POINT;
1819 } else {
1820 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_POINT;
1821 }
1822 break;
1823
1824 case GL_POLYGON_OFFSET_LINE:
1825 R200_STATECHANGE( rmesa, set );
1826 if ( state ) {
1827 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_LINE;
1828 } else {
1829 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_LINE;
1830 }
1831 break;
1832 #endif
1833
1834 case GL_POLYGON_OFFSET_FILL:
1835 R200_STATECHANGE( rmesa, set );
1836 if ( state ) {
1837 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_TRI;
1838 } else {
1839 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_TRI;
1840 }
1841 break;
1842
1843 case GL_POLYGON_SMOOTH:
1844 R200_STATECHANGE( rmesa, ctx );
1845 if ( state ) {
1846 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ANTI_ALIAS_POLY;
1847 } else {
1848 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_POLY;
1849 }
1850 break;
1851
1852 case GL_POLYGON_STIPPLE:
1853 R200_STATECHANGE(rmesa, set );
1854 if ( state ) {
1855 rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_STIPPLE_ENABLE;
1856 } else {
1857 rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_STIPPLE_ENABLE;
1858 }
1859 break;
1860
1861 case GL_RESCALE_NORMAL_EXT: {
1862 GLboolean tmp = ctx->_NeedEyeCoords ? state : !state;
1863 R200_STATECHANGE( rmesa, tcl );
1864 if ( tmp ) {
1865 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_RESCALE_NORMALS;
1866 } else {
1867 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS;
1868 }
1869 break;
1870 }
1871
1872 case GL_SCISSOR_TEST:
1873 R200_FIREVERTICES( rmesa );
1874 rmesa->state.scissor.enabled = state;
1875 r200UpdateScissor( ctx );
1876 break;
1877
1878 case GL_STENCIL_TEST:
1879 if ( rmesa->state.stencil.hwBuffer ) {
1880 R200_STATECHANGE( rmesa, ctx );
1881 if ( state ) {
1882 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_STENCIL_ENABLE;
1883 } else {
1884 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_STENCIL_ENABLE;
1885 }
1886 } else {
1887 FALLBACK( rmesa, R200_FALLBACK_STENCIL, state );
1888 }
1889 break;
1890
1891 case GL_TEXTURE_GEN_Q:
1892 case GL_TEXTURE_GEN_R:
1893 case GL_TEXTURE_GEN_S:
1894 case GL_TEXTURE_GEN_T:
1895 /* Picked up in r200UpdateTextureState.
1896 */
1897 rmesa->recheck_texgen[ctx->Texture.CurrentUnit] = GL_TRUE;
1898 break;
1899
1900 case GL_COLOR_SUM_EXT:
1901 r200UpdateSpecular ( ctx );
1902 break;
1903
1904 default:
1905 return;
1906 }
1907 }
1908
1909
1910 void r200LightingSpaceChange( GLcontext *ctx )
1911 {
1912 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1913 GLboolean tmp;
1914
1915 if (R200_DEBUG & DEBUG_STATE)
1916 fprintf(stderr, "%s %d BEFORE %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
1917 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]);
1918
1919 if (ctx->_NeedEyeCoords)
1920 tmp = ctx->Transform.RescaleNormals;
1921 else
1922 tmp = !ctx->Transform.RescaleNormals;
1923
1924 R200_STATECHANGE( rmesa, tcl );
1925 if ( tmp ) {
1926 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_RESCALE_NORMALS;
1927 } else {
1928 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS;
1929 }
1930
1931 if (R200_DEBUG & DEBUG_STATE)
1932 fprintf(stderr, "%s %d AFTER %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
1933 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]);
1934 }
1935
1936 /* =============================================================
1937 * Deferred state management - matrices, textures, other?
1938 */
1939
1940
1941
1942
1943 static void upload_matrix( r200ContextPtr rmesa, GLfloat *src, int idx )
1944 {
1945 float *dest = ((float *)R200_DB_STATE( mat[idx] ))+MAT_ELT_0;
1946 int i;
1947
1948
1949 for (i = 0 ; i < 4 ; i++) {
1950 *dest++ = src[i];
1951 *dest++ = src[i+4];
1952 *dest++ = src[i+8];
1953 *dest++ = src[i+12];
1954 }
1955
1956 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
1957 }
1958
1959 static void upload_matrix_t( r200ContextPtr rmesa, const GLfloat *src, int idx )
1960 {
1961 float *dest = ((float *)R200_DB_STATE( mat[idx] ))+MAT_ELT_0;
1962 memcpy(dest, src, 16*sizeof(float));
1963 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
1964 }
1965
1966
1967 static void update_texturematrix( GLcontext *ctx )
1968 {
1969 r200ContextPtr rmesa = R200_CONTEXT( ctx );
1970 GLuint tpc = rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0];
1971 GLuint compsel = rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL];
1972 int unit;
1973
1974 if (R200_DEBUG & DEBUG_STATE)
1975 fprintf(stderr, "%s before COMPSEL: %x\n", __FUNCTION__,
1976 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]);
1977
1978 rmesa->TexMatEnabled = 0;
1979 rmesa->TexMatCompSel = 0;
1980
1981 for (unit = 0 ; unit < 2; unit++) {
1982 if (!ctx->Texture.Unit[unit]._ReallyEnabled)
1983 continue;
1984
1985 if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY) {
1986 rmesa->TexMatEnabled |= (R200_TEXGEN_TEXMAT_0_ENABLE|
1987 R200_TEXMAT_0_ENABLE) << unit;
1988
1989 rmesa->TexMatCompSel |= R200_OUTPUT_TEX_0 << unit;
1990
1991 if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) {
1992 /* Need to preconcatenate any active texgen
1993 * obj/eyeplane matrices:
1994 */
1995 _math_matrix_mul_matrix( &rmesa->tmpmat,
1996 &rmesa->TexGenMatrix[unit],
1997 ctx->TextureMatrixStack[unit].Top );
1998 upload_matrix( rmesa, rmesa->tmpmat.m, R200_MTX_TEX0+unit );
1999 }
2000 else {
2001 upload_matrix( rmesa, ctx->TextureMatrixStack[unit].Top->m,
2002 R200_MTX_TEX0+unit );
2003 }
2004 }
2005 else if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) {
2006 upload_matrix( rmesa, rmesa->TexGenMatrix[unit].m,
2007 R200_MTX_TEX0+unit );
2008 }
2009 }
2010
2011 tpc = (rmesa->TexMatEnabled | rmesa->TexGenEnabled);
2012 if (tpc != rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0] ||
2013 rmesa->TexGenInputs != rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_1]) {
2014 R200_STATECHANGE(rmesa, tcg);
2015 rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0] = tpc;
2016 rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_1] = rmesa->TexGenInputs;
2017 }
2018
2019 compsel &= ~R200_OUTPUT_TEX_MASK;
2020 compsel |= rmesa->TexMatCompSel | rmesa->TexGenCompSel;
2021 if (compsel != rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]) {
2022 R200_STATECHANGE(rmesa, vtx);
2023 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] = compsel;
2024 }
2025 }
2026
2027
2028
2029 void r200ValidateState( GLcontext *ctx )
2030 {
2031 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2032 GLuint new_state = rmesa->NewGLState;
2033
2034 if (new_state & _NEW_TEXTURE) {
2035 r200UpdateTextureState( ctx );
2036 new_state |= rmesa->NewGLState; /* may add TEXTURE_MATRIX */
2037 }
2038
2039 /* Need an event driven matrix update?
2040 */
2041 if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION))
2042 upload_matrix( rmesa, ctx->_ModelProjectMatrix.m, R200_MTX_MVP );
2043
2044 /* Need these for lighting (shouldn't upload otherwise)
2045 */
2046 if (new_state & (_NEW_MODELVIEW)) {
2047 upload_matrix( rmesa, ctx->ModelviewMatrixStack.Top->m, R200_MTX_MV );
2048 upload_matrix_t( rmesa, ctx->ModelviewMatrixStack.Top->inv, R200_MTX_IMV );
2049 }
2050
2051 /* Does this need to be triggered on eg. modelview for
2052 * texgen-derived objplane/eyeplane matrices?
2053 */
2054 if (new_state & (_NEW_TEXTURE|_NEW_TEXTURE_MATRIX)) {
2055 update_texturematrix( ctx );
2056 }
2057
2058 if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW|_MESA_NEW_NEED_EYE_COORDS)) {
2059 update_light( ctx );
2060 }
2061
2062 /* emit all active clip planes if projection matrix changes.
2063 */
2064 if (new_state & (_NEW_PROJECTION)) {
2065 if (ctx->Transform.ClipPlanesEnabled)
2066 r200UpdateClipPlanes( ctx );
2067 }
2068
2069
2070 rmesa->NewGLState = 0;
2071 }
2072
2073
2074 static void r200InvalidateState( GLcontext *ctx, GLuint new_state )
2075 {
2076 _swrast_InvalidateState( ctx, new_state );
2077 _swsetup_InvalidateState( ctx, new_state );
2078 _ac_InvalidateState( ctx, new_state );
2079 _tnl_InvalidateState( ctx, new_state );
2080 _ae_invalidate_state( ctx, new_state );
2081 R200_CONTEXT(ctx)->NewGLState |= new_state;
2082 r200VtxfmtInvalidate( ctx );
2083 }
2084
2085 static void r200WrapRunPipeline( GLcontext *ctx )
2086 {
2087 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2088 TNLcontext *tnl = TNL_CONTEXT(ctx);
2089
2090 if (0)
2091 fprintf(stderr, "%s, newstate: %x\n", __FUNCTION__, rmesa->NewGLState);
2092
2093 /* Validate state:
2094 */
2095 if (rmesa->NewGLState)
2096 r200ValidateState( ctx );
2097
2098 if (tnl->vb.Material) {
2099 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_TRUE );
2100 }
2101
2102 /* Run the pipeline.
2103 */
2104 _tnl_run_pipeline( ctx );
2105
2106 if (tnl->vb.Material) {
2107 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_FALSE );
2108 r200UpdateMaterial( ctx ); /* not needed any more? */
2109 }
2110 }
2111
2112
2113 /* Initialize the driver's state functions.
2114 */
2115 void r200InitStateFuncs( GLcontext *ctx )
2116 {
2117 ctx->Driver.UpdateState = r200InvalidateState;
2118 ctx->Driver.LightingSpaceChange = r200LightingSpaceChange;
2119
2120 ctx->Driver.DrawBuffer = r200DrawBuffer;
2121 ctx->Driver.ReadBuffer = r200ReadBuffer;
2122
2123 ctx->Driver.AlphaFunc = r200AlphaFunc;
2124 ctx->Driver.BlendEquation = r200BlendEquation;
2125 ctx->Driver.BlendFunc = r200BlendFunc;
2126 ctx->Driver.BlendFuncSeparate = r200BlendFuncSeparate;
2127 ctx->Driver.ClearColor = r200ClearColor;
2128 ctx->Driver.ClearDepth = NULL;
2129 ctx->Driver.ClearIndex = NULL;
2130 ctx->Driver.ClearStencil = r200ClearStencil;
2131 ctx->Driver.ClipPlane = r200ClipPlane;
2132 ctx->Driver.ColorMask = r200ColorMask;
2133 ctx->Driver.CullFace = r200CullFace;
2134 ctx->Driver.DepthFunc = r200DepthFunc;
2135 ctx->Driver.DepthMask = r200DepthMask;
2136 ctx->Driver.DepthRange = r200DepthRange;
2137 ctx->Driver.Enable = r200Enable;
2138 ctx->Driver.Fogfv = r200Fogfv;
2139 ctx->Driver.FrontFace = r200FrontFace;
2140 ctx->Driver.Hint = NULL;
2141 ctx->Driver.IndexMask = NULL;
2142 ctx->Driver.LightModelfv = r200LightModelfv;
2143 ctx->Driver.Lightfv = r200Lightfv;
2144 ctx->Driver.LineStipple = r200LineStipple;
2145 ctx->Driver.LineWidth = r200LineWidth;
2146 ctx->Driver.LogicOpcode = r200LogicOpCode;
2147 ctx->Driver.PolygonMode = r200PolygonMode;
2148 ctx->Driver.PolygonOffset = r200PolygonOffset;
2149 ctx->Driver.PolygonStipple = r200PolygonStipple;
2150 ctx->Driver.PointSize = r200PointSize;
2151 ctx->Driver.RenderMode = r200RenderMode;
2152 ctx->Driver.Scissor = r200Scissor;
2153 ctx->Driver.ShadeModel = r200ShadeModel;
2154 ctx->Driver.StencilFunc = r200StencilFunc;
2155 ctx->Driver.StencilMask = r200StencilMask;
2156 ctx->Driver.StencilOp = r200StencilOp;
2157 ctx->Driver.Viewport = r200Viewport;
2158
2159 /* Swrast hooks for imaging extensions:
2160 */
2161 ctx->Driver.CopyColorTable = _swrast_CopyColorTable;
2162 ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable;
2163 ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
2164 ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
2165
2166 TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange = r200UpdateMaterial;
2167 TNL_CONTEXT(ctx)->Driver.RunPipeline = r200WrapRunPipeline;
2168 }