f3d809d62cbb7e517367e914c07877e7a43b3625
[mesa.git] / src / mesa / drivers / dri / r200 / r200_state.c
1 /**************************************************************************
2
3 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
4
5 The Weather Channel (TM) funded Tungsten Graphics to develop the
6 initial release of the Radeon 8500 driver under the XFree86 license.
7 This notice must be preserved.
8
9 Permission is hereby granted, free of charge, to any person obtaining
10 a copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sublicense, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
16
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial
19 portions of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
25 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
29 **************************************************************************/
30
31 /*
32 * Authors:
33 * Keith Whitwell <keith@tungstengraphics.com>
34 */
35
36 #include "main/glheader.h"
37 #include "main/imports.h"
38 #include "main/api_arrayelt.h"
39 #include "main/enums.h"
40 #include "main/colormac.h"
41 #include "main/light.h"
42 #include "main/framebuffer.h"
43
44 #include "swrast/swrast.h"
45 #include "vbo/vbo.h"
46 #include "tnl/tnl.h"
47 #include "tnl/t_pipeline.h"
48 #include "swrast_setup/swrast_setup.h"
49
50 #include "radeon_buffer.h"
51 #include "radeon_cs.h"
52 #include "radeon_mipmap_tree.h"
53 #include "r200_context.h"
54 #include "r200_ioctl.h"
55 #include "r200_state.h"
56 #include "r200_tcl.h"
57 #include "r200_tex.h"
58 #include "r200_swtcl.h"
59 #include "r200_vertprog.h"
60
61 #include "drirenderbuffer.h"
62
63
64 /* =============================================================
65 * Alpha blending
66 */
67
68 static void r200AlphaFunc( GLcontext *ctx, GLenum func, GLfloat ref )
69 {
70 r200ContextPtr rmesa = R200_CONTEXT(ctx);
71 int pp_misc = rmesa->hw.ctx.cmd[CTX_PP_MISC];
72 GLubyte refByte;
73
74 CLAMPED_FLOAT_TO_UBYTE(refByte, ref);
75
76 R200_STATECHANGE( rmesa, ctx );
77
78 pp_misc &= ~(R200_ALPHA_TEST_OP_MASK | R200_REF_ALPHA_MASK);
79 pp_misc |= (refByte & R200_REF_ALPHA_MASK);
80
81 switch ( func ) {
82 case GL_NEVER:
83 pp_misc |= R200_ALPHA_TEST_FAIL;
84 break;
85 case GL_LESS:
86 pp_misc |= R200_ALPHA_TEST_LESS;
87 break;
88 case GL_EQUAL:
89 pp_misc |= R200_ALPHA_TEST_EQUAL;
90 break;
91 case GL_LEQUAL:
92 pp_misc |= R200_ALPHA_TEST_LEQUAL;
93 break;
94 case GL_GREATER:
95 pp_misc |= R200_ALPHA_TEST_GREATER;
96 break;
97 case GL_NOTEQUAL:
98 pp_misc |= R200_ALPHA_TEST_NEQUAL;
99 break;
100 case GL_GEQUAL:
101 pp_misc |= R200_ALPHA_TEST_GEQUAL;
102 break;
103 case GL_ALWAYS:
104 pp_misc |= R200_ALPHA_TEST_PASS;
105 break;
106 }
107
108 rmesa->hw.ctx.cmd[CTX_PP_MISC] = pp_misc;
109 }
110
111 static void r200BlendColor( GLcontext *ctx, const GLfloat cf[4] )
112 {
113 GLubyte color[4];
114 r200ContextPtr rmesa = R200_CONTEXT(ctx);
115 R200_STATECHANGE( rmesa, ctx );
116 CLAMPED_FLOAT_TO_UBYTE(color[0], cf[0]);
117 CLAMPED_FLOAT_TO_UBYTE(color[1], cf[1]);
118 CLAMPED_FLOAT_TO_UBYTE(color[2], cf[2]);
119 CLAMPED_FLOAT_TO_UBYTE(color[3], cf[3]);
120 if (rmesa->radeon.radeonScreen->drmSupportsBlendColor)
121 rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCOLOR] = radeonPackColor( 4, color[0], color[1], color[2], color[3] );
122 }
123
124 /**
125 * Calculate the hardware blend factor setting. This same function is used
126 * for source and destination of both alpha and RGB.
127 *
128 * \returns
129 * The hardware register value for the specified blend factor. This value
130 * will need to be shifted into the correct position for either source or
131 * destination factor.
132 *
133 * \todo
134 * Since the two cases where source and destination are handled differently
135 * are essentially error cases, they should never happen. Determine if these
136 * cases can be removed.
137 */
138 static int blend_factor( GLenum factor, GLboolean is_src )
139 {
140 int func;
141
142 switch ( factor ) {
143 case GL_ZERO:
144 func = R200_BLEND_GL_ZERO;
145 break;
146 case GL_ONE:
147 func = R200_BLEND_GL_ONE;
148 break;
149 case GL_DST_COLOR:
150 func = R200_BLEND_GL_DST_COLOR;
151 break;
152 case GL_ONE_MINUS_DST_COLOR:
153 func = R200_BLEND_GL_ONE_MINUS_DST_COLOR;
154 break;
155 case GL_SRC_COLOR:
156 func = R200_BLEND_GL_SRC_COLOR;
157 break;
158 case GL_ONE_MINUS_SRC_COLOR:
159 func = R200_BLEND_GL_ONE_MINUS_SRC_COLOR;
160 break;
161 case GL_SRC_ALPHA:
162 func = R200_BLEND_GL_SRC_ALPHA;
163 break;
164 case GL_ONE_MINUS_SRC_ALPHA:
165 func = R200_BLEND_GL_ONE_MINUS_SRC_ALPHA;
166 break;
167 case GL_DST_ALPHA:
168 func = R200_BLEND_GL_DST_ALPHA;
169 break;
170 case GL_ONE_MINUS_DST_ALPHA:
171 func = R200_BLEND_GL_ONE_MINUS_DST_ALPHA;
172 break;
173 case GL_SRC_ALPHA_SATURATE:
174 func = (is_src) ? R200_BLEND_GL_SRC_ALPHA_SATURATE : R200_BLEND_GL_ZERO;
175 break;
176 case GL_CONSTANT_COLOR:
177 func = R200_BLEND_GL_CONST_COLOR;
178 break;
179 case GL_ONE_MINUS_CONSTANT_COLOR:
180 func = R200_BLEND_GL_ONE_MINUS_CONST_COLOR;
181 break;
182 case GL_CONSTANT_ALPHA:
183 func = R200_BLEND_GL_CONST_ALPHA;
184 break;
185 case GL_ONE_MINUS_CONSTANT_ALPHA:
186 func = R200_BLEND_GL_ONE_MINUS_CONST_ALPHA;
187 break;
188 default:
189 func = (is_src) ? R200_BLEND_GL_ONE : R200_BLEND_GL_ZERO;
190 }
191 return func;
192 }
193
194 /**
195 * Sets both the blend equation and the blend function.
196 * This is done in a single
197 * function because some blend equations (i.e., \c GL_MIN and \c GL_MAX)
198 * change the interpretation of the blend function.
199 * Also, make sure that blend function and blend equation are set to their default
200 * value if color blending is not enabled, since at least blend equations GL_MIN
201 * and GL_FUNC_REVERSE_SUBTRACT will cause wrong results otherwise for
202 * unknown reasons.
203 */
204 static void r200_set_blend_state( GLcontext * ctx )
205 {
206 r200ContextPtr rmesa = R200_CONTEXT(ctx);
207 GLuint cntl = rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &
208 ~(R200_ROP_ENABLE | R200_ALPHA_BLEND_ENABLE | R200_SEPARATE_ALPHA_ENABLE);
209
210 int func = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
211 (R200_BLEND_GL_ZERO << R200_DST_BLEND_SHIFT);
212 int eqn = R200_COMB_FCN_ADD_CLAMP;
213 int funcA = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
214 (R200_BLEND_GL_ZERO << R200_DST_BLEND_SHIFT);
215 int eqnA = R200_COMB_FCN_ADD_CLAMP;
216
217 R200_STATECHANGE( rmesa, ctx );
218
219 if (rmesa->radeon.radeonScreen->drmSupportsBlendColor) {
220 if (ctx->Color.ColorLogicOpEnabled) {
221 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl | R200_ROP_ENABLE;
222 rmesa->hw.ctx.cmd[CTX_RB3D_ABLENDCNTL] = eqn | func;
223 rmesa->hw.ctx.cmd[CTX_RB3D_CBLENDCNTL] = eqn | func;
224 return;
225 } else if (ctx->Color.BlendEnabled) {
226 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl | R200_ALPHA_BLEND_ENABLE | R200_SEPARATE_ALPHA_ENABLE;
227 }
228 else {
229 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl;
230 rmesa->hw.ctx.cmd[CTX_RB3D_ABLENDCNTL] = eqn | func;
231 rmesa->hw.ctx.cmd[CTX_RB3D_CBLENDCNTL] = eqn | func;
232 return;
233 }
234 }
235 else {
236 if (ctx->Color.ColorLogicOpEnabled) {
237 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl | R200_ROP_ENABLE;
238 rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = eqn | func;
239 return;
240 } else if (ctx->Color.BlendEnabled) {
241 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl | R200_ALPHA_BLEND_ENABLE;
242 }
243 else {
244 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl;
245 rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = eqn | func;
246 return;
247 }
248 }
249
250 func = (blend_factor( ctx->Color.BlendSrcRGB, GL_TRUE ) << R200_SRC_BLEND_SHIFT) |
251 (blend_factor( ctx->Color.BlendDstRGB, GL_FALSE ) << R200_DST_BLEND_SHIFT);
252
253 switch(ctx->Color.BlendEquationRGB) {
254 case GL_FUNC_ADD:
255 eqn = R200_COMB_FCN_ADD_CLAMP;
256 break;
257
258 case GL_FUNC_SUBTRACT:
259 eqn = R200_COMB_FCN_SUB_CLAMP;
260 break;
261
262 case GL_FUNC_REVERSE_SUBTRACT:
263 eqn = R200_COMB_FCN_RSUB_CLAMP;
264 break;
265
266 case GL_MIN:
267 eqn = R200_COMB_FCN_MIN;
268 func = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
269 (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT);
270 break;
271
272 case GL_MAX:
273 eqn = R200_COMB_FCN_MAX;
274 func = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
275 (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT);
276 break;
277
278 default:
279 fprintf( stderr, "[%s:%u] Invalid RGB blend equation (0x%04x).\n",
280 __FUNCTION__, __LINE__, ctx->Color.BlendEquationRGB );
281 return;
282 }
283
284 if (!rmesa->radeon.radeonScreen->drmSupportsBlendColor) {
285 rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = eqn | func;
286 return;
287 }
288
289 funcA = (blend_factor( ctx->Color.BlendSrcA, GL_TRUE ) << R200_SRC_BLEND_SHIFT) |
290 (blend_factor( ctx->Color.BlendDstA, GL_FALSE ) << R200_DST_BLEND_SHIFT);
291
292 switch(ctx->Color.BlendEquationA) {
293 case GL_FUNC_ADD:
294 eqnA = R200_COMB_FCN_ADD_CLAMP;
295 break;
296
297 case GL_FUNC_SUBTRACT:
298 eqnA = R200_COMB_FCN_SUB_CLAMP;
299 break;
300
301 case GL_FUNC_REVERSE_SUBTRACT:
302 eqnA = R200_COMB_FCN_RSUB_CLAMP;
303 break;
304
305 case GL_MIN:
306 eqnA = R200_COMB_FCN_MIN;
307 funcA = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
308 (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT);
309 break;
310
311 case GL_MAX:
312 eqnA = R200_COMB_FCN_MAX;
313 funcA = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
314 (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT);
315 break;
316
317 default:
318 fprintf( stderr, "[%s:%u] Invalid A blend equation (0x%04x).\n",
319 __FUNCTION__, __LINE__, ctx->Color.BlendEquationA );
320 return;
321 }
322
323 rmesa->hw.ctx.cmd[CTX_RB3D_ABLENDCNTL] = eqnA | funcA;
324 rmesa->hw.ctx.cmd[CTX_RB3D_CBLENDCNTL] = eqn | func;
325
326 }
327
328 static void r200BlendEquationSeparate( GLcontext *ctx,
329 GLenum modeRGB, GLenum modeA )
330 {
331 r200_set_blend_state( ctx );
332 }
333
334 static void r200BlendFuncSeparate( GLcontext *ctx,
335 GLenum sfactorRGB, GLenum dfactorRGB,
336 GLenum sfactorA, GLenum dfactorA )
337 {
338 r200_set_blend_state( ctx );
339 }
340
341
342 /* =============================================================
343 * Depth testing
344 */
345
346 static void r200DepthFunc( GLcontext *ctx, GLenum func )
347 {
348 r200ContextPtr rmesa = R200_CONTEXT(ctx);
349
350 R200_STATECHANGE( rmesa, ctx );
351 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_Z_TEST_MASK;
352
353 switch ( ctx->Depth.Func ) {
354 case GL_NEVER:
355 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_NEVER;
356 break;
357 case GL_LESS:
358 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_LESS;
359 break;
360 case GL_EQUAL:
361 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_EQUAL;
362 break;
363 case GL_LEQUAL:
364 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_LEQUAL;
365 break;
366 case GL_GREATER:
367 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_GREATER;
368 break;
369 case GL_NOTEQUAL:
370 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_NEQUAL;
371 break;
372 case GL_GEQUAL:
373 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_GEQUAL;
374 break;
375 case GL_ALWAYS:
376 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_ALWAYS;
377 break;
378 }
379 }
380
381 static void r200ClearDepth( GLcontext *ctx, GLclampd d )
382 {
383 r200ContextPtr rmesa = R200_CONTEXT(ctx);
384 GLuint format = (rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &
385 R200_DEPTH_FORMAT_MASK);
386
387 switch ( format ) {
388 case R200_DEPTH_FORMAT_16BIT_INT_Z:
389 rmesa->radeon.state.depth.clear = d * 0x0000ffff;
390 break;
391 case R200_DEPTH_FORMAT_24BIT_INT_Z:
392 rmesa->radeon.state.depth.clear = d * 0x00ffffff;
393 break;
394 }
395 }
396
397 static void r200DepthMask( GLcontext *ctx, GLboolean flag )
398 {
399 r200ContextPtr rmesa = R200_CONTEXT(ctx);
400 R200_STATECHANGE( rmesa, ctx );
401
402 if ( ctx->Depth.Mask ) {
403 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_WRITE_ENABLE;
404 } else {
405 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_Z_WRITE_ENABLE;
406 }
407 }
408
409
410 /* =============================================================
411 * Fog
412 */
413
414
415 static void r200Fogfv( GLcontext *ctx, GLenum pname, const GLfloat *param )
416 {
417 r200ContextPtr rmesa = R200_CONTEXT(ctx);
418 union { int i; float f; } c, d;
419 GLchan col[4];
420 GLuint i;
421
422 c.i = rmesa->hw.fog.cmd[FOG_C];
423 d.i = rmesa->hw.fog.cmd[FOG_D];
424
425 switch (pname) {
426 case GL_FOG_MODE:
427 if (!ctx->Fog.Enabled)
428 return;
429 R200_STATECHANGE(rmesa, tcl);
430 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_TCL_FOG_MASK;
431 switch (ctx->Fog.Mode) {
432 case GL_LINEAR:
433 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_TCL_FOG_LINEAR;
434 if (ctx->Fog.Start == ctx->Fog.End) {
435 c.f = 1.0F;
436 d.f = 1.0F;
437 }
438 else {
439 c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start);
440 d.f = -1.0/(ctx->Fog.End-ctx->Fog.Start);
441 }
442 break;
443 case GL_EXP:
444 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_TCL_FOG_EXP;
445 c.f = 0.0;
446 d.f = -ctx->Fog.Density;
447 break;
448 case GL_EXP2:
449 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_TCL_FOG_EXP2;
450 c.f = 0.0;
451 d.f = -(ctx->Fog.Density * ctx->Fog.Density);
452 break;
453 default:
454 return;
455 }
456 break;
457 case GL_FOG_DENSITY:
458 switch (ctx->Fog.Mode) {
459 case GL_EXP:
460 c.f = 0.0;
461 d.f = -ctx->Fog.Density;
462 break;
463 case GL_EXP2:
464 c.f = 0.0;
465 d.f = -(ctx->Fog.Density * ctx->Fog.Density);
466 break;
467 default:
468 break;
469 }
470 break;
471 case GL_FOG_START:
472 case GL_FOG_END:
473 if (ctx->Fog.Mode == GL_LINEAR) {
474 if (ctx->Fog.Start == ctx->Fog.End) {
475 c.f = 1.0F;
476 d.f = 1.0F;
477 } else {
478 c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start);
479 d.f = -1.0/(ctx->Fog.End-ctx->Fog.Start);
480 }
481 }
482 break;
483 case GL_FOG_COLOR:
484 R200_STATECHANGE( rmesa, ctx );
485 UNCLAMPED_FLOAT_TO_RGB_CHAN( col, ctx->Fog.Color );
486 i = radeonPackColor( 4, col[0], col[1], col[2], 0 );
487 rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] &= ~R200_FOG_COLOR_MASK;
488 rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] |= i;
489 break;
490 case GL_FOG_COORD_SRC: {
491 GLuint out_0 = rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0];
492 GLuint fog = rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR];
493
494 fog &= ~R200_FOG_USE_MASK;
495 if ( ctx->Fog.FogCoordinateSource == GL_FOG_COORD || ctx->VertexProgram.Enabled) {
496 fog |= R200_FOG_USE_VTX_FOG;
497 out_0 |= R200_VTX_DISCRETE_FOG;
498 }
499 else {
500 fog |= R200_FOG_USE_SPEC_ALPHA;
501 out_0 &= ~R200_VTX_DISCRETE_FOG;
502 }
503
504 if ( fog != rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] ) {
505 R200_STATECHANGE( rmesa, ctx );
506 rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] = fog;
507 }
508
509 if (out_0 != rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0]) {
510 R200_STATECHANGE( rmesa, vtx );
511 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] = out_0;
512 }
513
514 break;
515 }
516 default:
517 return;
518 }
519
520 if (c.i != rmesa->hw.fog.cmd[FOG_C] || d.i != rmesa->hw.fog.cmd[FOG_D]) {
521 R200_STATECHANGE( rmesa, fog );
522 rmesa->hw.fog.cmd[FOG_C] = c.i;
523 rmesa->hw.fog.cmd[FOG_D] = d.i;
524 }
525 }
526
527
528 /* =============================================================
529 * Scissoring
530 */
531
532
533 static void r200Scissor( GLcontext *ctx,
534 GLint x, GLint y, GLsizei w, GLsizei h )
535 {
536 r200ContextPtr rmesa = R200_CONTEXT(ctx);
537
538 if ( ctx->Scissor.Enabled ) {
539 R200_FIREVERTICES( rmesa ); /* don't pipeline cliprect changes */
540 radeonUpdateScissor( ctx );
541 }
542
543 }
544
545
546 /* =============================================================
547 * Culling
548 */
549
550 static void r200CullFace( GLcontext *ctx, GLenum unused )
551 {
552 r200ContextPtr rmesa = R200_CONTEXT(ctx);
553 GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL];
554 GLuint t = rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL];
555
556 s |= R200_FFACE_SOLID | R200_BFACE_SOLID;
557 t &= ~(R200_CULL_FRONT | R200_CULL_BACK);
558
559 if ( ctx->Polygon.CullFlag ) {
560 switch ( ctx->Polygon.CullFaceMode ) {
561 case GL_FRONT:
562 s &= ~R200_FFACE_SOLID;
563 t |= R200_CULL_FRONT;
564 break;
565 case GL_BACK:
566 s &= ~R200_BFACE_SOLID;
567 t |= R200_CULL_BACK;
568 break;
569 case GL_FRONT_AND_BACK:
570 s &= ~(R200_FFACE_SOLID | R200_BFACE_SOLID);
571 t |= (R200_CULL_FRONT | R200_CULL_BACK);
572 break;
573 }
574 }
575
576 if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) {
577 R200_STATECHANGE(rmesa, set );
578 rmesa->hw.set.cmd[SET_SE_CNTL] = s;
579 }
580
581 if ( rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] != t ) {
582 R200_STATECHANGE(rmesa, tcl );
583 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] = t;
584 }
585 }
586
587 static void r200FrontFace( GLcontext *ctx, GLenum mode )
588 {
589 r200ContextPtr rmesa = R200_CONTEXT(ctx);
590
591 R200_STATECHANGE( rmesa, set );
592 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_FFACE_CULL_DIR_MASK;
593
594 R200_STATECHANGE( rmesa, tcl );
595 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_CULL_FRONT_IS_CCW;
596
597 switch ( mode ) {
598 case GL_CW:
599 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_FFACE_CULL_CW;
600 break;
601 case GL_CCW:
602 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_FFACE_CULL_CCW;
603 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_CULL_FRONT_IS_CCW;
604 break;
605 }
606 }
607
608 /* =============================================================
609 * Point state
610 */
611 static void r200PointSize( GLcontext *ctx, GLfloat size )
612 {
613 r200ContextPtr rmesa = R200_CONTEXT(ctx);
614 GLfloat *fcmd = (GLfloat *)rmesa->hw.ptp.cmd;
615
616 R200_STATECHANGE( rmesa, cst );
617 R200_STATECHANGE( rmesa, ptp );
618 rmesa->hw.cst.cmd[CST_RE_POINTSIZE] &= ~0xffff;
619 rmesa->hw.cst.cmd[CST_RE_POINTSIZE] |= ((GLuint)(ctx->Point.Size * 16.0));
620 /* this is the size param of the point size calculation (point size reg value
621 is not used when calculation is active). */
622 fcmd[PTP_VPORT_SCALE_PTSIZE] = ctx->Point.Size;
623 }
624
625 static void r200PointParameter( GLcontext *ctx, GLenum pname, const GLfloat *params)
626 {
627 r200ContextPtr rmesa = R200_CONTEXT(ctx);
628 GLfloat *fcmd = (GLfloat *)rmesa->hw.ptp.cmd;
629
630 switch (pname) {
631 case GL_POINT_SIZE_MIN:
632 /* Can clamp both in tcl and setup - just set both (as does fglrx) */
633 R200_STATECHANGE( rmesa, lin );
634 R200_STATECHANGE( rmesa, ptp );
635 rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] &= 0xffff;
636 rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] |= (GLuint)(ctx->Point.MinSize * 16.0) << 16;
637 fcmd[PTP_CLAMP_MIN] = ctx->Point.MinSize;
638 break;
639 case GL_POINT_SIZE_MAX:
640 R200_STATECHANGE( rmesa, cst );
641 R200_STATECHANGE( rmesa, ptp );
642 rmesa->hw.cst.cmd[CST_RE_POINTSIZE] &= 0xffff;
643 rmesa->hw.cst.cmd[CST_RE_POINTSIZE] |= (GLuint)(ctx->Point.MaxSize * 16.0) << 16;
644 fcmd[PTP_CLAMP_MAX] = ctx->Point.MaxSize;
645 break;
646 case GL_POINT_DISTANCE_ATTENUATION:
647 R200_STATECHANGE( rmesa, vtx );
648 R200_STATECHANGE( rmesa, spr );
649 R200_STATECHANGE( rmesa, ptp );
650 GLfloat *fcmd = (GLfloat *)rmesa->hw.ptp.cmd;
651 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] &=
652 ~(R200_PS_MULT_MASK | R200_PS_LIN_ATT_ZERO | R200_PS_SE_SEL_STATE);
653 /* can't rely on ctx->Point._Attenuated here and test for NEW_POINT in
654 r200ValidateState looks like overkill */
655 if (ctx->Point.Params[0] != 1.0 ||
656 ctx->Point.Params[1] != 0.0 ||
657 ctx->Point.Params[2] != 0.0 ||
658 (ctx->VertexProgram.Enabled && ctx->VertexProgram.PointSizeEnabled)) {
659 /* all we care for vp would be the ps_se_sel_state setting */
660 fcmd[PTP_ATT_CONST_QUAD] = ctx->Point.Params[2];
661 fcmd[PTP_ATT_CONST_LIN] = ctx->Point.Params[1];
662 fcmd[PTP_ATT_CONST_CON] = ctx->Point.Params[0];
663 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |= R200_PS_MULT_ATTENCONST;
664 if (ctx->Point.Params[1] == 0.0)
665 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |= R200_PS_LIN_ATT_ZERO;
666 /* FIXME: setting this here doesn't look quite ok - we only want to do
667 that if we're actually drawing points probably */
668 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_PT_SIZE;
669 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |= R200_VTX_POINT_SIZE;
670 }
671 else {
672 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |=
673 R200_PS_SE_SEL_STATE | R200_PS_MULT_CONST;
674 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] &= ~R200_OUTPUT_PT_SIZE;
675 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] &= ~R200_VTX_POINT_SIZE;
676 }
677 break;
678 case GL_POINT_FADE_THRESHOLD_SIZE:
679 /* don't support multisampling, so doesn't matter. */
680 break;
681 /* can't do these but don't need them.
682 case GL_POINT_SPRITE_R_MODE_NV:
683 case GL_POINT_SPRITE_COORD_ORIGIN: */
684 default:
685 fprintf(stderr, "bad pname parameter in r200PointParameter\n");
686 return;
687 }
688 }
689
690 /* =============================================================
691 * Line state
692 */
693 static void r200LineWidth( GLcontext *ctx, GLfloat widthf )
694 {
695 r200ContextPtr rmesa = R200_CONTEXT(ctx);
696
697 R200_STATECHANGE( rmesa, lin );
698 R200_STATECHANGE( rmesa, set );
699
700 /* Line width is stored in U6.4 format.
701 * Same min/max limits for AA, non-AA lines.
702 */
703 rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] &= ~0xffff;
704 rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] |= (GLuint)
705 (CLAMP(widthf, ctx->Const.MinLineWidth, ctx->Const.MaxLineWidth) * 16.0);
706
707 if ( widthf > 1.0 ) {
708 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_WIDELINE_ENABLE;
709 } else {
710 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_WIDELINE_ENABLE;
711 }
712 }
713
714 static void r200LineStipple( GLcontext *ctx, GLint factor, GLushort pattern )
715 {
716 r200ContextPtr rmesa = R200_CONTEXT(ctx);
717
718 R200_STATECHANGE( rmesa, lin );
719 rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] =
720 ((((GLuint)factor & 0xff) << 16) | ((GLuint)pattern));
721 }
722
723
724 /* =============================================================
725 * Masks
726 */
727 static void r200ColorMask( GLcontext *ctx,
728 GLboolean r, GLboolean g,
729 GLboolean b, GLboolean a )
730 {
731 r200ContextPtr rmesa = R200_CONTEXT(ctx);
732 GLuint mask = radeonPackColor( rmesa->radeon.radeonScreen->cpp,
733 ctx->Color.ColorMask[RCOMP],
734 ctx->Color.ColorMask[GCOMP],
735 ctx->Color.ColorMask[BCOMP],
736 ctx->Color.ColorMask[ACOMP] );
737
738 GLuint flag = rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] & ~R200_PLANE_MASK_ENABLE;
739
740 if (!(r && g && b && a))
741 flag |= R200_PLANE_MASK_ENABLE;
742
743 if ( rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] != flag ) {
744 R200_STATECHANGE( rmesa, ctx );
745 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = flag;
746 }
747
748 if ( rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] != mask ) {
749 R200_STATECHANGE( rmesa, msk );
750 rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] = mask;
751 }
752 }
753
754
755 /* =============================================================
756 * Polygon state
757 */
758
759 static void r200PolygonOffset( GLcontext *ctx,
760 GLfloat factor, GLfloat units )
761 {
762 r200ContextPtr rmesa = R200_CONTEXT(ctx);
763 float_ui32_type constant = { units * rmesa->radeon.state.depth.scale };
764 float_ui32_type factoru = { factor };
765
766 /* factor *= 2; */
767 /* constant *= 2; */
768
769 /* fprintf(stderr, "%s f:%f u:%f\n", __FUNCTION__, factor, constant); */
770
771 R200_STATECHANGE( rmesa, zbs );
772 rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_FACTOR] = factoru.ui32;
773 rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_CONSTANT] = constant.ui32;
774 }
775
776 static void r200PolygonStipple( GLcontext *ctx, const GLubyte *mask )
777 {
778 r200ContextPtr rmesa = R200_CONTEXT(ctx);
779 GLuint i;
780 drm_radeon_stipple_t stipple;
781
782 /* Must flip pattern upside down.
783 */
784 for ( i = 0 ; i < 32 ; i++ ) {
785 rmesa->state.stipple.mask[31 - i] = ((GLuint *) mask)[i];
786 }
787
788 /* TODO: push this into cmd mechanism
789 */
790 R200_FIREVERTICES( rmesa );
791 LOCK_HARDWARE( &rmesa->radeon );
792
793 /* FIXME: Use window x,y offsets into stipple RAM.
794 */
795 stipple.mask = rmesa->state.stipple.mask;
796 drmCommandWrite( rmesa->radeon.dri.fd, DRM_RADEON_STIPPLE,
797 &stipple, sizeof(stipple) );
798 UNLOCK_HARDWARE( &rmesa->radeon );
799 }
800
801 static void r200PolygonMode( GLcontext *ctx, GLenum face, GLenum mode )
802 {
803 r200ContextPtr rmesa = R200_CONTEXT(ctx);
804 GLboolean flag = (ctx->_TriangleCaps & DD_TRI_UNFILLED) != 0;
805
806 /* Can't generally do unfilled via tcl, but some good special
807 * cases work.
808 */
809 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_UNFILLED, flag);
810 if (rmesa->radeon.TclFallback) {
811 r200ChooseRenderState( ctx );
812 r200ChooseVertexState( ctx );
813 }
814 }
815
816
817 /* =============================================================
818 * Rendering attributes
819 *
820 * We really don't want to recalculate all this every time we bind a
821 * texture. These things shouldn't change all that often, so it makes
822 * sense to break them out of the core texture state update routines.
823 */
824
825 /* Examine lighting and texture state to determine if separate specular
826 * should be enabled.
827 */
828 static void r200UpdateSpecular( GLcontext *ctx )
829 {
830 r200ContextPtr rmesa = R200_CONTEXT(ctx);
831 uint32_t p = rmesa->hw.ctx.cmd[CTX_PP_CNTL];
832
833 R200_STATECHANGE( rmesa, tcl );
834 R200_STATECHANGE( rmesa, vtx );
835
836 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] &= ~(3<<R200_VTX_COLOR_0_SHIFT);
837 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] &= ~(3<<R200_VTX_COLOR_1_SHIFT);
838 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] &= ~R200_OUTPUT_COLOR_0;
839 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] &= ~R200_OUTPUT_COLOR_1;
840 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_LIGHTING_ENABLE;
841
842 p &= ~R200_SPECULAR_ENABLE;
843
844 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_DIFFUSE_SPECULAR_COMBINE;
845
846
847 if (ctx->Light.Enabled &&
848 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) {
849 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
850 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT) |
851 (R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT));
852 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_0;
853 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_1;
854 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHTING_ENABLE;
855 p |= R200_SPECULAR_ENABLE;
856 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &=
857 ~R200_DIFFUSE_SPECULAR_COMBINE;
858 }
859 else if (ctx->Light.Enabled) {
860 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
861 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT));
862 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_0;
863 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHTING_ENABLE;
864 } else if (ctx->Fog.ColorSumEnabled ) {
865 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
866 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT) |
867 (R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT));
868 p |= R200_SPECULAR_ENABLE;
869 } else {
870 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
871 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT));
872 }
873
874 if (ctx->Fog.Enabled) {
875 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
876 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT));
877 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_1;
878 }
879
880 if ( rmesa->hw.ctx.cmd[CTX_PP_CNTL] != p ) {
881 R200_STATECHANGE( rmesa, ctx );
882 rmesa->hw.ctx.cmd[CTX_PP_CNTL] = p;
883 }
884
885 /* Update vertex/render formats
886 */
887 if (rmesa->radeon.TclFallback) {
888 r200ChooseRenderState( ctx );
889 r200ChooseVertexState( ctx );
890 }
891 }
892
893
894 /* =============================================================
895 * Materials
896 */
897
898
899 /* Update on colormaterial, material emmissive/ambient,
900 * lightmodel.globalambient
901 */
902 static void update_global_ambient( GLcontext *ctx )
903 {
904 r200ContextPtr rmesa = R200_CONTEXT(ctx);
905 float *fcmd = (float *)R200_DB_STATE( glt );
906
907 /* Need to do more if both emmissive & ambient are PREMULT:
908 * I believe this is not nessary when using source_material. This condition thus
909 * will never happen currently, and the function has no dependencies on materials now
910 */
911 if ((rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1] &
912 ((3 << R200_FRONT_EMISSIVE_SOURCE_SHIFT) |
913 (3 << R200_FRONT_AMBIENT_SOURCE_SHIFT))) == 0)
914 {
915 COPY_3V( &fcmd[GLT_RED],
916 ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION]);
917 ACC_SCALE_3V( &fcmd[GLT_RED],
918 ctx->Light.Model.Ambient,
919 ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT]);
920 }
921 else
922 {
923 COPY_3V( &fcmd[GLT_RED], ctx->Light.Model.Ambient );
924 }
925
926 R200_DB_STATECHANGE(rmesa, &rmesa->hw.glt);
927 }
928
929 /* Update on change to
930 * - light[p].colors
931 * - light[p].enabled
932 */
933 static void update_light_colors( GLcontext *ctx, GLuint p )
934 {
935 struct gl_light *l = &ctx->Light.Light[p];
936
937 /* fprintf(stderr, "%s\n", __FUNCTION__); */
938
939 if (l->Enabled) {
940 r200ContextPtr rmesa = R200_CONTEXT(ctx);
941 float *fcmd = (float *)R200_DB_STATE( lit[p] );
942
943 COPY_4V( &fcmd[LIT_AMBIENT_RED], l->Ambient );
944 COPY_4V( &fcmd[LIT_DIFFUSE_RED], l->Diffuse );
945 COPY_4V( &fcmd[LIT_SPECULAR_RED], l->Specular );
946
947 R200_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
948 }
949 }
950
951 static void r200ColorMaterial( GLcontext *ctx, GLenum face, GLenum mode )
952 {
953 r200ContextPtr rmesa = R200_CONTEXT(ctx);
954 GLuint light_model_ctl1 = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1];
955 light_model_ctl1 &= ~((0xf << R200_FRONT_EMISSIVE_SOURCE_SHIFT) |
956 (0xf << R200_FRONT_AMBIENT_SOURCE_SHIFT) |
957 (0xf << R200_FRONT_DIFFUSE_SOURCE_SHIFT) |
958 (0xf << R200_FRONT_SPECULAR_SOURCE_SHIFT) |
959 (0xf << R200_BACK_EMISSIVE_SOURCE_SHIFT) |
960 (0xf << R200_BACK_AMBIENT_SOURCE_SHIFT) |
961 (0xf << R200_BACK_DIFFUSE_SOURCE_SHIFT) |
962 (0xf << R200_BACK_SPECULAR_SOURCE_SHIFT));
963
964 if (ctx->Light.ColorMaterialEnabled) {
965 GLuint mask = ctx->Light.ColorMaterialBitmask;
966
967 if (mask & MAT_BIT_FRONT_EMISSION) {
968 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
969 R200_FRONT_EMISSIVE_SOURCE_SHIFT);
970 }
971 else
972 light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 <<
973 R200_FRONT_EMISSIVE_SOURCE_SHIFT);
974
975 if (mask & MAT_BIT_FRONT_AMBIENT) {
976 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
977 R200_FRONT_AMBIENT_SOURCE_SHIFT);
978 }
979 else
980 light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 <<
981 R200_FRONT_AMBIENT_SOURCE_SHIFT);
982
983 if (mask & MAT_BIT_FRONT_DIFFUSE) {
984 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
985 R200_FRONT_DIFFUSE_SOURCE_SHIFT);
986 }
987 else
988 light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 <<
989 R200_FRONT_DIFFUSE_SOURCE_SHIFT);
990
991 if (mask & MAT_BIT_FRONT_SPECULAR) {
992 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
993 R200_FRONT_SPECULAR_SOURCE_SHIFT);
994 }
995 else {
996 light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 <<
997 R200_FRONT_SPECULAR_SOURCE_SHIFT);
998 }
999
1000 if (mask & MAT_BIT_BACK_EMISSION) {
1001 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
1002 R200_BACK_EMISSIVE_SOURCE_SHIFT);
1003 }
1004
1005 else light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 <<
1006 R200_BACK_EMISSIVE_SOURCE_SHIFT);
1007
1008 if (mask & MAT_BIT_BACK_AMBIENT) {
1009 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
1010 R200_BACK_AMBIENT_SOURCE_SHIFT);
1011 }
1012 else light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 <<
1013 R200_BACK_AMBIENT_SOURCE_SHIFT);
1014
1015 if (mask & MAT_BIT_BACK_DIFFUSE) {
1016 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
1017 R200_BACK_DIFFUSE_SOURCE_SHIFT);
1018 }
1019 else light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 <<
1020 R200_BACK_DIFFUSE_SOURCE_SHIFT);
1021
1022 if (mask & MAT_BIT_BACK_SPECULAR) {
1023 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
1024 R200_BACK_SPECULAR_SOURCE_SHIFT);
1025 }
1026 else {
1027 light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 <<
1028 R200_BACK_SPECULAR_SOURCE_SHIFT);
1029 }
1030 }
1031 else {
1032 /* Default to SOURCE_MATERIAL:
1033 */
1034 light_model_ctl1 |=
1035 (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_EMISSIVE_SOURCE_SHIFT) |
1036 (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_AMBIENT_SOURCE_SHIFT) |
1037 (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_DIFFUSE_SOURCE_SHIFT) |
1038 (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_SPECULAR_SOURCE_SHIFT) |
1039 (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_EMISSIVE_SOURCE_SHIFT) |
1040 (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_AMBIENT_SOURCE_SHIFT) |
1041 (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_DIFFUSE_SOURCE_SHIFT) |
1042 (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_SPECULAR_SOURCE_SHIFT);
1043 }
1044
1045 if (light_model_ctl1 != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1]) {
1046 R200_STATECHANGE( rmesa, tcl );
1047 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1] = light_model_ctl1;
1048 }
1049
1050
1051 }
1052
1053 void r200UpdateMaterial( GLcontext *ctx )
1054 {
1055 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1056 GLfloat (*mat)[4] = ctx->Light.Material.Attrib;
1057 GLfloat *fcmd = (GLfloat *)R200_DB_STATE( mtl[0] );
1058 GLfloat *fcmd2 = (GLfloat *)R200_DB_STATE( mtl[1] );
1059 GLuint mask = ~0;
1060
1061 /* Might be possible and faster to update everything unconditionally? */
1062 if (ctx->Light.ColorMaterialEnabled)
1063 mask &= ~ctx->Light.ColorMaterialBitmask;
1064
1065 if (R200_DEBUG & DEBUG_STATE)
1066 fprintf(stderr, "%s\n", __FUNCTION__);
1067
1068 if (mask & MAT_BIT_FRONT_EMISSION) {
1069 fcmd[MTL_EMMISSIVE_RED] = mat[MAT_ATTRIB_FRONT_EMISSION][0];
1070 fcmd[MTL_EMMISSIVE_GREEN] = mat[MAT_ATTRIB_FRONT_EMISSION][1];
1071 fcmd[MTL_EMMISSIVE_BLUE] = mat[MAT_ATTRIB_FRONT_EMISSION][2];
1072 fcmd[MTL_EMMISSIVE_ALPHA] = mat[MAT_ATTRIB_FRONT_EMISSION][3];
1073 }
1074 if (mask & MAT_BIT_FRONT_AMBIENT) {
1075 fcmd[MTL_AMBIENT_RED] = mat[MAT_ATTRIB_FRONT_AMBIENT][0];
1076 fcmd[MTL_AMBIENT_GREEN] = mat[MAT_ATTRIB_FRONT_AMBIENT][1];
1077 fcmd[MTL_AMBIENT_BLUE] = mat[MAT_ATTRIB_FRONT_AMBIENT][2];
1078 fcmd[MTL_AMBIENT_ALPHA] = mat[MAT_ATTRIB_FRONT_AMBIENT][3];
1079 }
1080 if (mask & MAT_BIT_FRONT_DIFFUSE) {
1081 fcmd[MTL_DIFFUSE_RED] = mat[MAT_ATTRIB_FRONT_DIFFUSE][0];
1082 fcmd[MTL_DIFFUSE_GREEN] = mat[MAT_ATTRIB_FRONT_DIFFUSE][1];
1083 fcmd[MTL_DIFFUSE_BLUE] = mat[MAT_ATTRIB_FRONT_DIFFUSE][2];
1084 fcmd[MTL_DIFFUSE_ALPHA] = mat[MAT_ATTRIB_FRONT_DIFFUSE][3];
1085 }
1086 if (mask & MAT_BIT_FRONT_SPECULAR) {
1087 fcmd[MTL_SPECULAR_RED] = mat[MAT_ATTRIB_FRONT_SPECULAR][0];
1088 fcmd[MTL_SPECULAR_GREEN] = mat[MAT_ATTRIB_FRONT_SPECULAR][1];
1089 fcmd[MTL_SPECULAR_BLUE] = mat[MAT_ATTRIB_FRONT_SPECULAR][2];
1090 fcmd[MTL_SPECULAR_ALPHA] = mat[MAT_ATTRIB_FRONT_SPECULAR][3];
1091 }
1092 if (mask & MAT_BIT_FRONT_SHININESS) {
1093 fcmd[MTL_SHININESS] = mat[MAT_ATTRIB_FRONT_SHININESS][0];
1094 }
1095
1096 if (mask & MAT_BIT_BACK_EMISSION) {
1097 fcmd2[MTL_EMMISSIVE_RED] = mat[MAT_ATTRIB_BACK_EMISSION][0];
1098 fcmd2[MTL_EMMISSIVE_GREEN] = mat[MAT_ATTRIB_BACK_EMISSION][1];
1099 fcmd2[MTL_EMMISSIVE_BLUE] = mat[MAT_ATTRIB_BACK_EMISSION][2];
1100 fcmd2[MTL_EMMISSIVE_ALPHA] = mat[MAT_ATTRIB_BACK_EMISSION][3];
1101 }
1102 if (mask & MAT_BIT_BACK_AMBIENT) {
1103 fcmd2[MTL_AMBIENT_RED] = mat[MAT_ATTRIB_BACK_AMBIENT][0];
1104 fcmd2[MTL_AMBIENT_GREEN] = mat[MAT_ATTRIB_BACK_AMBIENT][1];
1105 fcmd2[MTL_AMBIENT_BLUE] = mat[MAT_ATTRIB_BACK_AMBIENT][2];
1106 fcmd2[MTL_AMBIENT_ALPHA] = mat[MAT_ATTRIB_BACK_AMBIENT][3];
1107 }
1108 if (mask & MAT_BIT_BACK_DIFFUSE) {
1109 fcmd2[MTL_DIFFUSE_RED] = mat[MAT_ATTRIB_BACK_DIFFUSE][0];
1110 fcmd2[MTL_DIFFUSE_GREEN] = mat[MAT_ATTRIB_BACK_DIFFUSE][1];
1111 fcmd2[MTL_DIFFUSE_BLUE] = mat[MAT_ATTRIB_BACK_DIFFUSE][2];
1112 fcmd2[MTL_DIFFUSE_ALPHA] = mat[MAT_ATTRIB_BACK_DIFFUSE][3];
1113 }
1114 if (mask & MAT_BIT_BACK_SPECULAR) {
1115 fcmd2[MTL_SPECULAR_RED] = mat[MAT_ATTRIB_BACK_SPECULAR][0];
1116 fcmd2[MTL_SPECULAR_GREEN] = mat[MAT_ATTRIB_BACK_SPECULAR][1];
1117 fcmd2[MTL_SPECULAR_BLUE] = mat[MAT_ATTRIB_BACK_SPECULAR][2];
1118 fcmd2[MTL_SPECULAR_ALPHA] = mat[MAT_ATTRIB_BACK_SPECULAR][3];
1119 }
1120 if (mask & MAT_BIT_BACK_SHININESS) {
1121 fcmd2[MTL_SHININESS] = mat[MAT_ATTRIB_BACK_SHININESS][0];
1122 }
1123
1124 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mtl[0] );
1125 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mtl[1] );
1126
1127 /* currently material changes cannot trigger a global ambient change, I believe this is correct
1128 update_global_ambient( ctx ); */
1129 }
1130
1131 /* _NEW_LIGHT
1132 * _NEW_MODELVIEW
1133 * _MESA_NEW_NEED_EYE_COORDS
1134 *
1135 * Uses derived state from mesa:
1136 * _VP_inf_norm
1137 * _h_inf_norm
1138 * _Position
1139 * _NormDirection
1140 * _ModelViewInvScale
1141 * _NeedEyeCoords
1142 * _EyeZDir
1143 *
1144 * which are calculated in light.c and are correct for the current
1145 * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
1146 * and _MESA_NEW_NEED_EYE_COORDS.
1147 */
1148 static void update_light( GLcontext *ctx )
1149 {
1150 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1151
1152 /* Have to check these, or have an automatic shortcircuit mechanism
1153 * to remove noop statechanges. (Or just do a better job on the
1154 * front end).
1155 */
1156 {
1157 GLuint tmp = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0];
1158
1159 if (ctx->_NeedEyeCoords)
1160 tmp &= ~R200_LIGHT_IN_MODELSPACE;
1161 else
1162 tmp |= R200_LIGHT_IN_MODELSPACE;
1163
1164 if (tmp != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0])
1165 {
1166 R200_STATECHANGE( rmesa, tcl );
1167 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] = tmp;
1168 }
1169 }
1170
1171 {
1172 GLfloat *fcmd = (GLfloat *)R200_DB_STATE( eye );
1173 fcmd[EYE_X] = ctx->_EyeZDir[0];
1174 fcmd[EYE_Y] = ctx->_EyeZDir[1];
1175 fcmd[EYE_Z] = - ctx->_EyeZDir[2];
1176 fcmd[EYE_RESCALE_FACTOR] = ctx->_ModelViewInvScale;
1177 R200_DB_STATECHANGE( rmesa, &rmesa->hw.eye );
1178 }
1179
1180
1181
1182 if (ctx->Light.Enabled) {
1183 GLint p;
1184 for (p = 0 ; p < MAX_LIGHTS; p++) {
1185 if (ctx->Light.Light[p].Enabled) {
1186 struct gl_light *l = &ctx->Light.Light[p];
1187 GLfloat *fcmd = (GLfloat *)R200_DB_STATE( lit[p] );
1188
1189 if (l->EyePosition[3] == 0.0) {
1190 COPY_3FV( &fcmd[LIT_POSITION_X], l->_VP_inf_norm );
1191 COPY_3FV( &fcmd[LIT_DIRECTION_X], l->_h_inf_norm );
1192 fcmd[LIT_POSITION_W] = 0;
1193 fcmd[LIT_DIRECTION_W] = 0;
1194 } else {
1195 COPY_4V( &fcmd[LIT_POSITION_X], l->_Position );
1196 fcmd[LIT_DIRECTION_X] = -l->_NormDirection[0];
1197 fcmd[LIT_DIRECTION_Y] = -l->_NormDirection[1];
1198 fcmd[LIT_DIRECTION_Z] = -l->_NormDirection[2];
1199 fcmd[LIT_DIRECTION_W] = 0;
1200 }
1201
1202 R200_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
1203 }
1204 }
1205 }
1206 }
1207
1208 static void r200Lightfv( GLcontext *ctx, GLenum light,
1209 GLenum pname, const GLfloat *params )
1210 {
1211 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1212 GLint p = light - GL_LIGHT0;
1213 struct gl_light *l = &ctx->Light.Light[p];
1214 GLfloat *fcmd = (GLfloat *)rmesa->hw.lit[p].cmd;
1215
1216
1217 switch (pname) {
1218 case GL_AMBIENT:
1219 case GL_DIFFUSE:
1220 case GL_SPECULAR:
1221 update_light_colors( ctx, p );
1222 break;
1223
1224 case GL_SPOT_DIRECTION:
1225 /* picked up in update_light */
1226 break;
1227
1228 case GL_POSITION: {
1229 /* positions picked up in update_light, but can do flag here */
1230 GLuint flag = (p&1)? R200_LIGHT_1_IS_LOCAL : R200_LIGHT_0_IS_LOCAL;
1231 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1232
1233 R200_STATECHANGE(rmesa, tcl);
1234 if (l->EyePosition[3] != 0.0F)
1235 rmesa->hw.tcl.cmd[idx] |= flag;
1236 else
1237 rmesa->hw.tcl.cmd[idx] &= ~flag;
1238 break;
1239 }
1240
1241 case GL_SPOT_EXPONENT:
1242 R200_STATECHANGE(rmesa, lit[p]);
1243 fcmd[LIT_SPOT_EXPONENT] = params[0];
1244 break;
1245
1246 case GL_SPOT_CUTOFF: {
1247 GLuint flag = (p&1) ? R200_LIGHT_1_IS_SPOT : R200_LIGHT_0_IS_SPOT;
1248 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1249
1250 R200_STATECHANGE(rmesa, lit[p]);
1251 fcmd[LIT_SPOT_CUTOFF] = l->_CosCutoff;
1252
1253 R200_STATECHANGE(rmesa, tcl);
1254 if (l->SpotCutoff != 180.0F)
1255 rmesa->hw.tcl.cmd[idx] |= flag;
1256 else
1257 rmesa->hw.tcl.cmd[idx] &= ~flag;
1258
1259 break;
1260 }
1261
1262 case GL_CONSTANT_ATTENUATION:
1263 R200_STATECHANGE(rmesa, lit[p]);
1264 fcmd[LIT_ATTEN_CONST] = params[0];
1265 if ( params[0] == 0.0 )
1266 fcmd[LIT_ATTEN_CONST_INV] = FLT_MAX;
1267 else
1268 fcmd[LIT_ATTEN_CONST_INV] = 1.0 / params[0];
1269 break;
1270 case GL_LINEAR_ATTENUATION:
1271 R200_STATECHANGE(rmesa, lit[p]);
1272 fcmd[LIT_ATTEN_LINEAR] = params[0];
1273 break;
1274 case GL_QUADRATIC_ATTENUATION:
1275 R200_STATECHANGE(rmesa, lit[p]);
1276 fcmd[LIT_ATTEN_QUADRATIC] = params[0];
1277 break;
1278 default:
1279 return;
1280 }
1281
1282 /* Set RANGE_ATTEN only when needed */
1283 switch (pname) {
1284 case GL_POSITION:
1285 case GL_CONSTANT_ATTENUATION:
1286 case GL_LINEAR_ATTENUATION:
1287 case GL_QUADRATIC_ATTENUATION: {
1288 GLuint *icmd = (GLuint *)R200_DB_STATE( tcl );
1289 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1290 GLuint atten_flag = ( p&1 ) ? R200_LIGHT_1_ENABLE_RANGE_ATTEN
1291 : R200_LIGHT_0_ENABLE_RANGE_ATTEN;
1292 GLuint atten_const_flag = ( p&1 ) ? R200_LIGHT_1_CONSTANT_RANGE_ATTEN
1293 : R200_LIGHT_0_CONSTANT_RANGE_ATTEN;
1294
1295 if ( l->EyePosition[3] == 0.0F ||
1296 ( ( fcmd[LIT_ATTEN_CONST] == 0.0 || fcmd[LIT_ATTEN_CONST] == 1.0 ) &&
1297 fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) ) {
1298 /* Disable attenuation */
1299 icmd[idx] &= ~atten_flag;
1300 } else {
1301 if ( fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) {
1302 /* Enable only constant portion of attenuation calculation */
1303 icmd[idx] |= ( atten_flag | atten_const_flag );
1304 } else {
1305 /* Enable full attenuation calculation */
1306 icmd[idx] &= ~atten_const_flag;
1307 icmd[idx] |= atten_flag;
1308 }
1309 }
1310
1311 R200_DB_STATECHANGE( rmesa, &rmesa->hw.tcl );
1312 break;
1313 }
1314 default:
1315 break;
1316 }
1317 }
1318
1319 static void r200UpdateLocalViewer ( GLcontext *ctx )
1320 {
1321 /* It looks like for the texgen modes GL_SPHERE_MAP, GL_NORMAL_MAP and
1322 GL_REFLECTION_MAP we need R200_LOCAL_VIEWER set (fglrx does exactly that
1323 for these and only these modes). This means specular highlights may turn out
1324 wrong in some cases when lighting is enabled but GL_LIGHT_MODEL_LOCAL_VIEWER
1325 is not set, though it seems to happen rarely and the effect seems quite
1326 subtle. May need TCL fallback to fix it completely, though I'm not sure
1327 how you'd identify the cases where the specular highlights indeed will
1328 be wrong. Don't know if fglrx does something special in that case.
1329 */
1330 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1331 R200_STATECHANGE( rmesa, tcl );
1332 if (ctx->Light.Model.LocalViewer ||
1333 ctx->Texture._GenFlags & TEXGEN_NEED_NORMALS)
1334 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LOCAL_VIEWER;
1335 else
1336 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_LOCAL_VIEWER;
1337 }
1338
1339 static void r200LightModelfv( GLcontext *ctx, GLenum pname,
1340 const GLfloat *param )
1341 {
1342 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1343
1344 switch (pname) {
1345 case GL_LIGHT_MODEL_AMBIENT:
1346 update_global_ambient( ctx );
1347 break;
1348
1349 case GL_LIGHT_MODEL_LOCAL_VIEWER:
1350 r200UpdateLocalViewer( ctx );
1351 break;
1352
1353 case GL_LIGHT_MODEL_TWO_SIDE:
1354 R200_STATECHANGE( rmesa, tcl );
1355 if (ctx->Light.Model.TwoSide)
1356 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHT_TWOSIDE;
1357 else
1358 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~(R200_LIGHT_TWOSIDE);
1359 if (rmesa->radeon.TclFallback) {
1360 r200ChooseRenderState( ctx );
1361 r200ChooseVertexState( ctx );
1362 }
1363 break;
1364
1365 case GL_LIGHT_MODEL_COLOR_CONTROL:
1366 r200UpdateSpecular(ctx);
1367 break;
1368
1369 default:
1370 break;
1371 }
1372 }
1373
1374 static void r200ShadeModel( GLcontext *ctx, GLenum mode )
1375 {
1376 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1377 GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL];
1378
1379 s &= ~(R200_DIFFUSE_SHADE_MASK |
1380 R200_ALPHA_SHADE_MASK |
1381 R200_SPECULAR_SHADE_MASK |
1382 R200_FOG_SHADE_MASK |
1383 R200_DISC_FOG_SHADE_MASK);
1384
1385 switch ( mode ) {
1386 case GL_FLAT:
1387 s |= (R200_DIFFUSE_SHADE_FLAT |
1388 R200_ALPHA_SHADE_FLAT |
1389 R200_SPECULAR_SHADE_FLAT |
1390 R200_FOG_SHADE_FLAT |
1391 R200_DISC_FOG_SHADE_FLAT);
1392 break;
1393 case GL_SMOOTH:
1394 s |= (R200_DIFFUSE_SHADE_GOURAUD |
1395 R200_ALPHA_SHADE_GOURAUD |
1396 R200_SPECULAR_SHADE_GOURAUD |
1397 R200_FOG_SHADE_GOURAUD |
1398 R200_DISC_FOG_SHADE_GOURAUD);
1399 break;
1400 default:
1401 return;
1402 }
1403
1404 if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) {
1405 R200_STATECHANGE( rmesa, set );
1406 rmesa->hw.set.cmd[SET_SE_CNTL] = s;
1407 }
1408 }
1409
1410
1411 /* =============================================================
1412 * User clip planes
1413 */
1414
1415 static void r200ClipPlane( GLcontext *ctx, GLenum plane, const GLfloat *eq )
1416 {
1417 GLint p = (GLint) plane - (GLint) GL_CLIP_PLANE0;
1418 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1419 GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
1420
1421 R200_STATECHANGE( rmesa, ucp[p] );
1422 rmesa->hw.ucp[p].cmd[UCP_X] = ip[0];
1423 rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1];
1424 rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2];
1425 rmesa->hw.ucp[p].cmd[UCP_W] = ip[3];
1426 }
1427
1428 static void r200UpdateClipPlanes( GLcontext *ctx )
1429 {
1430 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1431 GLuint p;
1432
1433 for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
1434 if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
1435 GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
1436
1437 R200_STATECHANGE( rmesa, ucp[p] );
1438 rmesa->hw.ucp[p].cmd[UCP_X] = ip[0];
1439 rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1];
1440 rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2];
1441 rmesa->hw.ucp[p].cmd[UCP_W] = ip[3];
1442 }
1443 }
1444 }
1445
1446
1447 /* =============================================================
1448 * Stencil
1449 */
1450
1451 static void
1452 r200StencilFuncSeparate( GLcontext *ctx, GLenum face, GLenum func,
1453 GLint ref, GLuint mask )
1454 {
1455 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1456 GLuint refmask = (((ctx->Stencil.Ref[0] & 0xff) << R200_STENCIL_REF_SHIFT) |
1457 ((ctx->Stencil.ValueMask[0] & 0xff) << R200_STENCIL_MASK_SHIFT));
1458
1459 R200_STATECHANGE( rmesa, ctx );
1460 R200_STATECHANGE( rmesa, msk );
1461
1462 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_STENCIL_TEST_MASK;
1463 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~(R200_STENCIL_REF_MASK|
1464 R200_STENCIL_VALUE_MASK);
1465
1466 switch ( ctx->Stencil.Function[0] ) {
1467 case GL_NEVER:
1468 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_NEVER;
1469 break;
1470 case GL_LESS:
1471 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_LESS;
1472 break;
1473 case GL_EQUAL:
1474 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_EQUAL;
1475 break;
1476 case GL_LEQUAL:
1477 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_LEQUAL;
1478 break;
1479 case GL_GREATER:
1480 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_GREATER;
1481 break;
1482 case GL_NOTEQUAL:
1483 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_NEQUAL;
1484 break;
1485 case GL_GEQUAL:
1486 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_GEQUAL;
1487 break;
1488 case GL_ALWAYS:
1489 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_ALWAYS;
1490 break;
1491 }
1492
1493 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |= refmask;
1494 }
1495
1496 static void
1497 r200StencilMaskSeparate( GLcontext *ctx, GLenum face, GLuint mask )
1498 {
1499 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1500
1501 R200_STATECHANGE( rmesa, msk );
1502 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~R200_STENCIL_WRITE_MASK;
1503 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |=
1504 ((ctx->Stencil.WriteMask[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT);
1505 }
1506
1507 static void
1508 r200StencilOpSeparate( GLcontext *ctx, GLenum face, GLenum fail,
1509 GLenum zfail, GLenum zpass )
1510 {
1511 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1512
1513 R200_STATECHANGE( rmesa, ctx );
1514 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~(R200_STENCIL_FAIL_MASK |
1515 R200_STENCIL_ZFAIL_MASK |
1516 R200_STENCIL_ZPASS_MASK);
1517
1518 switch ( ctx->Stencil.FailFunc[0] ) {
1519 case GL_KEEP:
1520 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_KEEP;
1521 break;
1522 case GL_ZERO:
1523 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_ZERO;
1524 break;
1525 case GL_REPLACE:
1526 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_REPLACE;
1527 break;
1528 case GL_INCR:
1529 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INC;
1530 break;
1531 case GL_DECR:
1532 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_DEC;
1533 break;
1534 case GL_INCR_WRAP_EXT:
1535 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INC_WRAP;
1536 break;
1537 case GL_DECR_WRAP_EXT:
1538 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_DEC_WRAP;
1539 break;
1540 case GL_INVERT:
1541 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INVERT;
1542 break;
1543 }
1544
1545 switch ( ctx->Stencil.ZFailFunc[0] ) {
1546 case GL_KEEP:
1547 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_KEEP;
1548 break;
1549 case GL_ZERO:
1550 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_ZERO;
1551 break;
1552 case GL_REPLACE:
1553 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_REPLACE;
1554 break;
1555 case GL_INCR:
1556 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INC;
1557 break;
1558 case GL_DECR:
1559 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_DEC;
1560 break;
1561 case GL_INCR_WRAP_EXT:
1562 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INC_WRAP;
1563 break;
1564 case GL_DECR_WRAP_EXT:
1565 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_DEC_WRAP;
1566 break;
1567 case GL_INVERT:
1568 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INVERT;
1569 break;
1570 }
1571
1572 switch ( ctx->Stencil.ZPassFunc[0] ) {
1573 case GL_KEEP:
1574 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_KEEP;
1575 break;
1576 case GL_ZERO:
1577 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_ZERO;
1578 break;
1579 case GL_REPLACE:
1580 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_REPLACE;
1581 break;
1582 case GL_INCR:
1583 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INC;
1584 break;
1585 case GL_DECR:
1586 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_DEC;
1587 break;
1588 case GL_INCR_WRAP_EXT:
1589 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INC_WRAP;
1590 break;
1591 case GL_DECR_WRAP_EXT:
1592 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_DEC_WRAP;
1593 break;
1594 case GL_INVERT:
1595 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INVERT;
1596 break;
1597 }
1598 }
1599
1600 static void r200ClearStencil( GLcontext *ctx, GLint s )
1601 {
1602 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1603
1604 rmesa->radeon.state.stencil.clear =
1605 ((GLuint) (ctx->Stencil.Clear & 0xff) |
1606 (0xff << R200_STENCIL_MASK_SHIFT) |
1607 ((ctx->Stencil.WriteMask[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT));
1608 }
1609
1610
1611 /* =============================================================
1612 * Window position and viewport transformation
1613 */
1614
1615 /*
1616 * To correctly position primitives:
1617 */
1618 #define SUBPIXEL_X 0.125
1619 #define SUBPIXEL_Y 0.125
1620
1621
1622 /**
1623 * Called when window size or position changes or viewport or depth range
1624 * state is changed. We update the hardware viewport state here.
1625 */
1626 void r200UpdateWindow( GLcontext *ctx )
1627 {
1628 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1629 __DRIdrawablePrivate *dPriv = rmesa->radeon.dri.drawable;
1630 GLfloat xoffset = dPriv ? (GLfloat) dPriv->x : 0;
1631 GLfloat yoffset = dPriv ? (GLfloat) dPriv->y + dPriv->h : 0;
1632 const GLfloat *v = ctx->Viewport._WindowMap.m;
1633
1634 float_ui32_type sx = { v[MAT_SX] };
1635 float_ui32_type tx = { v[MAT_TX] + xoffset + SUBPIXEL_X };
1636 float_ui32_type sy = { - v[MAT_SY] };
1637 float_ui32_type ty = { (- v[MAT_TY]) + yoffset + SUBPIXEL_Y };
1638 float_ui32_type sz = { v[MAT_SZ] * rmesa->radeon.state.depth.scale };
1639 float_ui32_type tz = { v[MAT_TZ] * rmesa->radeon.state.depth.scale };
1640
1641 R200_FIREVERTICES( rmesa );
1642 R200_STATECHANGE( rmesa, vpt );
1643
1644 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XSCALE] = sx.ui32;
1645 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = tx.ui32;
1646 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YSCALE] = sy.ui32;
1647 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = ty.ui32;
1648 rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZSCALE] = sz.ui32;
1649 rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZOFFSET] = tz.ui32;
1650 }
1651
1652
1653
1654 static void r200Viewport( GLcontext *ctx, GLint x, GLint y,
1655 GLsizei width, GLsizei height )
1656 {
1657 /* Don't pipeline viewport changes, conflict with window offset
1658 * setting below. Could apply deltas to rescue pipelined viewport
1659 * values, or keep the originals hanging around.
1660 */
1661 r200UpdateWindow( ctx );
1662 }
1663
1664 static void r200DepthRange( GLcontext *ctx, GLclampd nearval,
1665 GLclampd farval )
1666 {
1667 r200UpdateWindow( ctx );
1668 }
1669
1670 void r200UpdateViewportOffset( GLcontext *ctx )
1671 {
1672 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1673 __DRIdrawablePrivate *dPriv = rmesa->radeon.dri.drawable;
1674 GLfloat xoffset = (GLfloat)dPriv->x;
1675 GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h;
1676 const GLfloat *v = ctx->Viewport._WindowMap.m;
1677
1678 float_ui32_type tx;
1679 float_ui32_type ty;
1680
1681 tx.f = v[MAT_TX] + xoffset + SUBPIXEL_X;
1682 ty.f = (- v[MAT_TY]) + yoffset + SUBPIXEL_Y;
1683
1684 if ( rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] != tx.ui32 ||
1685 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] != ty.ui32 )
1686 {
1687 /* Note: this should also modify whatever data the context reset
1688 * code uses...
1689 */
1690 R200_STATECHANGE( rmesa, vpt );
1691 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = tx.ui32;
1692 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = ty.ui32;
1693
1694 /* update polygon stipple x/y screen offset */
1695 {
1696 GLuint stx, sty;
1697 GLuint m = rmesa->hw.msc.cmd[MSC_RE_MISC];
1698
1699 m &= ~(R200_STIPPLE_X_OFFSET_MASK |
1700 R200_STIPPLE_Y_OFFSET_MASK);
1701
1702 /* add magic offsets, then invert */
1703 stx = 31 - ((rmesa->radeon.dri.drawable->x - 1) & R200_STIPPLE_COORD_MASK);
1704 sty = 31 - ((rmesa->radeon.dri.drawable->y + rmesa->radeon.dri.drawable->h - 1)
1705 & R200_STIPPLE_COORD_MASK);
1706
1707 m |= ((stx << R200_STIPPLE_X_OFFSET_SHIFT) |
1708 (sty << R200_STIPPLE_Y_OFFSET_SHIFT));
1709
1710 if ( rmesa->hw.msc.cmd[MSC_RE_MISC] != m ) {
1711 R200_STATECHANGE( rmesa, msc );
1712 rmesa->hw.msc.cmd[MSC_RE_MISC] = m;
1713 }
1714 }
1715 }
1716
1717 radeonUpdateScissor( ctx );
1718 }
1719
1720
1721
1722 /* =============================================================
1723 * Miscellaneous
1724 */
1725
1726 static void r200ClearColor( GLcontext *ctx, const GLfloat c[4] )
1727 {
1728 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1729 GLubyte color[4];
1730 CLAMPED_FLOAT_TO_UBYTE(color[0], c[0]);
1731 CLAMPED_FLOAT_TO_UBYTE(color[1], c[1]);
1732 CLAMPED_FLOAT_TO_UBYTE(color[2], c[2]);
1733 CLAMPED_FLOAT_TO_UBYTE(color[3], c[3]);
1734 rmesa->radeon.state.color.clear = radeonPackColor( rmesa->radeon.radeonScreen->cpp,
1735 color[0], color[1],
1736 color[2], color[3] );
1737 }
1738
1739
1740 static void r200RenderMode( GLcontext *ctx, GLenum mode )
1741 {
1742 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1743 FALLBACK( rmesa, R200_FALLBACK_RENDER_MODE, (mode != GL_RENDER) );
1744 }
1745
1746
1747 static GLuint r200_rop_tab[] = {
1748 R200_ROP_CLEAR,
1749 R200_ROP_AND,
1750 R200_ROP_AND_REVERSE,
1751 R200_ROP_COPY,
1752 R200_ROP_AND_INVERTED,
1753 R200_ROP_NOOP,
1754 R200_ROP_XOR,
1755 R200_ROP_OR,
1756 R200_ROP_NOR,
1757 R200_ROP_EQUIV,
1758 R200_ROP_INVERT,
1759 R200_ROP_OR_REVERSE,
1760 R200_ROP_COPY_INVERTED,
1761 R200_ROP_OR_INVERTED,
1762 R200_ROP_NAND,
1763 R200_ROP_SET,
1764 };
1765
1766 static void r200LogicOpCode( GLcontext *ctx, GLenum opcode )
1767 {
1768 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1769 GLuint rop = (GLuint)opcode - GL_CLEAR;
1770
1771 ASSERT( rop < 16 );
1772
1773 R200_STATECHANGE( rmesa, msk );
1774 rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = r200_rop_tab[rop];
1775 }
1776
1777
1778 static void r200DrawBuffer( GLcontext *ctx, GLenum mode )
1779 {
1780 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1781
1782 if (R200_DEBUG & DEBUG_DRI)
1783 fprintf(stderr, "%s %s\n", __FUNCTION__,
1784 _mesa_lookup_enum_by_nr( mode ));
1785
1786 R200_FIREVERTICES(rmesa); /* don't pipeline cliprect changes */
1787
1788 if (ctx->DrawBuffer->_NumColorDrawBuffers != 1) {
1789 /* 0 (GL_NONE) buffers or multiple color drawing buffers */
1790 FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_TRUE );
1791 return;
1792 }
1793
1794 switch ( ctx->DrawBuffer->_ColorDrawBufferIndexes[0] ) {
1795 case BUFFER_FRONT_LEFT:
1796 case BUFFER_BACK_LEFT:
1797 FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_FALSE );
1798 break;
1799 default:
1800 FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_TRUE );
1801 return;
1802 }
1803
1804 radeonSetCliprects( &rmesa->radeon );
1805
1806 /* We'll set the drawing engine's offset/pitch parameters later
1807 * when we update other state.
1808 */
1809 }
1810
1811
1812 static void r200ReadBuffer( GLcontext *ctx, GLenum mode )
1813 {
1814 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
1815 }
1816
1817 /* =============================================================
1818 * State enable/disable
1819 */
1820
1821 static void r200Enable( GLcontext *ctx, GLenum cap, GLboolean state )
1822 {
1823 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1824 GLuint p, flag;
1825
1826 if ( R200_DEBUG & DEBUG_STATE )
1827 fprintf( stderr, "%s( %s = %s )\n", __FUNCTION__,
1828 _mesa_lookup_enum_by_nr( cap ),
1829 state ? "GL_TRUE" : "GL_FALSE" );
1830
1831 switch ( cap ) {
1832 /* Fast track this one...
1833 */
1834 case GL_TEXTURE_1D:
1835 case GL_TEXTURE_2D:
1836 case GL_TEXTURE_3D:
1837 break;
1838
1839 case GL_ALPHA_TEST:
1840 R200_STATECHANGE( rmesa, ctx );
1841 if (state) {
1842 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ALPHA_TEST_ENABLE;
1843 } else {
1844 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ALPHA_TEST_ENABLE;
1845 }
1846 break;
1847
1848 case GL_BLEND:
1849 case GL_COLOR_LOGIC_OP:
1850 r200_set_blend_state( ctx );
1851 break;
1852
1853 case GL_CLIP_PLANE0:
1854 case GL_CLIP_PLANE1:
1855 case GL_CLIP_PLANE2:
1856 case GL_CLIP_PLANE3:
1857 case GL_CLIP_PLANE4:
1858 case GL_CLIP_PLANE5:
1859 p = cap-GL_CLIP_PLANE0;
1860 R200_STATECHANGE( rmesa, tcl );
1861 if (state) {
1862 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (R200_UCP_ENABLE_0<<p);
1863 r200ClipPlane( ctx, cap, NULL );
1864 }
1865 else {
1866 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0<<p);
1867 }
1868 break;
1869
1870 case GL_COLOR_MATERIAL:
1871 r200ColorMaterial( ctx, 0, 0 );
1872 r200UpdateMaterial( ctx );
1873 break;
1874
1875 case GL_CULL_FACE:
1876 r200CullFace( ctx, 0 );
1877 break;
1878
1879 case GL_DEPTH_TEST:
1880 R200_STATECHANGE(rmesa, ctx );
1881 if ( state ) {
1882 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_Z_ENABLE;
1883 } else {
1884 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_Z_ENABLE;
1885 }
1886 break;
1887
1888 case GL_DITHER:
1889 R200_STATECHANGE(rmesa, ctx );
1890 if ( state ) {
1891 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_DITHER_ENABLE;
1892 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~rmesa->radeon.state.color.roundEnable;
1893 } else {
1894 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_DITHER_ENABLE;
1895 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= rmesa->radeon.state.color.roundEnable;
1896 }
1897 break;
1898
1899 case GL_FOG:
1900 R200_STATECHANGE(rmesa, ctx );
1901 if ( state ) {
1902 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_FOG_ENABLE;
1903 r200Fogfv( ctx, GL_FOG_MODE, NULL );
1904 } else {
1905 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_FOG_ENABLE;
1906 R200_STATECHANGE(rmesa, tcl);
1907 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_TCL_FOG_MASK;
1908 }
1909 r200UpdateSpecular( ctx ); /* for PK_SPEC */
1910 if (rmesa->radeon.TclFallback)
1911 r200ChooseVertexState( ctx );
1912 _mesa_allow_light_in_model( ctx, !state );
1913 break;
1914
1915 case GL_LIGHT0:
1916 case GL_LIGHT1:
1917 case GL_LIGHT2:
1918 case GL_LIGHT3:
1919 case GL_LIGHT4:
1920 case GL_LIGHT5:
1921 case GL_LIGHT6:
1922 case GL_LIGHT7:
1923 R200_STATECHANGE(rmesa, tcl);
1924 p = cap - GL_LIGHT0;
1925 if (p&1)
1926 flag = (R200_LIGHT_1_ENABLE |
1927 R200_LIGHT_1_ENABLE_AMBIENT |
1928 R200_LIGHT_1_ENABLE_SPECULAR);
1929 else
1930 flag = (R200_LIGHT_0_ENABLE |
1931 R200_LIGHT_0_ENABLE_AMBIENT |
1932 R200_LIGHT_0_ENABLE_SPECULAR);
1933
1934 if (state)
1935 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] |= flag;
1936 else
1937 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] &= ~flag;
1938
1939 /*
1940 */
1941 update_light_colors( ctx, p );
1942 break;
1943
1944 case GL_LIGHTING:
1945 r200UpdateSpecular(ctx);
1946 /* for reflection map fixup - might set recheck_texgen for all units too */
1947 rmesa->radeon.NewGLState |= _NEW_TEXTURE;
1948 break;
1949
1950 case GL_LINE_SMOOTH:
1951 R200_STATECHANGE( rmesa, ctx );
1952 if ( state ) {
1953 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ANTI_ALIAS_LINE;
1954 } else {
1955 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_LINE;
1956 }
1957 break;
1958
1959 case GL_LINE_STIPPLE:
1960 R200_STATECHANGE( rmesa, set );
1961 if ( state ) {
1962 rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_PATTERN_ENABLE;
1963 } else {
1964 rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_PATTERN_ENABLE;
1965 }
1966 break;
1967
1968 case GL_NORMALIZE:
1969 R200_STATECHANGE( rmesa, tcl );
1970 if ( state ) {
1971 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_NORMALIZE_NORMALS;
1972 } else {
1973 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_NORMALIZE_NORMALS;
1974 }
1975 break;
1976
1977 /* Pointsize registers on r200 only work for point sprites, and point smooth
1978 * doesn't work for point sprites (and isn't needed for 1.0 sized aa points).
1979 * In any case, setting pointmin == pointsizemax == 1.0 for aa points
1980 * is enough to satisfy conform.
1981 */
1982 case GL_POINT_SMOOTH:
1983 break;
1984
1985 /* These don't really do anything, as we don't use the 3vtx
1986 * primitives yet.
1987 */
1988 #if 0
1989 case GL_POLYGON_OFFSET_POINT:
1990 R200_STATECHANGE( rmesa, set );
1991 if ( state ) {
1992 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_POINT;
1993 } else {
1994 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_POINT;
1995 }
1996 break;
1997
1998 case GL_POLYGON_OFFSET_LINE:
1999 R200_STATECHANGE( rmesa, set );
2000 if ( state ) {
2001 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_LINE;
2002 } else {
2003 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_LINE;
2004 }
2005 break;
2006 #endif
2007
2008 case GL_POINT_SPRITE_ARB:
2009 R200_STATECHANGE( rmesa, spr );
2010 if ( state ) {
2011 int i;
2012 for (i = 0; i < 6; i++) {
2013 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |=
2014 ctx->Point.CoordReplace[i] << (R200_PS_GEN_TEX_0_SHIFT + i);
2015 }
2016 } else {
2017 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] &= ~R200_PS_GEN_TEX_MASK;
2018 }
2019 break;
2020
2021 case GL_POLYGON_OFFSET_FILL:
2022 R200_STATECHANGE( rmesa, set );
2023 if ( state ) {
2024 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_TRI;
2025 } else {
2026 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_TRI;
2027 }
2028 break;
2029
2030 case GL_POLYGON_SMOOTH:
2031 R200_STATECHANGE( rmesa, ctx );
2032 if ( state ) {
2033 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ANTI_ALIAS_POLY;
2034 } else {
2035 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_POLY;
2036 }
2037 break;
2038
2039 case GL_POLYGON_STIPPLE:
2040 R200_STATECHANGE(rmesa, set );
2041 if ( state ) {
2042 rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_STIPPLE_ENABLE;
2043 } else {
2044 rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_STIPPLE_ENABLE;
2045 }
2046 break;
2047
2048 case GL_RESCALE_NORMAL_EXT: {
2049 GLboolean tmp = ctx->_NeedEyeCoords ? state : !state;
2050 R200_STATECHANGE( rmesa, tcl );
2051 if ( tmp ) {
2052 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_RESCALE_NORMALS;
2053 } else {
2054 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS;
2055 }
2056 break;
2057 }
2058
2059 case GL_SCISSOR_TEST:
2060 R200_FIREVERTICES( rmesa );
2061 rmesa->radeon.state.scissor.enabled = state;
2062 radeonUpdateScissor( ctx );
2063 break;
2064
2065 case GL_STENCIL_TEST:
2066 if ( rmesa->radeon.state.stencil.hwBuffer ) {
2067 R200_STATECHANGE( rmesa, ctx );
2068 if ( state ) {
2069 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_STENCIL_ENABLE;
2070 } else {
2071 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_STENCIL_ENABLE;
2072 }
2073 } else {
2074 FALLBACK( rmesa, R200_FALLBACK_STENCIL, state );
2075 }
2076 break;
2077
2078 case GL_TEXTURE_GEN_Q:
2079 case GL_TEXTURE_GEN_R:
2080 case GL_TEXTURE_GEN_S:
2081 case GL_TEXTURE_GEN_T:
2082 /* Picked up in r200UpdateTextureState.
2083 */
2084 rmesa->recheck_texgen[ctx->Texture.CurrentUnit] = GL_TRUE;
2085 break;
2086
2087 case GL_COLOR_SUM_EXT:
2088 r200UpdateSpecular ( ctx );
2089 break;
2090
2091 case GL_VERTEX_PROGRAM_ARB:
2092 if (!state) {
2093 GLuint i;
2094 rmesa->curr_vp_hw = NULL;
2095 R200_STATECHANGE( rmesa, vap );
2096 rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] &= ~R200_VAP_PROG_VTX_SHADER_ENABLE;
2097 /* mark all tcl atoms (tcl vector state got overwritten) dirty
2098 not sure about tcl scalar state - we need at least grd
2099 with vert progs too.
2100 ucp looks like it doesn't get overwritten (may even work
2101 with vp for pos-invariant progs if we're lucky) */
2102 R200_STATECHANGE( rmesa, mtl[0] );
2103 R200_STATECHANGE( rmesa, mtl[1] );
2104 R200_STATECHANGE( rmesa, fog );
2105 R200_STATECHANGE( rmesa, glt );
2106 R200_STATECHANGE( rmesa, eye );
2107 for (i = R200_MTX_MV; i <= R200_MTX_TEX5; i++) {
2108 R200_STATECHANGE( rmesa, mat[i] );
2109 }
2110 for (i = 0 ; i < 8; i++) {
2111 R200_STATECHANGE( rmesa, lit[i] );
2112 }
2113 R200_STATECHANGE( rmesa, tcl );
2114 for (i = 0; i <= ctx->Const.MaxClipPlanes; i++) {
2115 if (ctx->Transform.ClipPlanesEnabled & (1 << i)) {
2116 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (R200_UCP_ENABLE_0 << i);
2117 }
2118 /* else {
2119 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0 << i);
2120 }*/
2121 }
2122 /* ugly. Need to call everything which might change compsel. */
2123 r200UpdateSpecular( ctx );
2124 #if 0
2125 /* shouldn't be necessary, as it's picked up anyway in r200ValidateState (_NEW_PROGRAM),
2126 but without it doom3 locks up at always the same places. Why? */
2127 /* FIXME: This can (and should) be replaced by a call to the TCL_STATE_FLUSH reg before
2128 accessing VAP_SE_VAP_CNTL. Requires drm changes (done). Remove after some time... */
2129 r200UpdateTextureState( ctx );
2130 /* if we call r200UpdateTextureState we need the code below because we are calling it with
2131 non-current derived enabled values which may revert the state atoms for frag progs even when
2132 they already got disabled... ugh
2133 Should really figure out why we need to call r200UpdateTextureState in the first place */
2134 GLuint unit;
2135 for (unit = 0; unit < R200_MAX_TEXTURE_UNITS; unit++) {
2136 R200_STATECHANGE( rmesa, pix[unit] );
2137 R200_STATECHANGE( rmesa, tex[unit] );
2138 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] &=
2139 ~(R200_TXFORMAT_ST_ROUTE_MASK | R200_TXFORMAT_LOOKUP_DISABLE);
2140 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] |= unit << R200_TXFORMAT_ST_ROUTE_SHIFT;
2141 /* need to guard this with drmSupportsFragmentShader? Should never get here if
2142 we don't announce ATI_fs, right? */
2143 rmesa->hw.tex[unit].cmd[TEX_PP_TXMULTI_CTL] = 0;
2144 }
2145 R200_STATECHANGE( rmesa, cst );
2146 R200_STATECHANGE( rmesa, tf );
2147 rmesa->hw.cst.cmd[CST_PP_CNTL_X] = 0;
2148 #endif
2149 }
2150 else {
2151 /* picked up later */
2152 }
2153 /* call functions which change hw state based on ARB_vp enabled or not. */
2154 r200PointParameter( ctx, GL_POINT_DISTANCE_ATTENUATION, NULL );
2155 r200Fogfv( ctx, GL_FOG_COORD_SRC, NULL );
2156 break;
2157
2158 case GL_VERTEX_PROGRAM_POINT_SIZE_ARB:
2159 r200PointParameter( ctx, GL_POINT_DISTANCE_ATTENUATION, NULL );
2160 break;
2161
2162 case GL_FRAGMENT_SHADER_ATI:
2163 if ( !state ) {
2164 /* restore normal tex env colors and make sure tex env combine will get updated
2165 mark env atoms dirty (as their data was overwritten by afs even
2166 if they didn't change) and restore tex coord routing */
2167 GLuint unit;
2168 for (unit = 0; unit < R200_MAX_TEXTURE_UNITS; unit++) {
2169 R200_STATECHANGE( rmesa, pix[unit] );
2170 R200_STATECHANGE( rmesa, tex[unit] );
2171 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] &=
2172 ~(R200_TXFORMAT_ST_ROUTE_MASK | R200_TXFORMAT_LOOKUP_DISABLE);
2173 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] |= unit << R200_TXFORMAT_ST_ROUTE_SHIFT;
2174 /* need to guard this with drmSupportsFragmentShader? Should never get here if
2175 we don't announce ATI_fs, right? */
2176 rmesa->hw.tex[unit].cmd[TEX_PP_TXMULTI_CTL] = 0;
2177 }
2178 R200_STATECHANGE( rmesa, cst );
2179 R200_STATECHANGE( rmesa, tf );
2180 rmesa->hw.cst.cmd[CST_PP_CNTL_X] = 0;
2181 }
2182 else {
2183 /* need to mark this dirty as pix/tf atoms have overwritten the data
2184 even if the data in the atoms didn't change */
2185 R200_STATECHANGE( rmesa, atf );
2186 R200_STATECHANGE( rmesa, afs[1] );
2187 /* everything else picked up in r200UpdateTextureState hopefully */
2188 }
2189 break;
2190 default:
2191 return;
2192 }
2193 }
2194
2195
2196 void r200LightingSpaceChange( GLcontext *ctx )
2197 {
2198 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2199 GLboolean tmp;
2200
2201 if (R200_DEBUG & DEBUG_STATE)
2202 fprintf(stderr, "%s %d BEFORE %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
2203 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]);
2204
2205 if (ctx->_NeedEyeCoords)
2206 tmp = ctx->Transform.RescaleNormals;
2207 else
2208 tmp = !ctx->Transform.RescaleNormals;
2209
2210 R200_STATECHANGE( rmesa, tcl );
2211 if ( tmp ) {
2212 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_RESCALE_NORMALS;
2213 } else {
2214 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS;
2215 }
2216
2217 if (R200_DEBUG & DEBUG_STATE)
2218 fprintf(stderr, "%s %d AFTER %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
2219 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]);
2220 }
2221
2222 /* =============================================================
2223 * Deferred state management - matrices, textures, other?
2224 */
2225
2226
2227
2228
2229 static void upload_matrix( r200ContextPtr rmesa, GLfloat *src, int idx )
2230 {
2231 float *dest = ((float *)R200_DB_STATE( mat[idx] ))+MAT_ELT_0;
2232 int i;
2233
2234
2235 for (i = 0 ; i < 4 ; i++) {
2236 *dest++ = src[i];
2237 *dest++ = src[i+4];
2238 *dest++ = src[i+8];
2239 *dest++ = src[i+12];
2240 }
2241
2242 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2243 }
2244
2245 static void upload_matrix_t( r200ContextPtr rmesa, const GLfloat *src, int idx )
2246 {
2247 float *dest = ((float *)R200_DB_STATE( mat[idx] ))+MAT_ELT_0;
2248 memcpy(dest, src, 16*sizeof(float));
2249 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2250 }
2251
2252
2253 static void update_texturematrix( GLcontext *ctx )
2254 {
2255 r200ContextPtr rmesa = R200_CONTEXT( ctx );
2256 GLuint tpc = rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0];
2257 GLuint compsel = rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL];
2258 int unit;
2259
2260 if (R200_DEBUG & DEBUG_STATE)
2261 fprintf(stderr, "%s before COMPSEL: %x\n", __FUNCTION__,
2262 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]);
2263
2264 rmesa->TexMatEnabled = 0;
2265 rmesa->TexMatCompSel = 0;
2266
2267 for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++) {
2268 if (!ctx->Texture.Unit[unit]._ReallyEnabled)
2269 continue;
2270
2271 if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY) {
2272 rmesa->TexMatEnabled |= (R200_TEXGEN_TEXMAT_0_ENABLE|
2273 R200_TEXMAT_0_ENABLE) << unit;
2274
2275 rmesa->TexMatCompSel |= R200_OUTPUT_TEX_0 << unit;
2276
2277 if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) {
2278 /* Need to preconcatenate any active texgen
2279 * obj/eyeplane matrices:
2280 */
2281 _math_matrix_mul_matrix( &rmesa->tmpmat,
2282 ctx->TextureMatrixStack[unit].Top,
2283 &rmesa->TexGenMatrix[unit] );
2284 upload_matrix( rmesa, rmesa->tmpmat.m, R200_MTX_TEX0+unit );
2285 }
2286 else {
2287 upload_matrix( rmesa, ctx->TextureMatrixStack[unit].Top->m,
2288 R200_MTX_TEX0+unit );
2289 }
2290 }
2291 else if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) {
2292 upload_matrix( rmesa, rmesa->TexGenMatrix[unit].m,
2293 R200_MTX_TEX0+unit );
2294 }
2295 }
2296
2297 tpc = (rmesa->TexMatEnabled | rmesa->TexGenEnabled);
2298 if (tpc != rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0]) {
2299 R200_STATECHANGE(rmesa, tcg);
2300 rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0] = tpc;
2301 }
2302
2303 compsel &= ~R200_OUTPUT_TEX_MASK;
2304 compsel |= rmesa->TexMatCompSel | rmesa->TexGenCompSel;
2305 if (compsel != rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]) {
2306 R200_STATECHANGE(rmesa, vtx);
2307 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] = compsel;
2308 }
2309 }
2310
2311
2312
2313 /**
2314 * Tell the card where to render (offset, pitch).
2315 * Effected by glDrawBuffer, etc
2316 */
2317 void
2318 r200UpdateDrawBuffer(GLcontext *ctx)
2319 {
2320 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2321 struct gl_framebuffer *fb = ctx->DrawBuffer;
2322 struct radeon_renderbuffer *rrb;
2323
2324 if (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) {
2325 /* draw to front */
2326 rrb = (void *) fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
2327 } else if (fb->_ColorDrawBufferIndexes[0] == BUFFER_BACK_LEFT) {
2328 /* draw to back */
2329 rrb = (void *) fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
2330 } else {
2331 /* drawing to multiple buffers, or none */
2332 return;
2333 }
2334
2335 assert(rrb);
2336 assert(rrb->pitch);
2337
2338 R200_STATECHANGE( rmesa, ctx );
2339
2340 #if 0
2341 /* Note: we used the (possibly) page-flipped values */
2342 rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET]
2343 = ((rrb->flippedOffset + rmesa->radeon.radeonScreen->fbLocation)
2344 & R200_COLOROFFSET_MASK);
2345 rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = drb->flippedPitch;
2346 if (rmesa->radeon.sarea->tiling_enabled) {
2347 rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] |= R200_COLOR_TILE_ENABLE;
2348 }
2349 #endif
2350 }
2351
2352 static GLboolean r200ValidateBuffers(GLcontext *ctx)
2353 {
2354 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2355 struct radeon_cs_space_check bos[8];
2356 struct radeon_renderbuffer *rrb;
2357 int num_bo = 0;
2358 int i;
2359 int flushed = 0, ret;
2360 again:
2361 num_bo = 0;
2362
2363 rrb = radeon_get_colorbuffer(&rmesa->radeon);
2364 /* color buffer */
2365 if (rrb && rrb->bo) {
2366 bos[num_bo].bo = rrb->bo;
2367 bos[num_bo].read_domains = 0;
2368 bos[num_bo].write_domain = RADEON_GEM_DOMAIN_VRAM;
2369 bos[num_bo].new_accounted = 0;
2370 num_bo++;
2371 }
2372
2373 /* depth buffer */
2374 rrb = radeon_get_depthbuffer(&rmesa->radeon);
2375 /* color buffer */
2376 if (rrb && rrb->bo) {
2377 bos[num_bo].bo = rrb->bo;
2378 bos[num_bo].read_domains = 0;
2379 bos[num_bo].write_domain = RADEON_GEM_DOMAIN_VRAM;
2380 bos[num_bo].new_accounted = 0;
2381 num_bo++;
2382 }
2383
2384 for (i = 0; i < ctx->Const.MaxTextureImageUnits; ++i) {
2385 radeonTexObj *t;
2386
2387 if (!ctx->Texture.Unit[i]._ReallyEnabled)
2388 continue;
2389
2390 t = radeon_tex_obj(ctx->Texture.Unit[i]._Current);
2391 bos[num_bo].bo = t->mt->bo;
2392 bos[num_bo].read_domains = RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM;
2393 bos[num_bo].write_domain = 0;
2394 bos[num_bo].new_accounted = 0;
2395 num_bo++;
2396 }
2397
2398 ret = radeon_cs_space_check(rmesa->radeon.cmdbuf.cs, bos, num_bo);
2399 if (ret == RADEON_CS_SPACE_OP_TO_BIG)
2400 return GL_FALSE;
2401 if (ret == RADEON_CS_SPACE_FLUSH) {
2402 r200Flush(ctx);
2403 if (flushed)
2404 return GL_FALSE;
2405 flushed = 1;
2406 goto again;
2407 }
2408 return GL_TRUE;
2409 }
2410
2411 GLboolean r200ValidateState( GLcontext *ctx )
2412 {
2413 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2414 GLuint new_state = rmesa->radeon.NewGLState;
2415
2416 if (new_state & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) {
2417 r200UpdateDrawBuffer(ctx);
2418 }
2419
2420 if (new_state & (_NEW_TEXTURE | _NEW_PROGRAM)) {
2421 r200UpdateTextureState( ctx );
2422 new_state |= rmesa->radeon.NewGLState; /* may add TEXTURE_MATRIX */
2423 r200UpdateLocalViewer( ctx );
2424 }
2425
2426 /* we need to do a space check here */
2427 if (!r200ValidateBuffers(ctx))
2428 return GL_FALSE;
2429
2430 /* FIXME: don't really need most of these when vertex progs are enabled */
2431
2432 /* Need an event driven matrix update?
2433 */
2434 if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION))
2435 upload_matrix( rmesa, ctx->_ModelProjectMatrix.m, R200_MTX_MVP );
2436
2437 /* Need these for lighting (shouldn't upload otherwise)
2438 */
2439 if (new_state & (_NEW_MODELVIEW)) {
2440 upload_matrix( rmesa, ctx->ModelviewMatrixStack.Top->m, R200_MTX_MV );
2441 upload_matrix_t( rmesa, ctx->ModelviewMatrixStack.Top->inv, R200_MTX_IMV );
2442 }
2443
2444 /* Does this need to be triggered on eg. modelview for
2445 * texgen-derived objplane/eyeplane matrices?
2446 */
2447 if (new_state & (_NEW_TEXTURE|_NEW_TEXTURE_MATRIX)) {
2448 update_texturematrix( ctx );
2449 }
2450
2451 if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW|_MESA_NEW_NEED_EYE_COORDS)) {
2452 update_light( ctx );
2453 }
2454
2455 /* emit all active clip planes if projection matrix changes.
2456 */
2457 if (new_state & (_NEW_PROJECTION)) {
2458 if (ctx->Transform.ClipPlanesEnabled)
2459 r200UpdateClipPlanes( ctx );
2460 }
2461
2462 if (new_state & (_NEW_PROGRAM|
2463 /* need to test for pretty much anything due to possible parameter bindings */
2464 _NEW_MODELVIEW|_NEW_PROJECTION|_NEW_TRANSFORM|
2465 _NEW_LIGHT|_NEW_TEXTURE|_NEW_TEXTURE_MATRIX|
2466 _NEW_FOG|_NEW_POINT|_NEW_TRACK_MATRIX)) {
2467 if (ctx->VertexProgram._Enabled) {
2468 r200SetupVertexProg( ctx );
2469 }
2470 else TCL_FALLBACK(ctx, R200_TCL_FALLBACK_VERTEX_PROGRAM, 0);
2471 }
2472
2473 rmesa->radeon.NewGLState = 0;
2474 return GL_TRUE;
2475 }
2476
2477
2478 static void r200InvalidateState( GLcontext *ctx, GLuint new_state )
2479 {
2480 _swrast_InvalidateState( ctx, new_state );
2481 _swsetup_InvalidateState( ctx, new_state );
2482 _vbo_InvalidateState( ctx, new_state );
2483 _tnl_InvalidateState( ctx, new_state );
2484 _ae_invalidate_state( ctx, new_state );
2485 R200_CONTEXT(ctx)->radeon.NewGLState |= new_state;
2486 }
2487
2488 /* A hack. The r200 can actually cope just fine with materials
2489 * between begin/ends, so fix this.
2490 * Should map to inputs just like the generic vertex arrays for vertex progs.
2491 * In theory there could still be too many and we'd still need a fallback.
2492 */
2493 static GLboolean check_material( GLcontext *ctx )
2494 {
2495 TNLcontext *tnl = TNL_CONTEXT(ctx);
2496 GLint i;
2497
2498 for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT;
2499 i < _TNL_ATTRIB_MAT_BACK_INDEXES;
2500 i++)
2501 if (tnl->vb.AttribPtr[i] &&
2502 tnl->vb.AttribPtr[i]->stride)
2503 return GL_TRUE;
2504
2505 return GL_FALSE;
2506 }
2507
2508 static void r200WrapRunPipeline( GLcontext *ctx )
2509 {
2510 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2511 GLboolean has_material;
2512
2513 if (0)
2514 fprintf(stderr, "%s, newstate: %x\n", __FUNCTION__, rmesa->radeon.NewGLState);
2515
2516 /* Validate state:
2517 */
2518 if (rmesa->radeon.NewGLState)
2519 if (!r200ValidateState( ctx ))
2520 FALLBACK(rmesa, RADEON_FALLBACK_TEXTURE, GL_TRUE);
2521
2522 has_material = !ctx->VertexProgram._Enabled && ctx->Light.Enabled && check_material( ctx );
2523
2524 if (has_material) {
2525 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_TRUE );
2526 }
2527
2528 /* Run the pipeline.
2529 */
2530 _tnl_run_pipeline( ctx );
2531
2532 if (has_material) {
2533 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_FALSE );
2534 }
2535 }
2536
2537
2538 /* Initialize the driver's state functions.
2539 */
2540 void r200InitStateFuncs( struct dd_function_table *functions )
2541 {
2542 functions->UpdateState = r200InvalidateState;
2543 functions->LightingSpaceChange = r200LightingSpaceChange;
2544
2545 functions->DrawBuffer = r200DrawBuffer;
2546 functions->ReadBuffer = r200ReadBuffer;
2547
2548 functions->AlphaFunc = r200AlphaFunc;
2549 functions->BlendColor = r200BlendColor;
2550 functions->BlendEquationSeparate = r200BlendEquationSeparate;
2551 functions->BlendFuncSeparate = r200BlendFuncSeparate;
2552 functions->ClearColor = r200ClearColor;
2553 functions->ClearDepth = r200ClearDepth;
2554 functions->ClearIndex = NULL;
2555 functions->ClearStencil = r200ClearStencil;
2556 functions->ClipPlane = r200ClipPlane;
2557 functions->ColorMask = r200ColorMask;
2558 functions->CullFace = r200CullFace;
2559 functions->DepthFunc = r200DepthFunc;
2560 functions->DepthMask = r200DepthMask;
2561 functions->DepthRange = r200DepthRange;
2562 functions->Enable = r200Enable;
2563 functions->Fogfv = r200Fogfv;
2564 functions->FrontFace = r200FrontFace;
2565 functions->Hint = NULL;
2566 functions->IndexMask = NULL;
2567 functions->LightModelfv = r200LightModelfv;
2568 functions->Lightfv = r200Lightfv;
2569 functions->LineStipple = r200LineStipple;
2570 functions->LineWidth = r200LineWidth;
2571 functions->LogicOpcode = r200LogicOpCode;
2572 functions->PolygonMode = r200PolygonMode;
2573 functions->PolygonOffset = r200PolygonOffset;
2574 functions->PolygonStipple = r200PolygonStipple;
2575 functions->PointParameterfv = r200PointParameter;
2576 functions->PointSize = r200PointSize;
2577 functions->RenderMode = r200RenderMode;
2578 functions->Scissor = r200Scissor;
2579 functions->ShadeModel = r200ShadeModel;
2580 functions->StencilFuncSeparate = r200StencilFuncSeparate;
2581 functions->StencilMaskSeparate = r200StencilMaskSeparate;
2582 functions->StencilOpSeparate = r200StencilOpSeparate;
2583 functions->Viewport = r200Viewport;
2584 }
2585
2586
2587 void r200InitTnlFuncs( GLcontext *ctx )
2588 {
2589 TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange = r200UpdateMaterial;
2590 TNL_CONTEXT(ctx)->Driver.RunPipeline = r200WrapRunPipeline;
2591 }