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