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