r100/r200: fix front rendering issue.
[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 * Culling
529 */
530
531 static void r200CullFace( GLcontext *ctx, GLenum unused )
532 {
533 r200ContextPtr rmesa = R200_CONTEXT(ctx);
534 GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL];
535 GLuint t = rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL];
536
537 s |= R200_FFACE_SOLID | R200_BFACE_SOLID;
538 t &= ~(R200_CULL_FRONT | R200_CULL_BACK);
539
540 if ( ctx->Polygon.CullFlag ) {
541 switch ( ctx->Polygon.CullFaceMode ) {
542 case GL_FRONT:
543 s &= ~R200_FFACE_SOLID;
544 t |= R200_CULL_FRONT;
545 break;
546 case GL_BACK:
547 s &= ~R200_BFACE_SOLID;
548 t |= R200_CULL_BACK;
549 break;
550 case GL_FRONT_AND_BACK:
551 s &= ~(R200_FFACE_SOLID | R200_BFACE_SOLID);
552 t |= (R200_CULL_FRONT | R200_CULL_BACK);
553 break;
554 }
555 }
556
557 if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) {
558 R200_STATECHANGE(rmesa, set );
559 rmesa->hw.set.cmd[SET_SE_CNTL] = s;
560 }
561
562 if ( rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] != t ) {
563 R200_STATECHANGE(rmesa, tcl );
564 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] = t;
565 }
566 }
567
568 static void r200FrontFace( GLcontext *ctx, GLenum mode )
569 {
570 r200ContextPtr rmesa = R200_CONTEXT(ctx);
571
572 R200_STATECHANGE( rmesa, set );
573 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_FFACE_CULL_DIR_MASK;
574
575 R200_STATECHANGE( rmesa, tcl );
576 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_CULL_FRONT_IS_CCW;
577
578 switch ( mode ) {
579 case GL_CW:
580 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_FFACE_CULL_CW;
581 break;
582 case GL_CCW:
583 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_FFACE_CULL_CCW;
584 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_CULL_FRONT_IS_CCW;
585 break;
586 }
587 }
588
589 /* =============================================================
590 * Point state
591 */
592 static void r200PointSize( GLcontext *ctx, GLfloat size )
593 {
594 r200ContextPtr rmesa = R200_CONTEXT(ctx);
595 GLfloat *fcmd = (GLfloat *)rmesa->hw.ptp.cmd;
596
597 R200_STATECHANGE( rmesa, cst );
598 R200_STATECHANGE( rmesa, ptp );
599 rmesa->hw.cst.cmd[CST_RE_POINTSIZE] &= ~0xffff;
600 rmesa->hw.cst.cmd[CST_RE_POINTSIZE] |= ((GLuint)(ctx->Point.Size * 16.0));
601 /* this is the size param of the point size calculation (point size reg value
602 is not used when calculation is active). */
603 fcmd[PTP_VPORT_SCALE_PTSIZE] = ctx->Point.Size;
604 }
605
606 static void r200PointParameter( GLcontext *ctx, GLenum pname, const GLfloat *params)
607 {
608 r200ContextPtr rmesa = R200_CONTEXT(ctx);
609 GLfloat *fcmd = (GLfloat *)rmesa->hw.ptp.cmd;
610
611 switch (pname) {
612 case GL_POINT_SIZE_MIN:
613 /* Can clamp both in tcl and setup - just set both (as does fglrx) */
614 R200_STATECHANGE( rmesa, lin );
615 R200_STATECHANGE( rmesa, ptp );
616 rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] &= 0xffff;
617 rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] |= (GLuint)(ctx->Point.MinSize * 16.0) << 16;
618 fcmd[PTP_CLAMP_MIN] = ctx->Point.MinSize;
619 break;
620 case GL_POINT_SIZE_MAX:
621 R200_STATECHANGE( rmesa, cst );
622 R200_STATECHANGE( rmesa, ptp );
623 rmesa->hw.cst.cmd[CST_RE_POINTSIZE] &= 0xffff;
624 rmesa->hw.cst.cmd[CST_RE_POINTSIZE] |= (GLuint)(ctx->Point.MaxSize * 16.0) << 16;
625 fcmd[PTP_CLAMP_MAX] = ctx->Point.MaxSize;
626 break;
627 case GL_POINT_DISTANCE_ATTENUATION:
628 R200_STATECHANGE( rmesa, vtx );
629 R200_STATECHANGE( rmesa, spr );
630 R200_STATECHANGE( rmesa, ptp );
631 GLfloat *fcmd = (GLfloat *)rmesa->hw.ptp.cmd;
632 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] &=
633 ~(R200_PS_MULT_MASK | R200_PS_LIN_ATT_ZERO | R200_PS_SE_SEL_STATE);
634 /* can't rely on ctx->Point._Attenuated here and test for NEW_POINT in
635 r200ValidateState looks like overkill */
636 if (ctx->Point.Params[0] != 1.0 ||
637 ctx->Point.Params[1] != 0.0 ||
638 ctx->Point.Params[2] != 0.0 ||
639 (ctx->VertexProgram.Enabled && ctx->VertexProgram.PointSizeEnabled)) {
640 /* all we care for vp would be the ps_se_sel_state setting */
641 fcmd[PTP_ATT_CONST_QUAD] = ctx->Point.Params[2];
642 fcmd[PTP_ATT_CONST_LIN] = ctx->Point.Params[1];
643 fcmd[PTP_ATT_CONST_CON] = ctx->Point.Params[0];
644 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |= R200_PS_MULT_ATTENCONST;
645 if (ctx->Point.Params[1] == 0.0)
646 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |= R200_PS_LIN_ATT_ZERO;
647 /* FIXME: setting this here doesn't look quite ok - we only want to do
648 that if we're actually drawing points probably */
649 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_PT_SIZE;
650 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |= R200_VTX_POINT_SIZE;
651 }
652 else {
653 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |=
654 R200_PS_SE_SEL_STATE | R200_PS_MULT_CONST;
655 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] &= ~R200_OUTPUT_PT_SIZE;
656 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] &= ~R200_VTX_POINT_SIZE;
657 }
658 break;
659 case GL_POINT_FADE_THRESHOLD_SIZE:
660 /* don't support multisampling, so doesn't matter. */
661 break;
662 /* can't do these but don't need them.
663 case GL_POINT_SPRITE_R_MODE_NV:
664 case GL_POINT_SPRITE_COORD_ORIGIN: */
665 default:
666 fprintf(stderr, "bad pname parameter in r200PointParameter\n");
667 return;
668 }
669 }
670
671 /* =============================================================
672 * Line state
673 */
674 static void r200LineWidth( GLcontext *ctx, GLfloat widthf )
675 {
676 r200ContextPtr rmesa = R200_CONTEXT(ctx);
677
678 R200_STATECHANGE( rmesa, lin );
679 R200_STATECHANGE( rmesa, set );
680
681 /* Line width is stored in U6.4 format.
682 * Same min/max limits for AA, non-AA lines.
683 */
684 rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] &= ~0xffff;
685 rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] |= (GLuint)
686 (CLAMP(widthf, ctx->Const.MinLineWidth, ctx->Const.MaxLineWidth) * 16.0);
687
688 if ( widthf > 1.0 ) {
689 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_WIDELINE_ENABLE;
690 } else {
691 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_WIDELINE_ENABLE;
692 }
693 }
694
695 static void r200LineStipple( GLcontext *ctx, GLint factor, GLushort pattern )
696 {
697 r200ContextPtr rmesa = R200_CONTEXT(ctx);
698
699 R200_STATECHANGE( rmesa, lin );
700 rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] =
701 ((((GLuint)factor & 0xff) << 16) | ((GLuint)pattern));
702 }
703
704
705 /* =============================================================
706 * Masks
707 */
708 static void r200ColorMask( GLcontext *ctx,
709 GLboolean r, GLboolean g,
710 GLboolean b, GLboolean a )
711 {
712 r200ContextPtr rmesa = R200_CONTEXT(ctx);
713 GLuint mask = radeonPackColor( rmesa->radeon.radeonScreen->cpp,
714 ctx->Color.ColorMask[RCOMP],
715 ctx->Color.ColorMask[GCOMP],
716 ctx->Color.ColorMask[BCOMP],
717 ctx->Color.ColorMask[ACOMP] );
718
719 GLuint flag = rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] & ~R200_PLANE_MASK_ENABLE;
720
721 if (!(r && g && b && a))
722 flag |= R200_PLANE_MASK_ENABLE;
723
724 if ( rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] != flag ) {
725 R200_STATECHANGE( rmesa, ctx );
726 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = flag;
727 }
728
729 if ( rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] != mask ) {
730 R200_STATECHANGE( rmesa, msk );
731 rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] = mask;
732 }
733 }
734
735
736 /* =============================================================
737 * Polygon state
738 */
739
740 static void r200PolygonOffset( GLcontext *ctx,
741 GLfloat factor, GLfloat units )
742 {
743 r200ContextPtr rmesa = R200_CONTEXT(ctx);
744 float_ui32_type constant = { units * rmesa->radeon.state.depth.scale };
745 float_ui32_type factoru = { factor };
746
747 /* factor *= 2; */
748 /* constant *= 2; */
749
750 /* fprintf(stderr, "%s f:%f u:%f\n", __FUNCTION__, factor, constant); */
751
752 R200_STATECHANGE( rmesa, zbs );
753 rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_FACTOR] = factoru.ui32;
754 rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_CONSTANT] = constant.ui32;
755 }
756
757 static void r200PolygonStipple( GLcontext *ctx, const GLubyte *mask )
758 {
759 r200ContextPtr rmesa = R200_CONTEXT(ctx);
760 GLuint i;
761 drm_radeon_stipple_t stipple;
762
763 /* Must flip pattern upside down.
764 */
765 for ( i = 0 ; i < 32 ; i++ ) {
766 rmesa->state.stipple.mask[31 - i] = ((GLuint *) mask)[i];
767 }
768
769 /* TODO: push this into cmd mechanism
770 */
771 radeon_firevertices(&rmesa->radeon);
772 LOCK_HARDWARE( &rmesa->radeon );
773
774 /* FIXME: Use window x,y offsets into stipple RAM.
775 */
776 stipple.mask = rmesa->state.stipple.mask;
777 drmCommandWrite( rmesa->radeon.dri.fd, DRM_RADEON_STIPPLE,
778 &stipple, sizeof(stipple) );
779 UNLOCK_HARDWARE( &rmesa->radeon );
780 }
781
782 static void r200PolygonMode( GLcontext *ctx, GLenum face, GLenum mode )
783 {
784 r200ContextPtr rmesa = R200_CONTEXT(ctx);
785 GLboolean flag = (ctx->_TriangleCaps & DD_TRI_UNFILLED) != 0;
786
787 /* Can't generally do unfilled via tcl, but some good special
788 * cases work.
789 */
790 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_UNFILLED, flag);
791 if (rmesa->radeon.TclFallback) {
792 r200ChooseRenderState( ctx );
793 r200ChooseVertexState( ctx );
794 }
795 }
796
797
798 /* =============================================================
799 * Rendering attributes
800 *
801 * We really don't want to recalculate all this every time we bind a
802 * texture. These things shouldn't change all that often, so it makes
803 * sense to break them out of the core texture state update routines.
804 */
805
806 /* Examine lighting and texture state to determine if separate specular
807 * should be enabled.
808 */
809 static void r200UpdateSpecular( GLcontext *ctx )
810 {
811 r200ContextPtr rmesa = R200_CONTEXT(ctx);
812 uint32_t p = rmesa->hw.ctx.cmd[CTX_PP_CNTL];
813
814 R200_STATECHANGE( rmesa, tcl );
815 R200_STATECHANGE( rmesa, vtx );
816
817 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] &= ~(3<<R200_VTX_COLOR_0_SHIFT);
818 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] &= ~(3<<R200_VTX_COLOR_1_SHIFT);
819 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] &= ~R200_OUTPUT_COLOR_0;
820 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] &= ~R200_OUTPUT_COLOR_1;
821 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_LIGHTING_ENABLE;
822
823 p &= ~R200_SPECULAR_ENABLE;
824
825 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_DIFFUSE_SPECULAR_COMBINE;
826
827
828 if (ctx->Light.Enabled &&
829 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) {
830 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
831 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT) |
832 (R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT));
833 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_0;
834 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_1;
835 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHTING_ENABLE;
836 p |= R200_SPECULAR_ENABLE;
837 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &=
838 ~R200_DIFFUSE_SPECULAR_COMBINE;
839 }
840 else if (ctx->Light.Enabled) {
841 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
842 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT));
843 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_0;
844 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHTING_ENABLE;
845 } else if (ctx->Fog.ColorSumEnabled ) {
846 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
847 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT) |
848 (R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT));
849 p |= R200_SPECULAR_ENABLE;
850 } else {
851 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
852 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT));
853 }
854
855 if (ctx->Fog.Enabled) {
856 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
857 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT));
858 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_1;
859 }
860
861 if ( rmesa->hw.ctx.cmd[CTX_PP_CNTL] != p ) {
862 R200_STATECHANGE( rmesa, ctx );
863 rmesa->hw.ctx.cmd[CTX_PP_CNTL] = p;
864 }
865
866 /* Update vertex/render formats
867 */
868 if (rmesa->radeon.TclFallback) {
869 r200ChooseRenderState( ctx );
870 r200ChooseVertexState( ctx );
871 }
872 }
873
874
875 /* =============================================================
876 * Materials
877 */
878
879
880 /* Update on colormaterial, material emmissive/ambient,
881 * lightmodel.globalambient
882 */
883 static void update_global_ambient( GLcontext *ctx )
884 {
885 r200ContextPtr rmesa = R200_CONTEXT(ctx);
886 float *fcmd = (float *)R200_DB_STATE( glt );
887
888 /* Need to do more if both emmissive & ambient are PREMULT:
889 * I believe this is not nessary when using source_material. This condition thus
890 * will never happen currently, and the function has no dependencies on materials now
891 */
892 if ((rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1] &
893 ((3 << R200_FRONT_EMISSIVE_SOURCE_SHIFT) |
894 (3 << R200_FRONT_AMBIENT_SOURCE_SHIFT))) == 0)
895 {
896 COPY_3V( &fcmd[GLT_RED],
897 ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION]);
898 ACC_SCALE_3V( &fcmd[GLT_RED],
899 ctx->Light.Model.Ambient,
900 ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT]);
901 }
902 else
903 {
904 COPY_3V( &fcmd[GLT_RED], ctx->Light.Model.Ambient );
905 }
906
907 R200_DB_STATECHANGE(rmesa, &rmesa->hw.glt);
908 }
909
910 /* Update on change to
911 * - light[p].colors
912 * - light[p].enabled
913 */
914 static void update_light_colors( GLcontext *ctx, GLuint p )
915 {
916 struct gl_light *l = &ctx->Light.Light[p];
917
918 /* fprintf(stderr, "%s\n", __FUNCTION__); */
919
920 if (l->Enabled) {
921 r200ContextPtr rmesa = R200_CONTEXT(ctx);
922 float *fcmd = (float *)R200_DB_STATE( lit[p] );
923
924 COPY_4V( &fcmd[LIT_AMBIENT_RED], l->Ambient );
925 COPY_4V( &fcmd[LIT_DIFFUSE_RED], l->Diffuse );
926 COPY_4V( &fcmd[LIT_SPECULAR_RED], l->Specular );
927
928 R200_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
929 }
930 }
931
932 static void r200ColorMaterial( GLcontext *ctx, GLenum face, GLenum mode )
933 {
934 r200ContextPtr rmesa = R200_CONTEXT(ctx);
935 GLuint light_model_ctl1 = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1];
936 light_model_ctl1 &= ~((0xf << R200_FRONT_EMISSIVE_SOURCE_SHIFT) |
937 (0xf << R200_FRONT_AMBIENT_SOURCE_SHIFT) |
938 (0xf << R200_FRONT_DIFFUSE_SOURCE_SHIFT) |
939 (0xf << R200_FRONT_SPECULAR_SOURCE_SHIFT) |
940 (0xf << R200_BACK_EMISSIVE_SOURCE_SHIFT) |
941 (0xf << R200_BACK_AMBIENT_SOURCE_SHIFT) |
942 (0xf << R200_BACK_DIFFUSE_SOURCE_SHIFT) |
943 (0xf << R200_BACK_SPECULAR_SOURCE_SHIFT));
944
945 if (ctx->Light.ColorMaterialEnabled) {
946 GLuint mask = ctx->Light.ColorMaterialBitmask;
947
948 if (mask & MAT_BIT_FRONT_EMISSION) {
949 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
950 R200_FRONT_EMISSIVE_SOURCE_SHIFT);
951 }
952 else
953 light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 <<
954 R200_FRONT_EMISSIVE_SOURCE_SHIFT);
955
956 if (mask & MAT_BIT_FRONT_AMBIENT) {
957 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
958 R200_FRONT_AMBIENT_SOURCE_SHIFT);
959 }
960 else
961 light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 <<
962 R200_FRONT_AMBIENT_SOURCE_SHIFT);
963
964 if (mask & MAT_BIT_FRONT_DIFFUSE) {
965 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
966 R200_FRONT_DIFFUSE_SOURCE_SHIFT);
967 }
968 else
969 light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 <<
970 R200_FRONT_DIFFUSE_SOURCE_SHIFT);
971
972 if (mask & MAT_BIT_FRONT_SPECULAR) {
973 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
974 R200_FRONT_SPECULAR_SOURCE_SHIFT);
975 }
976 else {
977 light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 <<
978 R200_FRONT_SPECULAR_SOURCE_SHIFT);
979 }
980
981 if (mask & MAT_BIT_BACK_EMISSION) {
982 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
983 R200_BACK_EMISSIVE_SOURCE_SHIFT);
984 }
985
986 else light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 <<
987 R200_BACK_EMISSIVE_SOURCE_SHIFT);
988
989 if (mask & MAT_BIT_BACK_AMBIENT) {
990 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
991 R200_BACK_AMBIENT_SOURCE_SHIFT);
992 }
993 else light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 <<
994 R200_BACK_AMBIENT_SOURCE_SHIFT);
995
996 if (mask & MAT_BIT_BACK_DIFFUSE) {
997 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
998 R200_BACK_DIFFUSE_SOURCE_SHIFT);
999 }
1000 else light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 <<
1001 R200_BACK_DIFFUSE_SOURCE_SHIFT);
1002
1003 if (mask & MAT_BIT_BACK_SPECULAR) {
1004 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
1005 R200_BACK_SPECULAR_SOURCE_SHIFT);
1006 }
1007 else {
1008 light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 <<
1009 R200_BACK_SPECULAR_SOURCE_SHIFT);
1010 }
1011 }
1012 else {
1013 /* Default to SOURCE_MATERIAL:
1014 */
1015 light_model_ctl1 |=
1016 (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_EMISSIVE_SOURCE_SHIFT) |
1017 (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_AMBIENT_SOURCE_SHIFT) |
1018 (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_DIFFUSE_SOURCE_SHIFT) |
1019 (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_SPECULAR_SOURCE_SHIFT) |
1020 (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_EMISSIVE_SOURCE_SHIFT) |
1021 (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_AMBIENT_SOURCE_SHIFT) |
1022 (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_DIFFUSE_SOURCE_SHIFT) |
1023 (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_SPECULAR_SOURCE_SHIFT);
1024 }
1025
1026 if (light_model_ctl1 != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1]) {
1027 R200_STATECHANGE( rmesa, tcl );
1028 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1] = light_model_ctl1;
1029 }
1030
1031
1032 }
1033
1034 void r200UpdateMaterial( GLcontext *ctx )
1035 {
1036 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1037 GLfloat (*mat)[4] = ctx->Light.Material.Attrib;
1038 GLfloat *fcmd = (GLfloat *)R200_DB_STATE( mtl[0] );
1039 GLfloat *fcmd2 = (GLfloat *)R200_DB_STATE( mtl[1] );
1040 GLuint mask = ~0;
1041
1042 /* Might be possible and faster to update everything unconditionally? */
1043 if (ctx->Light.ColorMaterialEnabled)
1044 mask &= ~ctx->Light.ColorMaterialBitmask;
1045
1046 if (R200_DEBUG & DEBUG_STATE)
1047 fprintf(stderr, "%s\n", __FUNCTION__);
1048
1049 if (mask & MAT_BIT_FRONT_EMISSION) {
1050 fcmd[MTL_EMMISSIVE_RED] = mat[MAT_ATTRIB_FRONT_EMISSION][0];
1051 fcmd[MTL_EMMISSIVE_GREEN] = mat[MAT_ATTRIB_FRONT_EMISSION][1];
1052 fcmd[MTL_EMMISSIVE_BLUE] = mat[MAT_ATTRIB_FRONT_EMISSION][2];
1053 fcmd[MTL_EMMISSIVE_ALPHA] = mat[MAT_ATTRIB_FRONT_EMISSION][3];
1054 }
1055 if (mask & MAT_BIT_FRONT_AMBIENT) {
1056 fcmd[MTL_AMBIENT_RED] = mat[MAT_ATTRIB_FRONT_AMBIENT][0];
1057 fcmd[MTL_AMBIENT_GREEN] = mat[MAT_ATTRIB_FRONT_AMBIENT][1];
1058 fcmd[MTL_AMBIENT_BLUE] = mat[MAT_ATTRIB_FRONT_AMBIENT][2];
1059 fcmd[MTL_AMBIENT_ALPHA] = mat[MAT_ATTRIB_FRONT_AMBIENT][3];
1060 }
1061 if (mask & MAT_BIT_FRONT_DIFFUSE) {
1062 fcmd[MTL_DIFFUSE_RED] = mat[MAT_ATTRIB_FRONT_DIFFUSE][0];
1063 fcmd[MTL_DIFFUSE_GREEN] = mat[MAT_ATTRIB_FRONT_DIFFUSE][1];
1064 fcmd[MTL_DIFFUSE_BLUE] = mat[MAT_ATTRIB_FRONT_DIFFUSE][2];
1065 fcmd[MTL_DIFFUSE_ALPHA] = mat[MAT_ATTRIB_FRONT_DIFFUSE][3];
1066 }
1067 if (mask & MAT_BIT_FRONT_SPECULAR) {
1068 fcmd[MTL_SPECULAR_RED] = mat[MAT_ATTRIB_FRONT_SPECULAR][0];
1069 fcmd[MTL_SPECULAR_GREEN] = mat[MAT_ATTRIB_FRONT_SPECULAR][1];
1070 fcmd[MTL_SPECULAR_BLUE] = mat[MAT_ATTRIB_FRONT_SPECULAR][2];
1071 fcmd[MTL_SPECULAR_ALPHA] = mat[MAT_ATTRIB_FRONT_SPECULAR][3];
1072 }
1073 if (mask & MAT_BIT_FRONT_SHININESS) {
1074 fcmd[MTL_SHININESS] = mat[MAT_ATTRIB_FRONT_SHININESS][0];
1075 }
1076
1077 if (mask & MAT_BIT_BACK_EMISSION) {
1078 fcmd2[MTL_EMMISSIVE_RED] = mat[MAT_ATTRIB_BACK_EMISSION][0];
1079 fcmd2[MTL_EMMISSIVE_GREEN] = mat[MAT_ATTRIB_BACK_EMISSION][1];
1080 fcmd2[MTL_EMMISSIVE_BLUE] = mat[MAT_ATTRIB_BACK_EMISSION][2];
1081 fcmd2[MTL_EMMISSIVE_ALPHA] = mat[MAT_ATTRIB_BACK_EMISSION][3];
1082 }
1083 if (mask & MAT_BIT_BACK_AMBIENT) {
1084 fcmd2[MTL_AMBIENT_RED] = mat[MAT_ATTRIB_BACK_AMBIENT][0];
1085 fcmd2[MTL_AMBIENT_GREEN] = mat[MAT_ATTRIB_BACK_AMBIENT][1];
1086 fcmd2[MTL_AMBIENT_BLUE] = mat[MAT_ATTRIB_BACK_AMBIENT][2];
1087 fcmd2[MTL_AMBIENT_ALPHA] = mat[MAT_ATTRIB_BACK_AMBIENT][3];
1088 }
1089 if (mask & MAT_BIT_BACK_DIFFUSE) {
1090 fcmd2[MTL_DIFFUSE_RED] = mat[MAT_ATTRIB_BACK_DIFFUSE][0];
1091 fcmd2[MTL_DIFFUSE_GREEN] = mat[MAT_ATTRIB_BACK_DIFFUSE][1];
1092 fcmd2[MTL_DIFFUSE_BLUE] = mat[MAT_ATTRIB_BACK_DIFFUSE][2];
1093 fcmd2[MTL_DIFFUSE_ALPHA] = mat[MAT_ATTRIB_BACK_DIFFUSE][3];
1094 }
1095 if (mask & MAT_BIT_BACK_SPECULAR) {
1096 fcmd2[MTL_SPECULAR_RED] = mat[MAT_ATTRIB_BACK_SPECULAR][0];
1097 fcmd2[MTL_SPECULAR_GREEN] = mat[MAT_ATTRIB_BACK_SPECULAR][1];
1098 fcmd2[MTL_SPECULAR_BLUE] = mat[MAT_ATTRIB_BACK_SPECULAR][2];
1099 fcmd2[MTL_SPECULAR_ALPHA] = mat[MAT_ATTRIB_BACK_SPECULAR][3];
1100 }
1101 if (mask & MAT_BIT_BACK_SHININESS) {
1102 fcmd2[MTL_SHININESS] = mat[MAT_ATTRIB_BACK_SHININESS][0];
1103 }
1104
1105 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mtl[0] );
1106 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mtl[1] );
1107
1108 /* currently material changes cannot trigger a global ambient change, I believe this is correct
1109 update_global_ambient( ctx ); */
1110 }
1111
1112 /* _NEW_LIGHT
1113 * _NEW_MODELVIEW
1114 * _MESA_NEW_NEED_EYE_COORDS
1115 *
1116 * Uses derived state from mesa:
1117 * _VP_inf_norm
1118 * _h_inf_norm
1119 * _Position
1120 * _NormDirection
1121 * _ModelViewInvScale
1122 * _NeedEyeCoords
1123 * _EyeZDir
1124 *
1125 * which are calculated in light.c and are correct for the current
1126 * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
1127 * and _MESA_NEW_NEED_EYE_COORDS.
1128 */
1129 static void update_light( GLcontext *ctx )
1130 {
1131 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1132
1133 /* Have to check these, or have an automatic shortcircuit mechanism
1134 * to remove noop statechanges. (Or just do a better job on the
1135 * front end).
1136 */
1137 {
1138 GLuint tmp = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0];
1139
1140 if (ctx->_NeedEyeCoords)
1141 tmp &= ~R200_LIGHT_IN_MODELSPACE;
1142 else
1143 tmp |= R200_LIGHT_IN_MODELSPACE;
1144
1145 if (tmp != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0])
1146 {
1147 R200_STATECHANGE( rmesa, tcl );
1148 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] = tmp;
1149 }
1150 }
1151
1152 {
1153 GLfloat *fcmd = (GLfloat *)R200_DB_STATE( eye );
1154 fcmd[EYE_X] = ctx->_EyeZDir[0];
1155 fcmd[EYE_Y] = ctx->_EyeZDir[1];
1156 fcmd[EYE_Z] = - ctx->_EyeZDir[2];
1157 fcmd[EYE_RESCALE_FACTOR] = ctx->_ModelViewInvScale;
1158 R200_DB_STATECHANGE( rmesa, &rmesa->hw.eye );
1159 }
1160
1161
1162
1163 if (ctx->Light.Enabled) {
1164 GLint p;
1165 for (p = 0 ; p < MAX_LIGHTS; p++) {
1166 if (ctx->Light.Light[p].Enabled) {
1167 struct gl_light *l = &ctx->Light.Light[p];
1168 GLfloat *fcmd = (GLfloat *)R200_DB_STATE( lit[p] );
1169
1170 if (l->EyePosition[3] == 0.0) {
1171 COPY_3FV( &fcmd[LIT_POSITION_X], l->_VP_inf_norm );
1172 COPY_3FV( &fcmd[LIT_DIRECTION_X], l->_h_inf_norm );
1173 fcmd[LIT_POSITION_W] = 0;
1174 fcmd[LIT_DIRECTION_W] = 0;
1175 } else {
1176 COPY_4V( &fcmd[LIT_POSITION_X], l->_Position );
1177 fcmd[LIT_DIRECTION_X] = -l->_NormDirection[0];
1178 fcmd[LIT_DIRECTION_Y] = -l->_NormDirection[1];
1179 fcmd[LIT_DIRECTION_Z] = -l->_NormDirection[2];
1180 fcmd[LIT_DIRECTION_W] = 0;
1181 }
1182
1183 R200_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
1184 }
1185 }
1186 }
1187 }
1188
1189 static void r200Lightfv( GLcontext *ctx, GLenum light,
1190 GLenum pname, const GLfloat *params )
1191 {
1192 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1193 GLint p = light - GL_LIGHT0;
1194 struct gl_light *l = &ctx->Light.Light[p];
1195 GLfloat *fcmd = (GLfloat *)rmesa->hw.lit[p].cmd;
1196
1197
1198 switch (pname) {
1199 case GL_AMBIENT:
1200 case GL_DIFFUSE:
1201 case GL_SPECULAR:
1202 update_light_colors( ctx, p );
1203 break;
1204
1205 case GL_SPOT_DIRECTION:
1206 /* picked up in update_light */
1207 break;
1208
1209 case GL_POSITION: {
1210 /* positions picked up in update_light, but can do flag here */
1211 GLuint flag = (p&1)? R200_LIGHT_1_IS_LOCAL : R200_LIGHT_0_IS_LOCAL;
1212 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1213
1214 R200_STATECHANGE(rmesa, tcl);
1215 if (l->EyePosition[3] != 0.0F)
1216 rmesa->hw.tcl.cmd[idx] |= flag;
1217 else
1218 rmesa->hw.tcl.cmd[idx] &= ~flag;
1219 break;
1220 }
1221
1222 case GL_SPOT_EXPONENT:
1223 R200_STATECHANGE(rmesa, lit[p]);
1224 fcmd[LIT_SPOT_EXPONENT] = params[0];
1225 break;
1226
1227 case GL_SPOT_CUTOFF: {
1228 GLuint flag = (p&1) ? R200_LIGHT_1_IS_SPOT : R200_LIGHT_0_IS_SPOT;
1229 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1230
1231 R200_STATECHANGE(rmesa, lit[p]);
1232 fcmd[LIT_SPOT_CUTOFF] = l->_CosCutoff;
1233
1234 R200_STATECHANGE(rmesa, tcl);
1235 if (l->SpotCutoff != 180.0F)
1236 rmesa->hw.tcl.cmd[idx] |= flag;
1237 else
1238 rmesa->hw.tcl.cmd[idx] &= ~flag;
1239
1240 break;
1241 }
1242
1243 case GL_CONSTANT_ATTENUATION:
1244 R200_STATECHANGE(rmesa, lit[p]);
1245 fcmd[LIT_ATTEN_CONST] = params[0];
1246 if ( params[0] == 0.0 )
1247 fcmd[LIT_ATTEN_CONST_INV] = FLT_MAX;
1248 else
1249 fcmd[LIT_ATTEN_CONST_INV] = 1.0 / params[0];
1250 break;
1251 case GL_LINEAR_ATTENUATION:
1252 R200_STATECHANGE(rmesa, lit[p]);
1253 fcmd[LIT_ATTEN_LINEAR] = params[0];
1254 break;
1255 case GL_QUADRATIC_ATTENUATION:
1256 R200_STATECHANGE(rmesa, lit[p]);
1257 fcmd[LIT_ATTEN_QUADRATIC] = params[0];
1258 break;
1259 default:
1260 return;
1261 }
1262
1263 /* Set RANGE_ATTEN only when needed */
1264 switch (pname) {
1265 case GL_POSITION:
1266 case GL_CONSTANT_ATTENUATION:
1267 case GL_LINEAR_ATTENUATION:
1268 case GL_QUADRATIC_ATTENUATION: {
1269 GLuint *icmd = (GLuint *)R200_DB_STATE( tcl );
1270 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1271 GLuint atten_flag = ( p&1 ) ? R200_LIGHT_1_ENABLE_RANGE_ATTEN
1272 : R200_LIGHT_0_ENABLE_RANGE_ATTEN;
1273 GLuint atten_const_flag = ( p&1 ) ? R200_LIGHT_1_CONSTANT_RANGE_ATTEN
1274 : R200_LIGHT_0_CONSTANT_RANGE_ATTEN;
1275
1276 if ( l->EyePosition[3] == 0.0F ||
1277 ( ( fcmd[LIT_ATTEN_CONST] == 0.0 || fcmd[LIT_ATTEN_CONST] == 1.0 ) &&
1278 fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) ) {
1279 /* Disable attenuation */
1280 icmd[idx] &= ~atten_flag;
1281 } else {
1282 if ( fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) {
1283 /* Enable only constant portion of attenuation calculation */
1284 icmd[idx] |= ( atten_flag | atten_const_flag );
1285 } else {
1286 /* Enable full attenuation calculation */
1287 icmd[idx] &= ~atten_const_flag;
1288 icmd[idx] |= atten_flag;
1289 }
1290 }
1291
1292 R200_DB_STATECHANGE( rmesa, &rmesa->hw.tcl );
1293 break;
1294 }
1295 default:
1296 break;
1297 }
1298 }
1299
1300 static void r200UpdateLocalViewer ( GLcontext *ctx )
1301 {
1302 /* It looks like for the texgen modes GL_SPHERE_MAP, GL_NORMAL_MAP and
1303 GL_REFLECTION_MAP we need R200_LOCAL_VIEWER set (fglrx does exactly that
1304 for these and only these modes). This means specular highlights may turn out
1305 wrong in some cases when lighting is enabled but GL_LIGHT_MODEL_LOCAL_VIEWER
1306 is not set, though it seems to happen rarely and the effect seems quite
1307 subtle. May need TCL fallback to fix it completely, though I'm not sure
1308 how you'd identify the cases where the specular highlights indeed will
1309 be wrong. Don't know if fglrx does something special in that case.
1310 */
1311 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1312 R200_STATECHANGE( rmesa, tcl );
1313 if (ctx->Light.Model.LocalViewer ||
1314 ctx->Texture._GenFlags & TEXGEN_NEED_NORMALS)
1315 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LOCAL_VIEWER;
1316 else
1317 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_LOCAL_VIEWER;
1318 }
1319
1320 static void r200LightModelfv( GLcontext *ctx, GLenum pname,
1321 const GLfloat *param )
1322 {
1323 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1324
1325 switch (pname) {
1326 case GL_LIGHT_MODEL_AMBIENT:
1327 update_global_ambient( ctx );
1328 break;
1329
1330 case GL_LIGHT_MODEL_LOCAL_VIEWER:
1331 r200UpdateLocalViewer( ctx );
1332 break;
1333
1334 case GL_LIGHT_MODEL_TWO_SIDE:
1335 R200_STATECHANGE( rmesa, tcl );
1336 if (ctx->Light.Model.TwoSide)
1337 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHT_TWOSIDE;
1338 else
1339 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~(R200_LIGHT_TWOSIDE);
1340 if (rmesa->radeon.TclFallback) {
1341 r200ChooseRenderState( ctx );
1342 r200ChooseVertexState( ctx );
1343 }
1344 break;
1345
1346 case GL_LIGHT_MODEL_COLOR_CONTROL:
1347 r200UpdateSpecular(ctx);
1348 break;
1349
1350 default:
1351 break;
1352 }
1353 }
1354
1355 static void r200ShadeModel( GLcontext *ctx, GLenum mode )
1356 {
1357 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1358 GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL];
1359
1360 s &= ~(R200_DIFFUSE_SHADE_MASK |
1361 R200_ALPHA_SHADE_MASK |
1362 R200_SPECULAR_SHADE_MASK |
1363 R200_FOG_SHADE_MASK |
1364 R200_DISC_FOG_SHADE_MASK);
1365
1366 switch ( mode ) {
1367 case GL_FLAT:
1368 s |= (R200_DIFFUSE_SHADE_FLAT |
1369 R200_ALPHA_SHADE_FLAT |
1370 R200_SPECULAR_SHADE_FLAT |
1371 R200_FOG_SHADE_FLAT |
1372 R200_DISC_FOG_SHADE_FLAT);
1373 break;
1374 case GL_SMOOTH:
1375 s |= (R200_DIFFUSE_SHADE_GOURAUD |
1376 R200_ALPHA_SHADE_GOURAUD |
1377 R200_SPECULAR_SHADE_GOURAUD |
1378 R200_FOG_SHADE_GOURAUD |
1379 R200_DISC_FOG_SHADE_GOURAUD);
1380 break;
1381 default:
1382 return;
1383 }
1384
1385 if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) {
1386 R200_STATECHANGE( rmesa, set );
1387 rmesa->hw.set.cmd[SET_SE_CNTL] = s;
1388 }
1389 }
1390
1391
1392 /* =============================================================
1393 * User clip planes
1394 */
1395
1396 static void r200ClipPlane( GLcontext *ctx, GLenum plane, const GLfloat *eq )
1397 {
1398 GLint p = (GLint) plane - (GLint) GL_CLIP_PLANE0;
1399 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1400 GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
1401
1402 R200_STATECHANGE( rmesa, ucp[p] );
1403 rmesa->hw.ucp[p].cmd[UCP_X] = ip[0];
1404 rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1];
1405 rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2];
1406 rmesa->hw.ucp[p].cmd[UCP_W] = ip[3];
1407 }
1408
1409 static void r200UpdateClipPlanes( GLcontext *ctx )
1410 {
1411 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1412 GLuint p;
1413
1414 for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
1415 if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
1416 GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
1417
1418 R200_STATECHANGE( rmesa, ucp[p] );
1419 rmesa->hw.ucp[p].cmd[UCP_X] = ip[0];
1420 rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1];
1421 rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2];
1422 rmesa->hw.ucp[p].cmd[UCP_W] = ip[3];
1423 }
1424 }
1425 }
1426
1427
1428 /* =============================================================
1429 * Stencil
1430 */
1431
1432 static void
1433 r200StencilFuncSeparate( GLcontext *ctx, GLenum face, GLenum func,
1434 GLint ref, GLuint mask )
1435 {
1436 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1437 GLuint refmask = (((ctx->Stencil.Ref[0] & 0xff) << R200_STENCIL_REF_SHIFT) |
1438 ((ctx->Stencil.ValueMask[0] & 0xff) << R200_STENCIL_MASK_SHIFT));
1439
1440 R200_STATECHANGE( rmesa, ctx );
1441 R200_STATECHANGE( rmesa, msk );
1442
1443 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_STENCIL_TEST_MASK;
1444 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~(R200_STENCIL_REF_MASK|
1445 R200_STENCIL_VALUE_MASK);
1446
1447 switch ( ctx->Stencil.Function[0] ) {
1448 case GL_NEVER:
1449 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_NEVER;
1450 break;
1451 case GL_LESS:
1452 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_LESS;
1453 break;
1454 case GL_EQUAL:
1455 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_EQUAL;
1456 break;
1457 case GL_LEQUAL:
1458 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_LEQUAL;
1459 break;
1460 case GL_GREATER:
1461 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_GREATER;
1462 break;
1463 case GL_NOTEQUAL:
1464 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_NEQUAL;
1465 break;
1466 case GL_GEQUAL:
1467 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_GEQUAL;
1468 break;
1469 case GL_ALWAYS:
1470 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_ALWAYS;
1471 break;
1472 }
1473
1474 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |= refmask;
1475 }
1476
1477 static void
1478 r200StencilMaskSeparate( GLcontext *ctx, GLenum face, GLuint mask )
1479 {
1480 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1481
1482 R200_STATECHANGE( rmesa, msk );
1483 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~R200_STENCIL_WRITE_MASK;
1484 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |=
1485 ((ctx->Stencil.WriteMask[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT);
1486 }
1487
1488 static void
1489 r200StencilOpSeparate( GLcontext *ctx, GLenum face, GLenum fail,
1490 GLenum zfail, GLenum zpass )
1491 {
1492 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1493
1494 R200_STATECHANGE( rmesa, ctx );
1495 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~(R200_STENCIL_FAIL_MASK |
1496 R200_STENCIL_ZFAIL_MASK |
1497 R200_STENCIL_ZPASS_MASK);
1498
1499 switch ( ctx->Stencil.FailFunc[0] ) {
1500 case GL_KEEP:
1501 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_KEEP;
1502 break;
1503 case GL_ZERO:
1504 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_ZERO;
1505 break;
1506 case GL_REPLACE:
1507 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_REPLACE;
1508 break;
1509 case GL_INCR:
1510 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INC;
1511 break;
1512 case GL_DECR:
1513 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_DEC;
1514 break;
1515 case GL_INCR_WRAP_EXT:
1516 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INC_WRAP;
1517 break;
1518 case GL_DECR_WRAP_EXT:
1519 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_DEC_WRAP;
1520 break;
1521 case GL_INVERT:
1522 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INVERT;
1523 break;
1524 }
1525
1526 switch ( ctx->Stencil.ZFailFunc[0] ) {
1527 case GL_KEEP:
1528 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_KEEP;
1529 break;
1530 case GL_ZERO:
1531 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_ZERO;
1532 break;
1533 case GL_REPLACE:
1534 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_REPLACE;
1535 break;
1536 case GL_INCR:
1537 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INC;
1538 break;
1539 case GL_DECR:
1540 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_DEC;
1541 break;
1542 case GL_INCR_WRAP_EXT:
1543 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INC_WRAP;
1544 break;
1545 case GL_DECR_WRAP_EXT:
1546 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_DEC_WRAP;
1547 break;
1548 case GL_INVERT:
1549 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INVERT;
1550 break;
1551 }
1552
1553 switch ( ctx->Stencil.ZPassFunc[0] ) {
1554 case GL_KEEP:
1555 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_KEEP;
1556 break;
1557 case GL_ZERO:
1558 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_ZERO;
1559 break;
1560 case GL_REPLACE:
1561 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_REPLACE;
1562 break;
1563 case GL_INCR:
1564 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INC;
1565 break;
1566 case GL_DECR:
1567 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_DEC;
1568 break;
1569 case GL_INCR_WRAP_EXT:
1570 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INC_WRAP;
1571 break;
1572 case GL_DECR_WRAP_EXT:
1573 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_DEC_WRAP;
1574 break;
1575 case GL_INVERT:
1576 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INVERT;
1577 break;
1578 }
1579 }
1580
1581 static void r200ClearStencil( GLcontext *ctx, GLint s )
1582 {
1583 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1584
1585 rmesa->radeon.state.stencil.clear =
1586 ((GLuint) (ctx->Stencil.Clear & 0xff) |
1587 (0xff << R200_STENCIL_MASK_SHIFT) |
1588 ((ctx->Stencil.WriteMask[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT));
1589 }
1590
1591
1592 /* =============================================================
1593 * Window position and viewport transformation
1594 */
1595
1596 /*
1597 * To correctly position primitives:
1598 */
1599 #define SUBPIXEL_X 0.125
1600 #define SUBPIXEL_Y 0.125
1601
1602
1603 /**
1604 * Called when window size or position changes or viewport or depth range
1605 * state is changed. We update the hardware viewport state here.
1606 */
1607 void r200UpdateWindow( GLcontext *ctx )
1608 {
1609 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1610 __DRIdrawablePrivate *dPriv = rmesa->radeon.dri.drawable;
1611 GLfloat xoffset = dPriv ? (GLfloat) dPriv->x : 0;
1612 GLfloat yoffset = dPriv ? (GLfloat) dPriv->y + dPriv->h : 0;
1613 const GLfloat *v = ctx->Viewport._WindowMap.m;
1614
1615 float_ui32_type sx = { v[MAT_SX] };
1616 float_ui32_type tx = { v[MAT_TX] + xoffset + SUBPIXEL_X };
1617 float_ui32_type sy = { - v[MAT_SY] };
1618 float_ui32_type ty = { (- v[MAT_TY]) + yoffset + SUBPIXEL_Y };
1619 float_ui32_type sz = { v[MAT_SZ] * rmesa->radeon.state.depth.scale };
1620 float_ui32_type tz = { v[MAT_TZ] * rmesa->radeon.state.depth.scale };
1621
1622 radeon_firevertices(&rmesa->radeon);
1623 R200_STATECHANGE( rmesa, vpt );
1624
1625 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XSCALE] = sx.ui32;
1626 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = tx.ui32;
1627 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YSCALE] = sy.ui32;
1628 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = ty.ui32;
1629 rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZSCALE] = sz.ui32;
1630 rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZOFFSET] = tz.ui32;
1631 }
1632
1633
1634
1635 static void r200Viewport( GLcontext *ctx, GLint x, GLint y,
1636 GLsizei width, GLsizei height )
1637 {
1638 /* Don't pipeline viewport changes, conflict with window offset
1639 * setting below. Could apply deltas to rescue pipelined viewport
1640 * values, or keep the originals hanging around.
1641 */
1642 r200UpdateWindow( ctx );
1643 }
1644
1645 static void r200DepthRange( GLcontext *ctx, GLclampd nearval,
1646 GLclampd farval )
1647 {
1648 r200UpdateWindow( ctx );
1649 }
1650
1651 void r200UpdateViewportOffset( GLcontext *ctx )
1652 {
1653 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1654 __DRIdrawablePrivate *dPriv = rmesa->radeon.dri.drawable;
1655 GLfloat xoffset = (GLfloat)dPriv->x;
1656 GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h;
1657 const GLfloat *v = ctx->Viewport._WindowMap.m;
1658
1659 float_ui32_type tx;
1660 float_ui32_type ty;
1661
1662 tx.f = v[MAT_TX] + xoffset + SUBPIXEL_X;
1663 ty.f = (- v[MAT_TY]) + yoffset + SUBPIXEL_Y;
1664
1665 if ( rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] != tx.ui32 ||
1666 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] != ty.ui32 )
1667 {
1668 /* Note: this should also modify whatever data the context reset
1669 * code uses...
1670 */
1671 R200_STATECHANGE( rmesa, vpt );
1672 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = tx.ui32;
1673 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = ty.ui32;
1674
1675 /* update polygon stipple x/y screen offset */
1676 {
1677 GLuint stx, sty;
1678 GLuint m = rmesa->hw.msc.cmd[MSC_RE_MISC];
1679
1680 m &= ~(R200_STIPPLE_X_OFFSET_MASK |
1681 R200_STIPPLE_Y_OFFSET_MASK);
1682
1683 /* add magic offsets, then invert */
1684 stx = 31 - ((rmesa->radeon.dri.drawable->x - 1) & R200_STIPPLE_COORD_MASK);
1685 sty = 31 - ((rmesa->radeon.dri.drawable->y + rmesa->radeon.dri.drawable->h - 1)
1686 & R200_STIPPLE_COORD_MASK);
1687
1688 m |= ((stx << R200_STIPPLE_X_OFFSET_SHIFT) |
1689 (sty << R200_STIPPLE_Y_OFFSET_SHIFT));
1690
1691 if ( rmesa->hw.msc.cmd[MSC_RE_MISC] != m ) {
1692 R200_STATECHANGE( rmesa, msc );
1693 rmesa->hw.msc.cmd[MSC_RE_MISC] = m;
1694 }
1695 }
1696 }
1697
1698 radeonUpdateScissor( ctx );
1699 }
1700
1701
1702
1703 /* =============================================================
1704 * Miscellaneous
1705 */
1706
1707 static void r200ClearColor( GLcontext *ctx, const GLfloat c[4] )
1708 {
1709 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1710 GLubyte color[4];
1711 CLAMPED_FLOAT_TO_UBYTE(color[0], c[0]);
1712 CLAMPED_FLOAT_TO_UBYTE(color[1], c[1]);
1713 CLAMPED_FLOAT_TO_UBYTE(color[2], c[2]);
1714 CLAMPED_FLOAT_TO_UBYTE(color[3], c[3]);
1715 rmesa->radeon.state.color.clear = radeonPackColor( rmesa->radeon.radeonScreen->cpp,
1716 color[0], color[1],
1717 color[2], color[3] );
1718 }
1719
1720
1721 static void r200RenderMode( GLcontext *ctx, GLenum mode )
1722 {
1723 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1724 FALLBACK( rmesa, R200_FALLBACK_RENDER_MODE, (mode != GL_RENDER) );
1725 }
1726
1727
1728 static GLuint r200_rop_tab[] = {
1729 R200_ROP_CLEAR,
1730 R200_ROP_AND,
1731 R200_ROP_AND_REVERSE,
1732 R200_ROP_COPY,
1733 R200_ROP_AND_INVERTED,
1734 R200_ROP_NOOP,
1735 R200_ROP_XOR,
1736 R200_ROP_OR,
1737 R200_ROP_NOR,
1738 R200_ROP_EQUIV,
1739 R200_ROP_INVERT,
1740 R200_ROP_OR_REVERSE,
1741 R200_ROP_COPY_INVERTED,
1742 R200_ROP_OR_INVERTED,
1743 R200_ROP_NAND,
1744 R200_ROP_SET,
1745 };
1746
1747 static void r200LogicOpCode( GLcontext *ctx, GLenum opcode )
1748 {
1749 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1750 GLuint rop = (GLuint)opcode - GL_CLEAR;
1751
1752 ASSERT( rop < 16 );
1753
1754 R200_STATECHANGE( rmesa, msk );
1755 rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = r200_rop_tab[rop];
1756 }
1757
1758
1759 static void r200DrawBuffer( GLcontext *ctx, GLenum mode )
1760 {
1761 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1762
1763 if (R200_DEBUG & DEBUG_DRI)
1764 fprintf(stderr, "%s %s\n", __FUNCTION__,
1765 _mesa_lookup_enum_by_nr( mode ));
1766
1767 radeon_firevertices(&rmesa->radeon); /* don't pipeline cliprect changes */
1768
1769 if (ctx->DrawBuffer->_NumColorDrawBuffers != 1) {
1770 /* 0 (GL_NONE) buffers or multiple color drawing buffers */
1771 FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_TRUE );
1772 return;
1773 }
1774
1775 switch ( ctx->DrawBuffer->_ColorDrawBufferIndexes[0] ) {
1776 case BUFFER_FRONT_LEFT:
1777 case BUFFER_BACK_LEFT:
1778 FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_FALSE );
1779 break;
1780 default:
1781 FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_TRUE );
1782 return;
1783 }
1784
1785 radeonSetCliprects( &rmesa->radeon );
1786 radeonUpdatePageFlipping(&rmesa->radeon);
1787
1788 /* We'll set the drawing engine's offset/pitch parameters later
1789 * when we update other state.
1790 */
1791 }
1792
1793
1794 static void r200ReadBuffer( GLcontext *ctx, GLenum mode )
1795 {
1796 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
1797 }
1798
1799 /* =============================================================
1800 * State enable/disable
1801 */
1802
1803 static void r200Enable( GLcontext *ctx, GLenum cap, GLboolean state )
1804 {
1805 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1806 GLuint p, flag;
1807
1808 if ( R200_DEBUG & DEBUG_STATE )
1809 fprintf( stderr, "%s( %s = %s )\n", __FUNCTION__,
1810 _mesa_lookup_enum_by_nr( cap ),
1811 state ? "GL_TRUE" : "GL_FALSE" );
1812
1813 switch ( cap ) {
1814 /* Fast track this one...
1815 */
1816 case GL_TEXTURE_1D:
1817 case GL_TEXTURE_2D:
1818 case GL_TEXTURE_3D:
1819 break;
1820
1821 case GL_ALPHA_TEST:
1822 R200_STATECHANGE( rmesa, ctx );
1823 if (state) {
1824 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ALPHA_TEST_ENABLE;
1825 } else {
1826 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ALPHA_TEST_ENABLE;
1827 }
1828 break;
1829
1830 case GL_BLEND:
1831 case GL_COLOR_LOGIC_OP:
1832 r200_set_blend_state( ctx );
1833 break;
1834
1835 case GL_CLIP_PLANE0:
1836 case GL_CLIP_PLANE1:
1837 case GL_CLIP_PLANE2:
1838 case GL_CLIP_PLANE3:
1839 case GL_CLIP_PLANE4:
1840 case GL_CLIP_PLANE5:
1841 p = cap-GL_CLIP_PLANE0;
1842 R200_STATECHANGE( rmesa, tcl );
1843 if (state) {
1844 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (R200_UCP_ENABLE_0<<p);
1845 r200ClipPlane( ctx, cap, NULL );
1846 }
1847 else {
1848 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0<<p);
1849 }
1850 break;
1851
1852 case GL_COLOR_MATERIAL:
1853 r200ColorMaterial( ctx, 0, 0 );
1854 r200UpdateMaterial( ctx );
1855 break;
1856
1857 case GL_CULL_FACE:
1858 r200CullFace( ctx, 0 );
1859 break;
1860
1861 case GL_DEPTH_TEST:
1862 R200_STATECHANGE(rmesa, ctx );
1863 if ( state ) {
1864 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_Z_ENABLE;
1865 } else {
1866 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_Z_ENABLE;
1867 }
1868 break;
1869
1870 case GL_DITHER:
1871 R200_STATECHANGE(rmesa, ctx );
1872 if ( state ) {
1873 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_DITHER_ENABLE;
1874 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~rmesa->radeon.state.color.roundEnable;
1875 } else {
1876 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_DITHER_ENABLE;
1877 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= rmesa->radeon.state.color.roundEnable;
1878 }
1879 break;
1880
1881 case GL_FOG:
1882 R200_STATECHANGE(rmesa, ctx );
1883 if ( state ) {
1884 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_FOG_ENABLE;
1885 r200Fogfv( ctx, GL_FOG_MODE, NULL );
1886 } else {
1887 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_FOG_ENABLE;
1888 R200_STATECHANGE(rmesa, tcl);
1889 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_TCL_FOG_MASK;
1890 }
1891 r200UpdateSpecular( ctx ); /* for PK_SPEC */
1892 if (rmesa->radeon.TclFallback)
1893 r200ChooseVertexState( ctx );
1894 _mesa_allow_light_in_model( ctx, !state );
1895 break;
1896
1897 case GL_LIGHT0:
1898 case GL_LIGHT1:
1899 case GL_LIGHT2:
1900 case GL_LIGHT3:
1901 case GL_LIGHT4:
1902 case GL_LIGHT5:
1903 case GL_LIGHT6:
1904 case GL_LIGHT7:
1905 R200_STATECHANGE(rmesa, tcl);
1906 p = cap - GL_LIGHT0;
1907 if (p&1)
1908 flag = (R200_LIGHT_1_ENABLE |
1909 R200_LIGHT_1_ENABLE_AMBIENT |
1910 R200_LIGHT_1_ENABLE_SPECULAR);
1911 else
1912 flag = (R200_LIGHT_0_ENABLE |
1913 R200_LIGHT_0_ENABLE_AMBIENT |
1914 R200_LIGHT_0_ENABLE_SPECULAR);
1915
1916 if (state)
1917 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] |= flag;
1918 else
1919 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] &= ~flag;
1920
1921 /*
1922 */
1923 update_light_colors( ctx, p );
1924 break;
1925
1926 case GL_LIGHTING:
1927 r200UpdateSpecular(ctx);
1928 /* for reflection map fixup - might set recheck_texgen for all units too */
1929 rmesa->radeon.NewGLState |= _NEW_TEXTURE;
1930 break;
1931
1932 case GL_LINE_SMOOTH:
1933 R200_STATECHANGE( rmesa, ctx );
1934 if ( state ) {
1935 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ANTI_ALIAS_LINE;
1936 } else {
1937 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_LINE;
1938 }
1939 break;
1940
1941 case GL_LINE_STIPPLE:
1942 R200_STATECHANGE( rmesa, set );
1943 if ( state ) {
1944 rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_PATTERN_ENABLE;
1945 } else {
1946 rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_PATTERN_ENABLE;
1947 }
1948 break;
1949
1950 case GL_NORMALIZE:
1951 R200_STATECHANGE( rmesa, tcl );
1952 if ( state ) {
1953 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_NORMALIZE_NORMALS;
1954 } else {
1955 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_NORMALIZE_NORMALS;
1956 }
1957 break;
1958
1959 /* Pointsize registers on r200 only work for point sprites, and point smooth
1960 * doesn't work for point sprites (and isn't needed for 1.0 sized aa points).
1961 * In any case, setting pointmin == pointsizemax == 1.0 for aa points
1962 * is enough to satisfy conform.
1963 */
1964 case GL_POINT_SMOOTH:
1965 break;
1966
1967 /* These don't really do anything, as we don't use the 3vtx
1968 * primitives yet.
1969 */
1970 #if 0
1971 case GL_POLYGON_OFFSET_POINT:
1972 R200_STATECHANGE( rmesa, set );
1973 if ( state ) {
1974 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_POINT;
1975 } else {
1976 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_POINT;
1977 }
1978 break;
1979
1980 case GL_POLYGON_OFFSET_LINE:
1981 R200_STATECHANGE( rmesa, set );
1982 if ( state ) {
1983 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_LINE;
1984 } else {
1985 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_LINE;
1986 }
1987 break;
1988 #endif
1989
1990 case GL_POINT_SPRITE_ARB:
1991 R200_STATECHANGE( rmesa, spr );
1992 if ( state ) {
1993 int i;
1994 for (i = 0; i < 6; i++) {
1995 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |=
1996 ctx->Point.CoordReplace[i] << (R200_PS_GEN_TEX_0_SHIFT + i);
1997 }
1998 } else {
1999 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] &= ~R200_PS_GEN_TEX_MASK;
2000 }
2001 break;
2002
2003 case GL_POLYGON_OFFSET_FILL:
2004 R200_STATECHANGE( rmesa, set );
2005 if ( state ) {
2006 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_TRI;
2007 } else {
2008 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_TRI;
2009 }
2010 break;
2011
2012 case GL_POLYGON_SMOOTH:
2013 R200_STATECHANGE( rmesa, ctx );
2014 if ( state ) {
2015 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ANTI_ALIAS_POLY;
2016 } else {
2017 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_POLY;
2018 }
2019 break;
2020
2021 case GL_POLYGON_STIPPLE:
2022 R200_STATECHANGE(rmesa, set );
2023 if ( state ) {
2024 rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_STIPPLE_ENABLE;
2025 } else {
2026 rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_STIPPLE_ENABLE;
2027 }
2028 break;
2029
2030 case GL_RESCALE_NORMAL_EXT: {
2031 GLboolean tmp = ctx->_NeedEyeCoords ? state : !state;
2032 R200_STATECHANGE( rmesa, tcl );
2033 if ( tmp ) {
2034 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_RESCALE_NORMALS;
2035 } else {
2036 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS;
2037 }
2038 break;
2039 }
2040
2041 case GL_SCISSOR_TEST:
2042 radeon_firevertices(&rmesa->radeon);
2043 rmesa->radeon.state.scissor.enabled = state;
2044 radeonUpdateScissor( ctx );
2045 break;
2046
2047 case GL_STENCIL_TEST:
2048 if ( rmesa->radeon.state.stencil.hwBuffer ) {
2049 R200_STATECHANGE( rmesa, ctx );
2050 if ( state ) {
2051 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_STENCIL_ENABLE;
2052 } else {
2053 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_STENCIL_ENABLE;
2054 }
2055 } else {
2056 FALLBACK( rmesa, R200_FALLBACK_STENCIL, state );
2057 }
2058 break;
2059
2060 case GL_TEXTURE_GEN_Q:
2061 case GL_TEXTURE_GEN_R:
2062 case GL_TEXTURE_GEN_S:
2063 case GL_TEXTURE_GEN_T:
2064 /* Picked up in r200UpdateTextureState.
2065 */
2066 rmesa->recheck_texgen[ctx->Texture.CurrentUnit] = GL_TRUE;
2067 break;
2068
2069 case GL_COLOR_SUM_EXT:
2070 r200UpdateSpecular ( ctx );
2071 break;
2072
2073 case GL_VERTEX_PROGRAM_ARB:
2074 if (!state) {
2075 GLuint i;
2076 rmesa->curr_vp_hw = NULL;
2077 R200_STATECHANGE( rmesa, vap );
2078 rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] &= ~R200_VAP_PROG_VTX_SHADER_ENABLE;
2079 /* mark all tcl atoms (tcl vector state got overwritten) dirty
2080 not sure about tcl scalar state - we need at least grd
2081 with vert progs too.
2082 ucp looks like it doesn't get overwritten (may even work
2083 with vp for pos-invariant progs if we're lucky) */
2084 R200_STATECHANGE( rmesa, mtl[0] );
2085 R200_STATECHANGE( rmesa, mtl[1] );
2086 R200_STATECHANGE( rmesa, fog );
2087 R200_STATECHANGE( rmesa, glt );
2088 R200_STATECHANGE( rmesa, eye );
2089 for (i = R200_MTX_MV; i <= R200_MTX_TEX5; i++) {
2090 R200_STATECHANGE( rmesa, mat[i] );
2091 }
2092 for (i = 0 ; i < 8; i++) {
2093 R200_STATECHANGE( rmesa, lit[i] );
2094 }
2095 R200_STATECHANGE( rmesa, tcl );
2096 for (i = 0; i <= ctx->Const.MaxClipPlanes; i++) {
2097 if (ctx->Transform.ClipPlanesEnabled & (1 << i)) {
2098 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (R200_UCP_ENABLE_0 << i);
2099 }
2100 /* else {
2101 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0 << i);
2102 }*/
2103 }
2104 /* ugly. Need to call everything which might change compsel. */
2105 r200UpdateSpecular( ctx );
2106 #if 0
2107 /* shouldn't be necessary, as it's picked up anyway in r200ValidateState (_NEW_PROGRAM),
2108 but without it doom3 locks up at always the same places. Why? */
2109 /* FIXME: This can (and should) be replaced by a call to the TCL_STATE_FLUSH reg before
2110 accessing VAP_SE_VAP_CNTL. Requires drm changes (done). Remove after some time... */
2111 r200UpdateTextureState( ctx );
2112 /* if we call r200UpdateTextureState we need the code below because we are calling it with
2113 non-current derived enabled values which may revert the state atoms for frag progs even when
2114 they already got disabled... ugh
2115 Should really figure out why we need to call r200UpdateTextureState in the first place */
2116 GLuint unit;
2117 for (unit = 0; unit < R200_MAX_TEXTURE_UNITS; unit++) {
2118 R200_STATECHANGE( rmesa, pix[unit] );
2119 R200_STATECHANGE( rmesa, tex[unit] );
2120 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] &=
2121 ~(R200_TXFORMAT_ST_ROUTE_MASK | R200_TXFORMAT_LOOKUP_DISABLE);
2122 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] |= unit << R200_TXFORMAT_ST_ROUTE_SHIFT;
2123 /* need to guard this with drmSupportsFragmentShader? Should never get here if
2124 we don't announce ATI_fs, right? */
2125 rmesa->hw.tex[unit].cmd[TEX_PP_TXMULTI_CTL] = 0;
2126 }
2127 R200_STATECHANGE( rmesa, cst );
2128 R200_STATECHANGE( rmesa, tf );
2129 rmesa->hw.cst.cmd[CST_PP_CNTL_X] = 0;
2130 #endif
2131 }
2132 else {
2133 /* picked up later */
2134 }
2135 /* call functions which change hw state based on ARB_vp enabled or not. */
2136 r200PointParameter( ctx, GL_POINT_DISTANCE_ATTENUATION, NULL );
2137 r200Fogfv( ctx, GL_FOG_COORD_SRC, NULL );
2138 break;
2139
2140 case GL_VERTEX_PROGRAM_POINT_SIZE_ARB:
2141 r200PointParameter( ctx, GL_POINT_DISTANCE_ATTENUATION, NULL );
2142 break;
2143
2144 case GL_FRAGMENT_SHADER_ATI:
2145 if ( !state ) {
2146 /* restore normal tex env colors and make sure tex env combine will get updated
2147 mark env atoms dirty (as their data was overwritten by afs even
2148 if they didn't change) and restore tex coord routing */
2149 GLuint unit;
2150 for (unit = 0; unit < R200_MAX_TEXTURE_UNITS; unit++) {
2151 R200_STATECHANGE( rmesa, pix[unit] );
2152 R200_STATECHANGE( rmesa, tex[unit] );
2153 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] &=
2154 ~(R200_TXFORMAT_ST_ROUTE_MASK | R200_TXFORMAT_LOOKUP_DISABLE);
2155 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] |= unit << R200_TXFORMAT_ST_ROUTE_SHIFT;
2156 /* need to guard this with drmSupportsFragmentShader? Should never get here if
2157 we don't announce ATI_fs, right? */
2158 rmesa->hw.tex[unit].cmd[TEX_PP_TXMULTI_CTL] = 0;
2159 }
2160 R200_STATECHANGE( rmesa, cst );
2161 R200_STATECHANGE( rmesa, tf );
2162 rmesa->hw.cst.cmd[CST_PP_CNTL_X] = 0;
2163 }
2164 else {
2165 /* need to mark this dirty as pix/tf atoms have overwritten the data
2166 even if the data in the atoms didn't change */
2167 R200_STATECHANGE( rmesa, atf );
2168 R200_STATECHANGE( rmesa, afs[1] );
2169 /* everything else picked up in r200UpdateTextureState hopefully */
2170 }
2171 break;
2172 default:
2173 return;
2174 }
2175 }
2176
2177
2178 void r200LightingSpaceChange( GLcontext *ctx )
2179 {
2180 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2181 GLboolean tmp;
2182
2183 if (R200_DEBUG & DEBUG_STATE)
2184 fprintf(stderr, "%s %d BEFORE %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
2185 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]);
2186
2187 if (ctx->_NeedEyeCoords)
2188 tmp = ctx->Transform.RescaleNormals;
2189 else
2190 tmp = !ctx->Transform.RescaleNormals;
2191
2192 R200_STATECHANGE( rmesa, tcl );
2193 if ( tmp ) {
2194 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_RESCALE_NORMALS;
2195 } else {
2196 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS;
2197 }
2198
2199 if (R200_DEBUG & DEBUG_STATE)
2200 fprintf(stderr, "%s %d AFTER %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
2201 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]);
2202 }
2203
2204 /* =============================================================
2205 * Deferred state management - matrices, textures, other?
2206 */
2207
2208
2209
2210
2211 static void upload_matrix( r200ContextPtr rmesa, GLfloat *src, int idx )
2212 {
2213 float *dest = ((float *)R200_DB_STATE( mat[idx] ))+MAT_ELT_0;
2214 int i;
2215
2216
2217 for (i = 0 ; i < 4 ; i++) {
2218 *dest++ = src[i];
2219 *dest++ = src[i+4];
2220 *dest++ = src[i+8];
2221 *dest++ = src[i+12];
2222 }
2223
2224 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2225 }
2226
2227 static void upload_matrix_t( r200ContextPtr rmesa, const GLfloat *src, int idx )
2228 {
2229 float *dest = ((float *)R200_DB_STATE( mat[idx] ))+MAT_ELT_0;
2230 memcpy(dest, src, 16*sizeof(float));
2231 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2232 }
2233
2234
2235 static void update_texturematrix( GLcontext *ctx )
2236 {
2237 r200ContextPtr rmesa = R200_CONTEXT( ctx );
2238 GLuint tpc = rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0];
2239 GLuint compsel = rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL];
2240 int unit;
2241
2242 if (R200_DEBUG & DEBUG_STATE)
2243 fprintf(stderr, "%s before COMPSEL: %x\n", __FUNCTION__,
2244 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]);
2245
2246 rmesa->TexMatEnabled = 0;
2247 rmesa->TexMatCompSel = 0;
2248
2249 for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++) {
2250 if (!ctx->Texture.Unit[unit]._ReallyEnabled)
2251 continue;
2252
2253 if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY) {
2254 rmesa->TexMatEnabled |= (R200_TEXGEN_TEXMAT_0_ENABLE|
2255 R200_TEXMAT_0_ENABLE) << unit;
2256
2257 rmesa->TexMatCompSel |= R200_OUTPUT_TEX_0 << unit;
2258
2259 if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) {
2260 /* Need to preconcatenate any active texgen
2261 * obj/eyeplane matrices:
2262 */
2263 _math_matrix_mul_matrix( &rmesa->tmpmat,
2264 ctx->TextureMatrixStack[unit].Top,
2265 &rmesa->TexGenMatrix[unit] );
2266 upload_matrix( rmesa, rmesa->tmpmat.m, R200_MTX_TEX0+unit );
2267 }
2268 else {
2269 upload_matrix( rmesa, ctx->TextureMatrixStack[unit].Top->m,
2270 R200_MTX_TEX0+unit );
2271 }
2272 }
2273 else if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) {
2274 upload_matrix( rmesa, rmesa->TexGenMatrix[unit].m,
2275 R200_MTX_TEX0+unit );
2276 }
2277 }
2278
2279 tpc = (rmesa->TexMatEnabled | rmesa->TexGenEnabled);
2280 if (tpc != rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0]) {
2281 R200_STATECHANGE(rmesa, tcg);
2282 rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0] = tpc;
2283 }
2284
2285 compsel &= ~R200_OUTPUT_TEX_MASK;
2286 compsel |= rmesa->TexMatCompSel | rmesa->TexGenCompSel;
2287 if (compsel != rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]) {
2288 R200_STATECHANGE(rmesa, vtx);
2289 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] = compsel;
2290 }
2291 }
2292
2293
2294
2295 /**
2296 * Tell the card where to render (offset, pitch).
2297 * Effected by glDrawBuffer, etc
2298 */
2299 void
2300 r200UpdateDrawBuffer(GLcontext *ctx)
2301 {
2302 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2303 struct gl_framebuffer *fb = ctx->DrawBuffer;
2304 struct radeon_renderbuffer *rrb;
2305
2306 if (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) {
2307 /* draw to front */
2308 rrb = (void *) fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
2309 } else if (fb->_ColorDrawBufferIndexes[0] == BUFFER_BACK_LEFT) {
2310 /* draw to back */
2311 rrb = (void *) fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
2312 } else {
2313 /* drawing to multiple buffers, or none */
2314 return;
2315 }
2316
2317 assert(rrb);
2318 assert(rrb->pitch);
2319
2320 R200_STATECHANGE( rmesa, ctx );
2321
2322 #if 0
2323 /* Note: we used the (possibly) page-flipped values */
2324 rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET]
2325 = ((rrb->flippedOffset + rmesa->radeon.radeonScreen->fbLocation)
2326 & R200_COLOROFFSET_MASK);
2327 rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = drb->flippedPitch;
2328 if (rmesa->radeon.sarea->tiling_enabled) {
2329 rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] |= R200_COLOR_TILE_ENABLE;
2330 }
2331 #endif
2332 }
2333
2334 static GLboolean r200ValidateBuffers(GLcontext *ctx)
2335 {
2336 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2337 struct radeon_cs_space_check bos[8];
2338 struct radeon_renderbuffer *rrb;
2339 int num_bo = 0;
2340 int i;
2341 int flushed = 0, ret;
2342 again:
2343 num_bo = 0;
2344
2345 rrb = radeon_get_colorbuffer(&rmesa->radeon);
2346 /* color buffer */
2347 if (rrb && rrb->bo) {
2348 bos[num_bo].bo = rrb->bo;
2349 bos[num_bo].read_domains = 0;
2350 bos[num_bo].write_domain = RADEON_GEM_DOMAIN_VRAM;
2351 bos[num_bo].new_accounted = 0;
2352 num_bo++;
2353 }
2354
2355 /* depth buffer */
2356 rrb = radeon_get_depthbuffer(&rmesa->radeon);
2357 /* color buffer */
2358 if (rrb && rrb->bo) {
2359 bos[num_bo].bo = rrb->bo;
2360 bos[num_bo].read_domains = 0;
2361 bos[num_bo].write_domain = RADEON_GEM_DOMAIN_VRAM;
2362 bos[num_bo].new_accounted = 0;
2363 num_bo++;
2364 }
2365
2366 for (i = 0; i < ctx->Const.MaxTextureImageUnits; ++i) {
2367 radeonTexObj *t;
2368
2369 if (!ctx->Texture.Unit[i]._ReallyEnabled)
2370 continue;
2371
2372 t = radeon_tex_obj(ctx->Texture.Unit[i]._Current);
2373 bos[num_bo].bo = t->mt->bo;
2374 bos[num_bo].read_domains = RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM;
2375 bos[num_bo].write_domain = 0;
2376 bos[num_bo].new_accounted = 0;
2377 num_bo++;
2378 }
2379
2380 ret = radeon_cs_space_check(rmesa->radeon.cmdbuf.cs, bos, num_bo);
2381 if (ret == RADEON_CS_SPACE_OP_TO_BIG)
2382 return GL_FALSE;
2383 if (ret == RADEON_CS_SPACE_FLUSH) {
2384 r200Flush(ctx);
2385 if (flushed)
2386 return GL_FALSE;
2387 flushed = 1;
2388 goto again;
2389 }
2390 return GL_TRUE;
2391 }
2392
2393 GLboolean r200ValidateState( GLcontext *ctx )
2394 {
2395 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2396 GLuint new_state = rmesa->radeon.NewGLState;
2397
2398 if (new_state & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) {
2399 r200UpdateDrawBuffer(ctx);
2400 }
2401
2402 if (new_state & (_NEW_TEXTURE | _NEW_PROGRAM)) {
2403 r200UpdateTextureState( ctx );
2404 new_state |= rmesa->radeon.NewGLState; /* may add TEXTURE_MATRIX */
2405 r200UpdateLocalViewer( ctx );
2406 }
2407
2408 /* we need to do a space check here */
2409 if (!r200ValidateBuffers(ctx))
2410 return GL_FALSE;
2411
2412 /* FIXME: don't really need most of these when vertex progs are enabled */
2413
2414 /* Need an event driven matrix update?
2415 */
2416 if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION))
2417 upload_matrix( rmesa, ctx->_ModelProjectMatrix.m, R200_MTX_MVP );
2418
2419 /* Need these for lighting (shouldn't upload otherwise)
2420 */
2421 if (new_state & (_NEW_MODELVIEW)) {
2422 upload_matrix( rmesa, ctx->ModelviewMatrixStack.Top->m, R200_MTX_MV );
2423 upload_matrix_t( rmesa, ctx->ModelviewMatrixStack.Top->inv, R200_MTX_IMV );
2424 }
2425
2426 /* Does this need to be triggered on eg. modelview for
2427 * texgen-derived objplane/eyeplane matrices?
2428 */
2429 if (new_state & (_NEW_TEXTURE|_NEW_TEXTURE_MATRIX)) {
2430 update_texturematrix( ctx );
2431 }
2432
2433 if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW|_MESA_NEW_NEED_EYE_COORDS)) {
2434 update_light( ctx );
2435 }
2436
2437 /* emit all active clip planes if projection matrix changes.
2438 */
2439 if (new_state & (_NEW_PROJECTION)) {
2440 if (ctx->Transform.ClipPlanesEnabled)
2441 r200UpdateClipPlanes( ctx );
2442 }
2443
2444 if (new_state & (_NEW_PROGRAM|
2445 /* need to test for pretty much anything due to possible parameter bindings */
2446 _NEW_MODELVIEW|_NEW_PROJECTION|_NEW_TRANSFORM|
2447 _NEW_LIGHT|_NEW_TEXTURE|_NEW_TEXTURE_MATRIX|
2448 _NEW_FOG|_NEW_POINT|_NEW_TRACK_MATRIX)) {
2449 if (ctx->VertexProgram._Enabled) {
2450 r200SetupVertexProg( ctx );
2451 }
2452 else TCL_FALLBACK(ctx, R200_TCL_FALLBACK_VERTEX_PROGRAM, 0);
2453 }
2454
2455 rmesa->radeon.NewGLState = 0;
2456 return GL_TRUE;
2457 }
2458
2459
2460 static void r200InvalidateState( GLcontext *ctx, GLuint new_state )
2461 {
2462 _swrast_InvalidateState( ctx, new_state );
2463 _swsetup_InvalidateState( ctx, new_state );
2464 _vbo_InvalidateState( ctx, new_state );
2465 _tnl_InvalidateState( ctx, new_state );
2466 _ae_invalidate_state( ctx, new_state );
2467 R200_CONTEXT(ctx)->radeon.NewGLState |= new_state;
2468 }
2469
2470 /* A hack. The r200 can actually cope just fine with materials
2471 * between begin/ends, so fix this.
2472 * Should map to inputs just like the generic vertex arrays for vertex progs.
2473 * In theory there could still be too many and we'd still need a fallback.
2474 */
2475 static GLboolean check_material( GLcontext *ctx )
2476 {
2477 TNLcontext *tnl = TNL_CONTEXT(ctx);
2478 GLint i;
2479
2480 for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT;
2481 i < _TNL_ATTRIB_MAT_BACK_INDEXES;
2482 i++)
2483 if (tnl->vb.AttribPtr[i] &&
2484 tnl->vb.AttribPtr[i]->stride)
2485 return GL_TRUE;
2486
2487 return GL_FALSE;
2488 }
2489
2490 static void r200WrapRunPipeline( GLcontext *ctx )
2491 {
2492 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2493 GLboolean has_material;
2494
2495 if (0)
2496 fprintf(stderr, "%s, newstate: %x\n", __FUNCTION__, rmesa->radeon.NewGLState);
2497
2498 /* Validate state:
2499 */
2500 if (rmesa->radeon.NewGLState)
2501 if (!r200ValidateState( ctx ))
2502 FALLBACK(rmesa, RADEON_FALLBACK_TEXTURE, GL_TRUE);
2503
2504 has_material = !ctx->VertexProgram._Enabled && ctx->Light.Enabled && check_material( ctx );
2505
2506 if (has_material) {
2507 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_TRUE );
2508 }
2509
2510 /* Run the pipeline.
2511 */
2512 _tnl_run_pipeline( ctx );
2513
2514 if (has_material) {
2515 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_FALSE );
2516 }
2517 }
2518
2519
2520 /* Initialize the driver's state functions.
2521 */
2522 void r200InitStateFuncs( struct dd_function_table *functions )
2523 {
2524 functions->UpdateState = r200InvalidateState;
2525 functions->LightingSpaceChange = r200LightingSpaceChange;
2526
2527 functions->DrawBuffer = r200DrawBuffer;
2528 functions->ReadBuffer = r200ReadBuffer;
2529
2530 functions->AlphaFunc = r200AlphaFunc;
2531 functions->BlendColor = r200BlendColor;
2532 functions->BlendEquationSeparate = r200BlendEquationSeparate;
2533 functions->BlendFuncSeparate = r200BlendFuncSeparate;
2534 functions->ClearColor = r200ClearColor;
2535 functions->ClearDepth = r200ClearDepth;
2536 functions->ClearIndex = NULL;
2537 functions->ClearStencil = r200ClearStencil;
2538 functions->ClipPlane = r200ClipPlane;
2539 functions->ColorMask = r200ColorMask;
2540 functions->CullFace = r200CullFace;
2541 functions->DepthFunc = r200DepthFunc;
2542 functions->DepthMask = r200DepthMask;
2543 functions->DepthRange = r200DepthRange;
2544 functions->Enable = r200Enable;
2545 functions->Fogfv = r200Fogfv;
2546 functions->FrontFace = r200FrontFace;
2547 functions->Hint = NULL;
2548 functions->IndexMask = NULL;
2549 functions->LightModelfv = r200LightModelfv;
2550 functions->Lightfv = r200Lightfv;
2551 functions->LineStipple = r200LineStipple;
2552 functions->LineWidth = r200LineWidth;
2553 functions->LogicOpcode = r200LogicOpCode;
2554 functions->PolygonMode = r200PolygonMode;
2555 functions->PolygonOffset = r200PolygonOffset;
2556 functions->PolygonStipple = r200PolygonStipple;
2557 functions->PointParameterfv = r200PointParameter;
2558 functions->PointSize = r200PointSize;
2559 functions->RenderMode = r200RenderMode;
2560 functions->Scissor = radeonScissor;
2561 functions->ShadeModel = r200ShadeModel;
2562 functions->StencilFuncSeparate = r200StencilFuncSeparate;
2563 functions->StencilMaskSeparate = r200StencilMaskSeparate;
2564 functions->StencilOpSeparate = r200StencilOpSeparate;
2565 functions->Viewport = r200Viewport;
2566 }
2567
2568
2569 void r200InitTnlFuncs( GLcontext *ctx )
2570 {
2571 TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange = r200UpdateMaterial;
2572 TNL_CONTEXT(ctx)->Driver.RunPipeline = r200WrapRunPipeline;
2573 }