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