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