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