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