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