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