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