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