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