updates to dri drivers for recent stencil changes
[mesa.git] / src / mesa / drivers / dri / radeon / radeon_state.c
1 /* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_state.c,v 1.8 2002/12/16 16:18:58 dawes Exp $ */
2 /**************************************************************************
3
4 Copyright 2000, 2001 VA Linux Systems Inc., Fremont, California.
5
6 All Rights Reserved.
7
8 Permission is hereby granted, free of charge, to any person obtaining
9 a copy of this software and associated documentation files (the
10 "Software"), to deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify, merge, publish,
12 distribute, sublicense, and/or sell copies of the Software, and to
13 permit persons to whom the Software is furnished to do so, subject to
14 the following conditions:
15
16 The above copyright notice and this permission notice (including the
17 next paragraph) shall be included in all copies or substantial
18 portions of the Software.
19
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
24 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
28 **************************************************************************/
29
30 /*
31 * Authors:
32 * Gareth Hughes <gareth@valinux.com>
33 * Keith Whitwell <keith@tungstengraphics.com>
34 */
35
36 #include "glheader.h"
37 #include "imports.h"
38 #include "api_arrayelt.h"
39 #include "enums.h"
40 #include "light.h"
41 #include "state.h"
42 #include "context.h"
43
44 #include "array_cache/acache.h"
45 #include "tnl/tnl.h"
46 #include "tnl/t_pipeline.h"
47 #include "swrast_setup/swrast_setup.h"
48
49 #include "radeon_context.h"
50 #include "radeon_ioctl.h"
51 #include "radeon_state.h"
52 #include "radeon_tcl.h"
53 #include "radeon_tex.h"
54 #include "radeon_swtcl.h"
55 #include "radeon_vtxfmt.h"
56 #include "drirenderbuffer.h"
57
58 static void radeonUpdateSpecular( GLcontext *ctx );
59
60 /* =============================================================
61 * Alpha blending
62 */
63
64 static void radeonAlphaFunc( GLcontext *ctx, GLenum func, GLfloat ref )
65 {
66 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
67 int pp_misc = rmesa->hw.ctx.cmd[CTX_PP_MISC];
68 GLubyte refByte;
69
70 CLAMPED_FLOAT_TO_UBYTE(refByte, ref);
71
72 RADEON_STATECHANGE( rmesa, ctx );
73
74 pp_misc &= ~(RADEON_ALPHA_TEST_OP_MASK | RADEON_REF_ALPHA_MASK);
75 pp_misc |= (refByte & RADEON_REF_ALPHA_MASK);
76
77 switch ( func ) {
78 case GL_NEVER:
79 pp_misc |= RADEON_ALPHA_TEST_FAIL;
80 break;
81 case GL_LESS:
82 pp_misc |= RADEON_ALPHA_TEST_LESS;
83 break;
84 case GL_EQUAL:
85 pp_misc |= RADEON_ALPHA_TEST_EQUAL;
86 break;
87 case GL_LEQUAL:
88 pp_misc |= RADEON_ALPHA_TEST_LEQUAL;
89 break;
90 case GL_GREATER:
91 pp_misc |= RADEON_ALPHA_TEST_GREATER;
92 break;
93 case GL_NOTEQUAL:
94 pp_misc |= RADEON_ALPHA_TEST_NEQUAL;
95 break;
96 case GL_GEQUAL:
97 pp_misc |= RADEON_ALPHA_TEST_GEQUAL;
98 break;
99 case GL_ALWAYS:
100 pp_misc |= RADEON_ALPHA_TEST_PASS;
101 break;
102 }
103
104 rmesa->hw.ctx.cmd[CTX_PP_MISC] = pp_misc;
105 }
106
107 static void radeonBlendEquationSeparate( GLcontext *ctx,
108 GLenum modeRGB, GLenum modeA )
109 {
110 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
111 GLuint b = rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] & ~RADEON_COMB_FCN_MASK;
112 GLboolean fallback = GL_FALSE;
113
114 assert( modeRGB == modeA );
115
116 switch ( modeRGB ) {
117 case GL_FUNC_ADD:
118 case GL_LOGIC_OP:
119 b |= RADEON_COMB_FCN_ADD_CLAMP;
120 break;
121
122 case GL_FUNC_SUBTRACT:
123 b |= RADEON_COMB_FCN_SUB_CLAMP;
124 break;
125
126 default:
127 if (ctx->Color.BlendEnabled)
128 fallback = GL_TRUE;
129 else
130 b |= RADEON_COMB_FCN_ADD_CLAMP;
131 break;
132 }
133
134 FALLBACK( rmesa, RADEON_FALLBACK_BLEND_EQ, fallback );
135 if ( !fallback ) {
136 RADEON_STATECHANGE( rmesa, ctx );
137 rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = b;
138 if ( ctx->Color._LogicOpEnabled ) {
139 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_ROP_ENABLE;
140 } else {
141 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ROP_ENABLE;
142 }
143 }
144 }
145
146 static void radeonBlendFuncSeparate( GLcontext *ctx,
147 GLenum sfactorRGB, GLenum dfactorRGB,
148 GLenum sfactorA, GLenum dfactorA )
149 {
150 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
151 GLuint b = rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] &
152 ~(RADEON_SRC_BLEND_MASK | RADEON_DST_BLEND_MASK);
153 GLboolean fallback = GL_FALSE;
154
155 switch ( ctx->Color.BlendSrcRGB ) {
156 case GL_ZERO:
157 b |= RADEON_SRC_BLEND_GL_ZERO;
158 break;
159 case GL_ONE:
160 b |= RADEON_SRC_BLEND_GL_ONE;
161 break;
162 case GL_DST_COLOR:
163 b |= RADEON_SRC_BLEND_GL_DST_COLOR;
164 break;
165 case GL_ONE_MINUS_DST_COLOR:
166 b |= RADEON_SRC_BLEND_GL_ONE_MINUS_DST_COLOR;
167 break;
168 case GL_SRC_COLOR:
169 b |= RADEON_SRC_BLEND_GL_SRC_COLOR;
170 break;
171 case GL_ONE_MINUS_SRC_COLOR:
172 b |= RADEON_SRC_BLEND_GL_ONE_MINUS_SRC_COLOR;
173 break;
174 case GL_SRC_ALPHA:
175 b |= RADEON_SRC_BLEND_GL_SRC_ALPHA;
176 break;
177 case GL_ONE_MINUS_SRC_ALPHA:
178 b |= RADEON_SRC_BLEND_GL_ONE_MINUS_SRC_ALPHA;
179 break;
180 case GL_DST_ALPHA:
181 b |= RADEON_SRC_BLEND_GL_DST_ALPHA;
182 break;
183 case GL_ONE_MINUS_DST_ALPHA:
184 b |= RADEON_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA;
185 break;
186 case GL_SRC_ALPHA_SATURATE:
187 b |= RADEON_SRC_BLEND_GL_SRC_ALPHA_SATURATE;
188 break;
189 case GL_CONSTANT_COLOR:
190 case GL_ONE_MINUS_CONSTANT_COLOR:
191 case GL_CONSTANT_ALPHA:
192 case GL_ONE_MINUS_CONSTANT_ALPHA:
193 if (ctx->Color.BlendEnabled)
194 fallback = GL_TRUE;
195 else
196 b |= RADEON_SRC_BLEND_GL_ONE;
197 break;
198 default:
199 break;
200 }
201
202 switch ( ctx->Color.BlendDstRGB ) {
203 case GL_ZERO:
204 b |= RADEON_DST_BLEND_GL_ZERO;
205 break;
206 case GL_ONE:
207 b |= RADEON_DST_BLEND_GL_ONE;
208 break;
209 case GL_SRC_COLOR:
210 b |= RADEON_DST_BLEND_GL_SRC_COLOR;
211 break;
212 case GL_ONE_MINUS_SRC_COLOR:
213 b |= RADEON_DST_BLEND_GL_ONE_MINUS_SRC_COLOR;
214 break;
215 case GL_SRC_ALPHA:
216 b |= RADEON_DST_BLEND_GL_SRC_ALPHA;
217 break;
218 case GL_ONE_MINUS_SRC_ALPHA:
219 b |= RADEON_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA;
220 break;
221 case GL_DST_COLOR:
222 b |= RADEON_DST_BLEND_GL_DST_COLOR;
223 break;
224 case GL_ONE_MINUS_DST_COLOR:
225 b |= RADEON_DST_BLEND_GL_ONE_MINUS_DST_COLOR;
226 break;
227 case GL_DST_ALPHA:
228 b |= RADEON_DST_BLEND_GL_DST_ALPHA;
229 break;
230 case GL_ONE_MINUS_DST_ALPHA:
231 b |= RADEON_DST_BLEND_GL_ONE_MINUS_DST_ALPHA;
232 break;
233 case GL_CONSTANT_COLOR:
234 case GL_ONE_MINUS_CONSTANT_COLOR:
235 case GL_CONSTANT_ALPHA:
236 case GL_ONE_MINUS_CONSTANT_ALPHA:
237 if (ctx->Color.BlendEnabled)
238 fallback = GL_TRUE;
239 else
240 b |= RADEON_DST_BLEND_GL_ZERO;
241 break;
242 default:
243 break;
244 }
245
246 FALLBACK( rmesa, RADEON_FALLBACK_BLEND_FUNC, fallback );
247 if ( !fallback ) {
248 RADEON_STATECHANGE( rmesa, ctx );
249 rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = b;
250 }
251 }
252
253
254 /* =============================================================
255 * Depth testing
256 */
257
258 static void radeonDepthFunc( GLcontext *ctx, GLenum func )
259 {
260 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
261
262 RADEON_STATECHANGE( rmesa, ctx );
263 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~RADEON_Z_TEST_MASK;
264
265 switch ( ctx->Depth.Func ) {
266 case GL_NEVER:
267 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_NEVER;
268 break;
269 case GL_LESS:
270 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_LESS;
271 break;
272 case GL_EQUAL:
273 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_EQUAL;
274 break;
275 case GL_LEQUAL:
276 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_LEQUAL;
277 break;
278 case GL_GREATER:
279 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_GREATER;
280 break;
281 case GL_NOTEQUAL:
282 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_NEQUAL;
283 break;
284 case GL_GEQUAL:
285 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_GEQUAL;
286 break;
287 case GL_ALWAYS:
288 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_ALWAYS;
289 break;
290 }
291 }
292
293
294 static void radeonDepthMask( GLcontext *ctx, GLboolean flag )
295 {
296 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
297 RADEON_STATECHANGE( rmesa, ctx );
298
299 if ( ctx->Depth.Mask ) {
300 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_WRITE_ENABLE;
301 } else {
302 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~RADEON_Z_WRITE_ENABLE;
303 }
304 }
305
306 static void radeonClearDepth( GLcontext *ctx, GLclampd d )
307 {
308 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
309 GLuint format = (rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &
310 RADEON_DEPTH_FORMAT_MASK);
311
312 switch ( format ) {
313 case RADEON_DEPTH_FORMAT_16BIT_INT_Z:
314 rmesa->state.depth.clear = d * 0x0000ffff;
315 break;
316 case RADEON_DEPTH_FORMAT_24BIT_INT_Z:
317 rmesa->state.depth.clear = d * 0x00ffffff;
318 break;
319 }
320 }
321
322
323 /* =============================================================
324 * Fog
325 */
326
327
328 static void radeonFogfv( GLcontext *ctx, GLenum pname, const GLfloat *param )
329 {
330 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
331 union { int i; float f; } c, d;
332 GLchan col[4];
333
334 switch (pname) {
335 case GL_FOG_MODE:
336 if (!ctx->Fog.Enabled)
337 return;
338 RADEON_STATECHANGE(rmesa, tcl);
339 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_TCL_FOG_MASK;
340 switch (ctx->Fog.Mode) {
341 case GL_LINEAR:
342 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_TCL_FOG_LINEAR;
343 break;
344 case GL_EXP:
345 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_TCL_FOG_EXP;
346 break;
347 case GL_EXP2:
348 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_TCL_FOG_EXP2;
349 break;
350 default:
351 return;
352 }
353 /* fallthrough */
354 case GL_FOG_DENSITY:
355 case GL_FOG_START:
356 case GL_FOG_END:
357 if (!ctx->Fog.Enabled)
358 return;
359 c.i = rmesa->hw.fog.cmd[FOG_C];
360 d.i = rmesa->hw.fog.cmd[FOG_D];
361 switch (ctx->Fog.Mode) {
362 case GL_EXP:
363 c.f = 0.0;
364 /* While this is the opposite sign from the DDK, it makes the fog test
365 * pass, and matches r200.
366 */
367 d.f = -ctx->Fog.Density;
368 break;
369 case GL_EXP2:
370 c.f = 0.0;
371 d.f = -(ctx->Fog.Density * ctx->Fog.Density);
372 break;
373 case GL_LINEAR:
374 if (ctx->Fog.Start == ctx->Fog.End) {
375 c.f = 1.0F;
376 d.f = 1.0F;
377 } else {
378 c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start);
379 /* While this is the opposite sign from the DDK, it makes the fog
380 * test pass, and matches r200.
381 */
382 d.f = -1.0/(ctx->Fog.End-ctx->Fog.Start);
383 }
384 break;
385 default:
386 break;
387 }
388 if (c.i != rmesa->hw.fog.cmd[FOG_C] || d.i != rmesa->hw.fog.cmd[FOG_D]) {
389 RADEON_STATECHANGE( rmesa, fog );
390 rmesa->hw.fog.cmd[FOG_C] = c.i;
391 rmesa->hw.fog.cmd[FOG_D] = d.i;
392 }
393 break;
394 case GL_FOG_COLOR:
395 RADEON_STATECHANGE( rmesa, ctx );
396 UNCLAMPED_FLOAT_TO_RGB_CHAN( col, ctx->Fog.Color );
397 rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] &= ~RADEON_FOG_COLOR_MASK;
398 rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] |=
399 radeonPackColor( 4, col[0], col[1], col[2], 0 );
400 break;
401 case GL_FOG_COORD_SRC:
402 radeonUpdateSpecular( ctx );
403 break;
404 default:
405 return;
406 }
407 }
408
409
410 /* =============================================================
411 * Scissoring
412 */
413
414
415 static GLboolean intersect_rect( drm_clip_rect_t *out,
416 drm_clip_rect_t *a,
417 drm_clip_rect_t *b )
418 {
419 *out = *a;
420 if ( b->x1 > out->x1 ) out->x1 = b->x1;
421 if ( b->y1 > out->y1 ) out->y1 = b->y1;
422 if ( b->x2 < out->x2 ) out->x2 = b->x2;
423 if ( b->y2 < out->y2 ) out->y2 = b->y2;
424 if ( out->x1 >= out->x2 ) return GL_FALSE;
425 if ( out->y1 >= out->y2 ) return GL_FALSE;
426 return GL_TRUE;
427 }
428
429
430 void radeonRecalcScissorRects( radeonContextPtr rmesa )
431 {
432 drm_clip_rect_t *out;
433 int i;
434
435 /* Grow cliprect store?
436 */
437 if (rmesa->state.scissor.numAllocedClipRects < rmesa->numClipRects) {
438 while (rmesa->state.scissor.numAllocedClipRects < rmesa->numClipRects) {
439 rmesa->state.scissor.numAllocedClipRects += 1; /* zero case */
440 rmesa->state.scissor.numAllocedClipRects *= 2;
441 }
442
443 if (rmesa->state.scissor.pClipRects)
444 FREE(rmesa->state.scissor.pClipRects);
445
446 rmesa->state.scissor.pClipRects =
447 MALLOC( rmesa->state.scissor.numAllocedClipRects *
448 sizeof(drm_clip_rect_t) );
449
450 if ( rmesa->state.scissor.pClipRects == NULL ) {
451 rmesa->state.scissor.numAllocedClipRects = 0;
452 return;
453 }
454 }
455
456 out = rmesa->state.scissor.pClipRects;
457 rmesa->state.scissor.numClipRects = 0;
458
459 for ( i = 0 ; i < rmesa->numClipRects ; i++ ) {
460 if ( intersect_rect( out,
461 &rmesa->pClipRects[i],
462 &rmesa->state.scissor.rect ) ) {
463 rmesa->state.scissor.numClipRects++;
464 out++;
465 }
466 }
467 }
468
469
470 static void radeonUpdateScissor( GLcontext *ctx )
471 {
472 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
473
474 if ( rmesa->dri.drawable ) {
475 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
476
477 int x = ctx->Scissor.X;
478 int y = dPriv->h - ctx->Scissor.Y - ctx->Scissor.Height;
479 int w = ctx->Scissor.X + ctx->Scissor.Width - 1;
480 int h = dPriv->h - ctx->Scissor.Y - 1;
481
482 rmesa->state.scissor.rect.x1 = x + dPriv->x;
483 rmesa->state.scissor.rect.y1 = y + dPriv->y;
484 rmesa->state.scissor.rect.x2 = w + dPriv->x + 1;
485 rmesa->state.scissor.rect.y2 = h + dPriv->y + 1;
486
487 radeonRecalcScissorRects( rmesa );
488 }
489 }
490
491
492 static void radeonScissor( GLcontext *ctx,
493 GLint x, GLint y, GLsizei w, GLsizei h )
494 {
495 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
496
497 if ( ctx->Scissor.Enabled ) {
498 RADEON_FIREVERTICES( rmesa ); /* don't pipeline cliprect changes */
499 radeonUpdateScissor( ctx );
500 }
501
502 }
503
504
505 /* =============================================================
506 * Culling
507 */
508
509 static void radeonCullFace( GLcontext *ctx, GLenum unused )
510 {
511 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
512 GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL];
513 GLuint t = rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL];
514
515 s |= RADEON_FFACE_SOLID | RADEON_BFACE_SOLID;
516 t &= ~(RADEON_CULL_FRONT | RADEON_CULL_BACK);
517
518 if ( ctx->Polygon.CullFlag ) {
519 switch ( ctx->Polygon.CullFaceMode ) {
520 case GL_FRONT:
521 s &= ~RADEON_FFACE_SOLID;
522 t |= RADEON_CULL_FRONT;
523 break;
524 case GL_BACK:
525 s &= ~RADEON_BFACE_SOLID;
526 t |= RADEON_CULL_BACK;
527 break;
528 case GL_FRONT_AND_BACK:
529 s &= ~(RADEON_FFACE_SOLID | RADEON_BFACE_SOLID);
530 t |= (RADEON_CULL_FRONT | RADEON_CULL_BACK);
531 break;
532 }
533 }
534
535 if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) {
536 RADEON_STATECHANGE(rmesa, set );
537 rmesa->hw.set.cmd[SET_SE_CNTL] = s;
538 }
539
540 if ( rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] != t ) {
541 RADEON_STATECHANGE(rmesa, tcl );
542 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] = t;
543 }
544 }
545
546 static void radeonFrontFace( GLcontext *ctx, GLenum mode )
547 {
548 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
549
550 RADEON_STATECHANGE( rmesa, set );
551 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_FFACE_CULL_DIR_MASK;
552
553 RADEON_STATECHANGE( rmesa, tcl );
554 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_CULL_FRONT_IS_CCW;
555
556 switch ( mode ) {
557 case GL_CW:
558 rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_FFACE_CULL_CW;
559 break;
560 case GL_CCW:
561 rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_FFACE_CULL_CCW;
562 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_CULL_FRONT_IS_CCW;
563 break;
564 }
565 }
566
567
568 /* =============================================================
569 * Line state
570 */
571 static void radeonLineWidth( GLcontext *ctx, GLfloat widthf )
572 {
573 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
574
575 RADEON_STATECHANGE( rmesa, lin );
576 RADEON_STATECHANGE( rmesa, set );
577
578 /* Line width is stored in U6.4 format.
579 */
580 rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] = (GLuint)(widthf * 16.0);
581 if ( widthf > 1.0 ) {
582 rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_WIDELINE_ENABLE;
583 } else {
584 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_WIDELINE_ENABLE;
585 }
586 }
587
588 static void radeonLineStipple( GLcontext *ctx, GLint factor, GLushort pattern )
589 {
590 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
591
592 RADEON_STATECHANGE( rmesa, lin );
593 rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] =
594 ((((GLuint)factor & 0xff) << 16) | ((GLuint)pattern));
595 }
596
597
598 /* =============================================================
599 * Masks
600 */
601 static void radeonColorMask( GLcontext *ctx,
602 GLboolean r, GLboolean g,
603 GLboolean b, GLboolean a )
604 {
605 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
606 GLuint mask = radeonPackColor( rmesa->radeonScreen->cpp,
607 ctx->Color.ColorMask[RCOMP],
608 ctx->Color.ColorMask[GCOMP],
609 ctx->Color.ColorMask[BCOMP],
610 ctx->Color.ColorMask[ACOMP] );
611
612 if ( rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] != mask ) {
613 RADEON_STATECHANGE( rmesa, msk );
614 rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] = mask;
615 }
616 }
617
618
619 /* =============================================================
620 * Polygon state
621 */
622
623 static void radeonPolygonOffset( GLcontext *ctx,
624 GLfloat factor, GLfloat units )
625 {
626 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
627 float_ui32_type constant = { units * rmesa->state.depth.scale };
628 float_ui32_type factoru = { factor };
629
630 RADEON_STATECHANGE( rmesa, zbs );
631 rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_FACTOR] = factoru.ui32;
632 rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_CONSTANT] = constant.ui32;
633 }
634
635 static void radeonPolygonStipple( GLcontext *ctx, const GLubyte *mask )
636 {
637 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
638 GLuint i;
639 drm_radeon_stipple_t stipple;
640
641 /* Must flip pattern upside down.
642 */
643 for ( i = 0 ; i < 32 ; i++ ) {
644 rmesa->state.stipple.mask[31 - i] = ((GLuint *) mask)[i];
645 }
646
647 /* TODO: push this into cmd mechanism
648 */
649 RADEON_FIREVERTICES( rmesa );
650 LOCK_HARDWARE( rmesa );
651
652 /* FIXME: Use window x,y offsets into stipple RAM.
653 */
654 stipple.mask = rmesa->state.stipple.mask;
655 drmCommandWrite( rmesa->dri.fd, DRM_RADEON_STIPPLE,
656 &stipple, sizeof(drm_radeon_stipple_t) );
657 UNLOCK_HARDWARE( rmesa );
658 }
659
660 static void radeonPolygonMode( GLcontext *ctx, GLenum face, GLenum mode )
661 {
662 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
663 GLboolean flag = (ctx->_TriangleCaps & DD_TRI_UNFILLED) != 0;
664
665 /* Can't generally do unfilled via tcl, but some good special
666 * cases work.
667 */
668 TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_UNFILLED, flag);
669 if (rmesa->TclFallback) {
670 radeonChooseRenderState( ctx );
671 radeonChooseVertexState( ctx );
672 }
673 }
674
675
676 /* =============================================================
677 * Rendering attributes
678 *
679 * We really don't want to recalculate all this every time we bind a
680 * texture. These things shouldn't change all that often, so it makes
681 * sense to break them out of the core texture state update routines.
682 */
683
684 /* Examine lighting and texture state to determine if separate specular
685 * should be enabled.
686 */
687 static void radeonUpdateSpecular( GLcontext *ctx )
688 {
689 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
690 u_int32_t p = rmesa->hw.ctx.cmd[CTX_PP_CNTL];
691 GLuint flag = 0;
692
693 RADEON_STATECHANGE( rmesa, tcl );
694
695 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &= ~RADEON_TCL_COMPUTE_SPECULAR;
696 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &= ~RADEON_TCL_COMPUTE_DIFFUSE;
697 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &= ~RADEON_TCL_VTX_PK_SPEC;
698 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &= ~RADEON_TCL_VTX_PK_DIFFUSE;
699 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_LIGHTING_ENABLE;
700
701 p &= ~RADEON_SPECULAR_ENABLE;
702
703 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_DIFFUSE_SPECULAR_COMBINE;
704
705
706 if (ctx->Light.Enabled &&
707 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) {
708 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_SPECULAR;
709 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_DIFFUSE;
710 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC;
711 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE;
712 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE;
713 p |= RADEON_SPECULAR_ENABLE;
714 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &=
715 ~RADEON_DIFFUSE_SPECULAR_COMBINE;
716 }
717 else if (ctx->Light.Enabled) {
718 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_DIFFUSE;
719 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE;
720 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE;
721 } else if (ctx->Fog.ColorSumEnabled ) {
722 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC;
723 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE;
724 p |= RADEON_SPECULAR_ENABLE;
725 } else {
726 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE;
727 }
728
729 if (ctx->Fog.Enabled) {
730 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC;
731 if (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH) {
732 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_SPECULAR;
733 /* Bizzare: have to leave lighting enabled to get fog. */
734 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE;
735 }
736 else {
737 /* cannot do tcl fog factor calculation with fog coord source
738 * (send precomputed factors). Cannot use precomputed fog
739 * factors together with tcl spec light (need tcl fallback) */
740 flag = (rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &
741 RADEON_TCL_COMPUTE_SPECULAR) != 0;
742 }
743 }
744
745 TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_FOGCOORDSPEC, flag);
746
747 if (NEED_SECONDARY_COLOR(ctx)) {
748 assert( (p & RADEON_SPECULAR_ENABLE) != 0 );
749 } else {
750 assert( (p & RADEON_SPECULAR_ENABLE) == 0 );
751 }
752
753 if ( rmesa->hw.ctx.cmd[CTX_PP_CNTL] != p ) {
754 RADEON_STATECHANGE( rmesa, ctx );
755 rmesa->hw.ctx.cmd[CTX_PP_CNTL] = p;
756 }
757
758 /* Update vertex/render formats
759 */
760 if (rmesa->TclFallback) {
761 radeonChooseRenderState( ctx );
762 radeonChooseVertexState( ctx );
763 }
764 }
765
766
767 /* =============================================================
768 * Materials
769 */
770
771
772 /* Update on colormaterial, material emmissive/ambient,
773 * lightmodel.globalambient
774 */
775 static void update_global_ambient( GLcontext *ctx )
776 {
777 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
778 float *fcmd = (float *)RADEON_DB_STATE( glt );
779
780 /* Need to do more if both emmissive & ambient are PREMULT:
781 * Hope this is not needed for MULT
782 */
783 if ((rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &
784 ((3 << RADEON_EMISSIVE_SOURCE_SHIFT) |
785 (3 << RADEON_AMBIENT_SOURCE_SHIFT))) == 0)
786 {
787 COPY_3V( &fcmd[GLT_RED],
788 ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION]);
789 ACC_SCALE_3V( &fcmd[GLT_RED],
790 ctx->Light.Model.Ambient,
791 ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT]);
792 }
793 else
794 {
795 COPY_3V( &fcmd[GLT_RED], ctx->Light.Model.Ambient );
796 }
797
798 RADEON_DB_STATECHANGE(rmesa, &rmesa->hw.glt);
799 }
800
801 /* Update on change to
802 * - light[p].colors
803 * - light[p].enabled
804 */
805 static void update_light_colors( GLcontext *ctx, GLuint p )
806 {
807 struct gl_light *l = &ctx->Light.Light[p];
808
809 /* fprintf(stderr, "%s\n", __FUNCTION__); */
810
811 if (l->Enabled) {
812 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
813 float *fcmd = (float *)RADEON_DB_STATE( lit[p] );
814
815 COPY_4V( &fcmd[LIT_AMBIENT_RED], l->Ambient );
816 COPY_4V( &fcmd[LIT_DIFFUSE_RED], l->Diffuse );
817 COPY_4V( &fcmd[LIT_SPECULAR_RED], l->Specular );
818
819 RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
820 }
821 }
822
823 /* Also fallback for asym colormaterial mode in twoside lighting...
824 */
825 static void check_twoside_fallback( GLcontext *ctx )
826 {
827 GLboolean fallback = GL_FALSE;
828 GLint i;
829
830 if (ctx->Light.Enabled && ctx->Light.Model.TwoSide) {
831 if (ctx->Light.ColorMaterialEnabled &&
832 (ctx->Light.ColorMaterialBitmask & BACK_MATERIAL_BITS) !=
833 ((ctx->Light.ColorMaterialBitmask & FRONT_MATERIAL_BITS)<<1))
834 fallback = GL_TRUE;
835 else {
836 for (i = MAT_ATTRIB_FRONT_AMBIENT; i < MAT_ATTRIB_FRONT_INDEXES; i+=2)
837 if (memcmp( ctx->Light.Material.Attrib[i],
838 ctx->Light.Material.Attrib[i+1],
839 sizeof(GLfloat)*4) != 0) {
840 fallback = GL_TRUE;
841 break;
842 }
843 }
844 }
845
846 TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_LIGHT_TWOSIDE, fallback );
847 }
848
849
850 static void radeonColorMaterial( GLcontext *ctx, GLenum face, GLenum mode )
851 {
852 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
853 GLuint light_model_ctl1 = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL];
854
855 light_model_ctl1 &= ~((3 << RADEON_EMISSIVE_SOURCE_SHIFT) |
856 (3 << RADEON_AMBIENT_SOURCE_SHIFT) |
857 (3 << RADEON_DIFFUSE_SOURCE_SHIFT) |
858 (3 << RADEON_SPECULAR_SOURCE_SHIFT));
859
860 if (ctx->Light.ColorMaterialEnabled) {
861 GLuint mask = ctx->Light.ColorMaterialBitmask;
862
863 if (mask & MAT_BIT_FRONT_EMISSION) {
864 light_model_ctl1 |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE <<
865 RADEON_EMISSIVE_SOURCE_SHIFT);
866 }
867 else {
868 light_model_ctl1 |= (RADEON_LM_SOURCE_STATE_MULT <<
869 RADEON_EMISSIVE_SOURCE_SHIFT);
870 }
871
872 if (mask & MAT_BIT_FRONT_AMBIENT) {
873 light_model_ctl1 |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE <<
874 RADEON_AMBIENT_SOURCE_SHIFT);
875 }
876 else {
877 light_model_ctl1 |= (RADEON_LM_SOURCE_STATE_MULT <<
878 RADEON_AMBIENT_SOURCE_SHIFT);
879 }
880
881 if (mask & MAT_BIT_FRONT_DIFFUSE) {
882 light_model_ctl1 |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE <<
883 RADEON_DIFFUSE_SOURCE_SHIFT);
884 }
885 else {
886 light_model_ctl1 |= (RADEON_LM_SOURCE_STATE_MULT <<
887 RADEON_DIFFUSE_SOURCE_SHIFT);
888 }
889
890 if (mask & MAT_BIT_FRONT_SPECULAR) {
891 light_model_ctl1 |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE <<
892 RADEON_SPECULAR_SOURCE_SHIFT);
893 }
894 else {
895 light_model_ctl1 |= (RADEON_LM_SOURCE_STATE_MULT <<
896 RADEON_SPECULAR_SOURCE_SHIFT);
897 }
898 }
899 else {
900 /* Default to MULT:
901 */
902 light_model_ctl1 |= (RADEON_LM_SOURCE_STATE_MULT << RADEON_EMISSIVE_SOURCE_SHIFT) |
903 (RADEON_LM_SOURCE_STATE_MULT << RADEON_AMBIENT_SOURCE_SHIFT) |
904 (RADEON_LM_SOURCE_STATE_MULT << RADEON_DIFFUSE_SOURCE_SHIFT) |
905 (RADEON_LM_SOURCE_STATE_MULT << RADEON_SPECULAR_SOURCE_SHIFT);
906 }
907
908 if (light_model_ctl1 != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]) {
909 RADEON_STATECHANGE( rmesa, tcl );
910 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] = light_model_ctl1;
911 }
912 }
913
914 void radeonUpdateMaterial( GLcontext *ctx )
915 {
916 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
917 GLfloat (*mat)[4] = ctx->Light.Material.Attrib;
918 GLfloat *fcmd = (GLfloat *)RADEON_DB_STATE( mtl );
919 GLuint mask = ~0;
920
921 if (ctx->Light.ColorMaterialEnabled)
922 mask &= ~ctx->Light.ColorMaterialBitmask;
923
924 if (RADEON_DEBUG & DEBUG_STATE)
925 fprintf(stderr, "%s\n", __FUNCTION__);
926
927
928 if (mask & MAT_BIT_FRONT_EMISSION) {
929 fcmd[MTL_EMMISSIVE_RED] = mat[MAT_ATTRIB_FRONT_EMISSION][0];
930 fcmd[MTL_EMMISSIVE_GREEN] = mat[MAT_ATTRIB_FRONT_EMISSION][1];
931 fcmd[MTL_EMMISSIVE_BLUE] = mat[MAT_ATTRIB_FRONT_EMISSION][2];
932 fcmd[MTL_EMMISSIVE_ALPHA] = mat[MAT_ATTRIB_FRONT_EMISSION][3];
933 }
934 if (mask & MAT_BIT_FRONT_AMBIENT) {
935 fcmd[MTL_AMBIENT_RED] = mat[MAT_ATTRIB_FRONT_AMBIENT][0];
936 fcmd[MTL_AMBIENT_GREEN] = mat[MAT_ATTRIB_FRONT_AMBIENT][1];
937 fcmd[MTL_AMBIENT_BLUE] = mat[MAT_ATTRIB_FRONT_AMBIENT][2];
938 fcmd[MTL_AMBIENT_ALPHA] = mat[MAT_ATTRIB_FRONT_AMBIENT][3];
939 }
940 if (mask & MAT_BIT_FRONT_DIFFUSE) {
941 fcmd[MTL_DIFFUSE_RED] = mat[MAT_ATTRIB_FRONT_DIFFUSE][0];
942 fcmd[MTL_DIFFUSE_GREEN] = mat[MAT_ATTRIB_FRONT_DIFFUSE][1];
943 fcmd[MTL_DIFFUSE_BLUE] = mat[MAT_ATTRIB_FRONT_DIFFUSE][2];
944 fcmd[MTL_DIFFUSE_ALPHA] = mat[MAT_ATTRIB_FRONT_DIFFUSE][3];
945 }
946 if (mask & MAT_BIT_FRONT_SPECULAR) {
947 fcmd[MTL_SPECULAR_RED] = mat[MAT_ATTRIB_FRONT_SPECULAR][0];
948 fcmd[MTL_SPECULAR_GREEN] = mat[MAT_ATTRIB_FRONT_SPECULAR][1];
949 fcmd[MTL_SPECULAR_BLUE] = mat[MAT_ATTRIB_FRONT_SPECULAR][2];
950 fcmd[MTL_SPECULAR_ALPHA] = mat[MAT_ATTRIB_FRONT_SPECULAR][3];
951 }
952 if (mask & MAT_BIT_FRONT_SHININESS) {
953 fcmd[MTL_SHININESS] = mat[MAT_ATTRIB_FRONT_SHININESS][0];
954 }
955
956 RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mtl );
957
958 check_twoside_fallback( ctx );
959 /* update_global_ambient( ctx );*/
960 }
961
962 /* _NEW_LIGHT
963 * _NEW_MODELVIEW
964 * _MESA_NEW_NEED_EYE_COORDS
965 *
966 * Uses derived state from mesa:
967 * _VP_inf_norm
968 * _h_inf_norm
969 * _Position
970 * _NormDirection
971 * _ModelViewInvScale
972 * _NeedEyeCoords
973 * _EyeZDir
974 *
975 * which are calculated in light.c and are correct for the current
976 * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
977 * and _MESA_NEW_NEED_EYE_COORDS.
978 */
979 static void update_light( GLcontext *ctx )
980 {
981 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
982
983 /* Have to check these, or have an automatic shortcircuit mechanism
984 * to remove noop statechanges. (Or just do a better job on the
985 * front end).
986 */
987 {
988 GLuint tmp = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL];
989
990 if (ctx->_NeedEyeCoords)
991 tmp &= ~RADEON_LIGHT_IN_MODELSPACE;
992 else
993 tmp |= RADEON_LIGHT_IN_MODELSPACE;
994
995
996 /* Leave this test disabled: (unexplained q3 lockup) (even with
997 new packets)
998 */
999 if (tmp != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL])
1000 {
1001 RADEON_STATECHANGE( rmesa, tcl );
1002 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] = tmp;
1003 }
1004 }
1005
1006 {
1007 GLfloat *fcmd = (GLfloat *)RADEON_DB_STATE( eye );
1008 fcmd[EYE_X] = ctx->_EyeZDir[0];
1009 fcmd[EYE_Y] = ctx->_EyeZDir[1];
1010 fcmd[EYE_Z] = - ctx->_EyeZDir[2];
1011 fcmd[EYE_RESCALE_FACTOR] = ctx->_ModelViewInvScale;
1012 RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.eye );
1013 }
1014
1015
1016
1017 if (ctx->Light.Enabled) {
1018 GLint p;
1019 for (p = 0 ; p < MAX_LIGHTS; p++) {
1020 if (ctx->Light.Light[p].Enabled) {
1021 struct gl_light *l = &ctx->Light.Light[p];
1022 GLfloat *fcmd = (GLfloat *)RADEON_DB_STATE( lit[p] );
1023
1024 if (l->EyePosition[3] == 0.0) {
1025 COPY_3FV( &fcmd[LIT_POSITION_X], l->_VP_inf_norm );
1026 COPY_3FV( &fcmd[LIT_DIRECTION_X], l->_h_inf_norm );
1027 fcmd[LIT_POSITION_W] = 0;
1028 fcmd[LIT_DIRECTION_W] = 0;
1029 } else {
1030 COPY_4V( &fcmd[LIT_POSITION_X], l->_Position );
1031 fcmd[LIT_DIRECTION_X] = -l->_NormDirection[0];
1032 fcmd[LIT_DIRECTION_Y] = -l->_NormDirection[1];
1033 fcmd[LIT_DIRECTION_Z] = -l->_NormDirection[2];
1034 fcmd[LIT_DIRECTION_W] = 0;
1035 }
1036
1037 RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
1038 }
1039 }
1040 }
1041 }
1042
1043 static void radeonLightfv( GLcontext *ctx, GLenum light,
1044 GLenum pname, const GLfloat *params )
1045 {
1046 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1047 GLint p = light - GL_LIGHT0;
1048 struct gl_light *l = &ctx->Light.Light[p];
1049 GLfloat *fcmd = (GLfloat *)rmesa->hw.lit[p].cmd;
1050
1051
1052 switch (pname) {
1053 case GL_AMBIENT:
1054 case GL_DIFFUSE:
1055 case GL_SPECULAR:
1056 update_light_colors( ctx, p );
1057 break;
1058
1059 case GL_SPOT_DIRECTION:
1060 /* picked up in update_light */
1061 break;
1062
1063 case GL_POSITION: {
1064 /* positions picked up in update_light, but can do flag here */
1065 GLuint flag;
1066 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1067
1068 /* FIXME: Set RANGE_ATTEN only when needed */
1069 if (p&1)
1070 flag = RADEON_LIGHT_1_IS_LOCAL;
1071 else
1072 flag = RADEON_LIGHT_0_IS_LOCAL;
1073
1074 RADEON_STATECHANGE(rmesa, tcl);
1075 if (l->EyePosition[3] != 0.0F)
1076 rmesa->hw.tcl.cmd[idx] |= flag;
1077 else
1078 rmesa->hw.tcl.cmd[idx] &= ~flag;
1079 break;
1080 }
1081
1082 case GL_SPOT_EXPONENT:
1083 RADEON_STATECHANGE(rmesa, lit[p]);
1084 fcmd[LIT_SPOT_EXPONENT] = params[0];
1085 break;
1086
1087 case GL_SPOT_CUTOFF: {
1088 GLuint flag = (p&1) ? RADEON_LIGHT_1_IS_SPOT : RADEON_LIGHT_0_IS_SPOT;
1089 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1090
1091 RADEON_STATECHANGE(rmesa, lit[p]);
1092 fcmd[LIT_SPOT_CUTOFF] = l->_CosCutoff;
1093
1094 RADEON_STATECHANGE(rmesa, tcl);
1095 if (l->SpotCutoff != 180.0F)
1096 rmesa->hw.tcl.cmd[idx] |= flag;
1097 else
1098 rmesa->hw.tcl.cmd[idx] &= ~flag;
1099
1100 break;
1101 }
1102
1103 case GL_CONSTANT_ATTENUATION:
1104 RADEON_STATECHANGE(rmesa, lit[p]);
1105 fcmd[LIT_ATTEN_CONST] = params[0];
1106 if ( params[0] == 0.0 )
1107 fcmd[LIT_ATTEN_CONST_INV] = FLT_MAX;
1108 else
1109 fcmd[LIT_ATTEN_CONST_INV] = 1.0 / params[0];
1110 break;
1111 case GL_LINEAR_ATTENUATION:
1112 RADEON_STATECHANGE(rmesa, lit[p]);
1113 fcmd[LIT_ATTEN_LINEAR] = params[0];
1114 break;
1115 case GL_QUADRATIC_ATTENUATION:
1116 RADEON_STATECHANGE(rmesa, lit[p]);
1117 fcmd[LIT_ATTEN_QUADRATIC] = params[0];
1118 break;
1119 default:
1120 return;
1121 }
1122
1123 /* Set RANGE_ATTEN only when needed */
1124 switch (pname) {
1125 case GL_POSITION:
1126 case GL_CONSTANT_ATTENUATION:
1127 case GL_LINEAR_ATTENUATION:
1128 case GL_QUADRATIC_ATTENUATION:
1129 {
1130 GLuint *icmd = (GLuint *)RADEON_DB_STATE( tcl );
1131 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1132 GLuint atten_flag = ( p&1 ) ? RADEON_LIGHT_1_ENABLE_RANGE_ATTEN
1133 : RADEON_LIGHT_0_ENABLE_RANGE_ATTEN;
1134 GLuint atten_const_flag = ( p&1 ) ? RADEON_LIGHT_1_CONSTANT_RANGE_ATTEN
1135 : RADEON_LIGHT_0_CONSTANT_RANGE_ATTEN;
1136
1137 if ( l->EyePosition[3] == 0.0F ||
1138 ( ( fcmd[LIT_ATTEN_CONST] == 0.0 || fcmd[LIT_ATTEN_CONST] == 1.0 ) &&
1139 fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) ) {
1140 /* Disable attenuation */
1141 icmd[idx] &= ~atten_flag;
1142 } else {
1143 if ( fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) {
1144 /* Enable only constant portion of attenuation calculation */
1145 icmd[idx] |= ( atten_flag | atten_const_flag );
1146 } else {
1147 /* Enable full attenuation calculation */
1148 icmd[idx] &= ~atten_const_flag;
1149 icmd[idx] |= atten_flag;
1150 }
1151 }
1152
1153 RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.tcl );
1154 break;
1155 }
1156 default:
1157 break;
1158 }
1159 }
1160
1161
1162
1163
1164 static void radeonLightModelfv( GLcontext *ctx, GLenum pname,
1165 const GLfloat *param )
1166 {
1167 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1168
1169 switch (pname) {
1170 case GL_LIGHT_MODEL_AMBIENT:
1171 update_global_ambient( ctx );
1172 break;
1173
1174 case GL_LIGHT_MODEL_LOCAL_VIEWER:
1175 RADEON_STATECHANGE( rmesa, tcl );
1176 if (ctx->Light.Model.LocalViewer)
1177 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LOCAL_VIEWER;
1178 else
1179 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_LOCAL_VIEWER;
1180 break;
1181
1182 case GL_LIGHT_MODEL_TWO_SIDE:
1183 RADEON_STATECHANGE( rmesa, tcl );
1184 if (ctx->Light.Model.TwoSide)
1185 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_LIGHT_TWOSIDE;
1186 else
1187 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_LIGHT_TWOSIDE;
1188
1189 check_twoside_fallback( ctx );
1190
1191 if (rmesa->TclFallback) {
1192 radeonChooseRenderState( ctx );
1193 radeonChooseVertexState( ctx );
1194 }
1195 break;
1196
1197 case GL_LIGHT_MODEL_COLOR_CONTROL:
1198 radeonUpdateSpecular(ctx);
1199 break;
1200
1201 default:
1202 break;
1203 }
1204 }
1205
1206 static void radeonShadeModel( GLcontext *ctx, GLenum mode )
1207 {
1208 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1209 GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL];
1210
1211 s &= ~(RADEON_DIFFUSE_SHADE_MASK |
1212 RADEON_ALPHA_SHADE_MASK |
1213 RADEON_SPECULAR_SHADE_MASK |
1214 RADEON_FOG_SHADE_MASK);
1215
1216 switch ( mode ) {
1217 case GL_FLAT:
1218 s |= (RADEON_DIFFUSE_SHADE_FLAT |
1219 RADEON_ALPHA_SHADE_FLAT |
1220 RADEON_SPECULAR_SHADE_FLAT |
1221 RADEON_FOG_SHADE_FLAT);
1222 break;
1223 case GL_SMOOTH:
1224 s |= (RADEON_DIFFUSE_SHADE_GOURAUD |
1225 RADEON_ALPHA_SHADE_GOURAUD |
1226 RADEON_SPECULAR_SHADE_GOURAUD |
1227 RADEON_FOG_SHADE_GOURAUD);
1228 break;
1229 default:
1230 return;
1231 }
1232
1233 if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) {
1234 RADEON_STATECHANGE( rmesa, set );
1235 rmesa->hw.set.cmd[SET_SE_CNTL] = s;
1236 }
1237 }
1238
1239
1240 /* =============================================================
1241 * User clip planes
1242 */
1243
1244 static void radeonClipPlane( GLcontext *ctx, GLenum plane, const GLfloat *eq )
1245 {
1246 GLint p = (GLint) plane - (GLint) GL_CLIP_PLANE0;
1247 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1248 GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
1249
1250 RADEON_STATECHANGE( rmesa, ucp[p] );
1251 rmesa->hw.ucp[p].cmd[UCP_X] = ip[0];
1252 rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1];
1253 rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2];
1254 rmesa->hw.ucp[p].cmd[UCP_W] = ip[3];
1255 }
1256
1257 static void radeonUpdateClipPlanes( GLcontext *ctx )
1258 {
1259 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1260 GLuint p;
1261
1262 for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
1263 if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
1264 GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
1265
1266 RADEON_STATECHANGE( rmesa, ucp[p] );
1267 rmesa->hw.ucp[p].cmd[UCP_X] = ip[0];
1268 rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1];
1269 rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2];
1270 rmesa->hw.ucp[p].cmd[UCP_W] = ip[3];
1271 }
1272 }
1273 }
1274
1275
1276 /* =============================================================
1277 * Stencil
1278 */
1279
1280 static void
1281 radeonStencilFuncSeparate( GLcontext *ctx, GLenum face, GLenum func,
1282 GLint ref, GLuint mask )
1283 {
1284 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1285 GLuint refmask = (((ctx->Stencil.Ref[0] & 0xff) << RADEON_STENCIL_REF_SHIFT) |
1286 ((ctx->Stencil.ValueMask[0] & 0xff) << RADEON_STENCIL_MASK_SHIFT));
1287
1288 RADEON_STATECHANGE( rmesa, ctx );
1289 RADEON_STATECHANGE( rmesa, msk );
1290
1291 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~RADEON_STENCIL_TEST_MASK;
1292 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~(RADEON_STENCIL_REF_MASK|
1293 RADEON_STENCIL_VALUE_MASK);
1294
1295 switch ( ctx->Stencil.Function[0] ) {
1296 case GL_NEVER:
1297 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_NEVER;
1298 break;
1299 case GL_LESS:
1300 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_LESS;
1301 break;
1302 case GL_EQUAL:
1303 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_EQUAL;
1304 break;
1305 case GL_LEQUAL:
1306 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_LEQUAL;
1307 break;
1308 case GL_GREATER:
1309 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_GREATER;
1310 break;
1311 case GL_NOTEQUAL:
1312 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_NEQUAL;
1313 break;
1314 case GL_GEQUAL:
1315 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_GEQUAL;
1316 break;
1317 case GL_ALWAYS:
1318 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_ALWAYS;
1319 break;
1320 }
1321
1322 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |= refmask;
1323 }
1324
1325 static void
1326 radeonStencilMaskSeparate( GLcontext *ctx, GLenum face, GLuint mask )
1327 {
1328 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1329
1330 RADEON_STATECHANGE( rmesa, msk );
1331 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~RADEON_STENCIL_WRITE_MASK;
1332 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |=
1333 ((ctx->Stencil.WriteMask[0] & 0xff) << RADEON_STENCIL_WRITEMASK_SHIFT);
1334 }
1335
1336 static void radeonStencilOpSeparate( GLcontext *ctx, GLenum face, GLenum fail,
1337 GLenum zfail, GLenum zpass )
1338 {
1339 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1340
1341 /* radeon 7200 have stencil bug, DEC and INC_WRAP will actually both do DEC_WRAP,
1342 and DEC_WRAP (and INVERT) will do INVERT. No way to get correct INC_WRAP and DEC,
1343 but DEC_WRAP can be fixed by using DEC and INC_WRAP at least use INC. */
1344
1345 GLuint tempRADEON_STENCIL_FAIL_DEC_WRAP;
1346 GLuint tempRADEON_STENCIL_FAIL_INC_WRAP;
1347 GLuint tempRADEON_STENCIL_ZFAIL_DEC_WRAP;
1348 GLuint tempRADEON_STENCIL_ZFAIL_INC_WRAP;
1349 GLuint tempRADEON_STENCIL_ZPASS_DEC_WRAP;
1350 GLuint tempRADEON_STENCIL_ZPASS_INC_WRAP;
1351
1352 if (rmesa->radeonScreen->chip_flags & RADEON_CHIPSET_BROKEN_STENCIL) {
1353 tempRADEON_STENCIL_FAIL_DEC_WRAP = RADEON_STENCIL_FAIL_DEC;
1354 tempRADEON_STENCIL_FAIL_INC_WRAP = RADEON_STENCIL_FAIL_INC;
1355 tempRADEON_STENCIL_ZFAIL_DEC_WRAP = RADEON_STENCIL_ZFAIL_DEC;
1356 tempRADEON_STENCIL_ZFAIL_INC_WRAP = RADEON_STENCIL_ZFAIL_INC;
1357 tempRADEON_STENCIL_ZPASS_DEC_WRAP = RADEON_STENCIL_ZPASS_DEC;
1358 tempRADEON_STENCIL_ZPASS_INC_WRAP = RADEON_STENCIL_ZPASS_INC;
1359 }
1360 else {
1361 tempRADEON_STENCIL_FAIL_DEC_WRAP = RADEON_STENCIL_FAIL_DEC_WRAP;
1362 tempRADEON_STENCIL_FAIL_INC_WRAP = RADEON_STENCIL_FAIL_INC_WRAP;
1363 tempRADEON_STENCIL_ZFAIL_DEC_WRAP = RADEON_STENCIL_ZFAIL_DEC_WRAP;
1364 tempRADEON_STENCIL_ZFAIL_INC_WRAP = RADEON_STENCIL_ZFAIL_INC_WRAP;
1365 tempRADEON_STENCIL_ZPASS_DEC_WRAP = RADEON_STENCIL_ZPASS_DEC_WRAP;
1366 tempRADEON_STENCIL_ZPASS_INC_WRAP = RADEON_STENCIL_ZPASS_INC_WRAP;
1367 }
1368
1369 RADEON_STATECHANGE( rmesa, ctx );
1370 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~(RADEON_STENCIL_FAIL_MASK |
1371 RADEON_STENCIL_ZFAIL_MASK |
1372 RADEON_STENCIL_ZPASS_MASK);
1373
1374 switch ( ctx->Stencil.FailFunc[0] ) {
1375 case GL_KEEP:
1376 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_KEEP;
1377 break;
1378 case GL_ZERO:
1379 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_ZERO;
1380 break;
1381 case GL_REPLACE:
1382 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_REPLACE;
1383 break;
1384 case GL_INCR:
1385 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_INC;
1386 break;
1387 case GL_DECR:
1388 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_DEC;
1389 break;
1390 case GL_INCR_WRAP:
1391 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= tempRADEON_STENCIL_FAIL_INC_WRAP;
1392 break;
1393 case GL_DECR_WRAP:
1394 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= tempRADEON_STENCIL_FAIL_DEC_WRAP;
1395 break;
1396 case GL_INVERT:
1397 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_INVERT;
1398 break;
1399 }
1400
1401 switch ( ctx->Stencil.ZFailFunc[0] ) {
1402 case GL_KEEP:
1403 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_KEEP;
1404 break;
1405 case GL_ZERO:
1406 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_ZERO;
1407 break;
1408 case GL_REPLACE:
1409 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_REPLACE;
1410 break;
1411 case GL_INCR:
1412 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_INC;
1413 break;
1414 case GL_DECR:
1415 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_DEC;
1416 break;
1417 case GL_INCR_WRAP:
1418 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= tempRADEON_STENCIL_ZFAIL_INC_WRAP;
1419 break;
1420 case GL_DECR_WRAP:
1421 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= tempRADEON_STENCIL_ZFAIL_DEC_WRAP;
1422 break;
1423 case GL_INVERT:
1424 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_INVERT;
1425 break;
1426 }
1427
1428 switch ( ctx->Stencil.ZPassFunc[0] ) {
1429 case GL_KEEP:
1430 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_KEEP;
1431 break;
1432 case GL_ZERO:
1433 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_ZERO;
1434 break;
1435 case GL_REPLACE:
1436 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_REPLACE;
1437 break;
1438 case GL_INCR:
1439 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_INC;
1440 break;
1441 case GL_DECR:
1442 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_DEC;
1443 break;
1444 case GL_INCR_WRAP:
1445 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= tempRADEON_STENCIL_ZPASS_INC_WRAP;
1446 break;
1447 case GL_DECR_WRAP:
1448 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= tempRADEON_STENCIL_ZPASS_DEC_WRAP;
1449 break;
1450 case GL_INVERT:
1451 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_INVERT;
1452 break;
1453 }
1454 }
1455
1456 static void radeonClearStencil( GLcontext *ctx, GLint s )
1457 {
1458 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1459
1460 rmesa->state.stencil.clear =
1461 ((GLuint) (ctx->Stencil.Clear & 0xff) |
1462 (0xff << RADEON_STENCIL_MASK_SHIFT) |
1463 ((ctx->Stencil.WriteMask[0] & 0xff) << RADEON_STENCIL_WRITEMASK_SHIFT));
1464 }
1465
1466
1467 /* =============================================================
1468 * Window position and viewport transformation
1469 */
1470
1471 /*
1472 * To correctly position primitives:
1473 */
1474 #define SUBPIXEL_X 0.125
1475 #define SUBPIXEL_Y 0.125
1476
1477
1478 /**
1479 * Called when window size or position changes or viewport or depth range
1480 * state is changed. We update the hardware viewport state here.
1481 */
1482 void radeonUpdateWindow( GLcontext *ctx )
1483 {
1484 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1485 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
1486 GLfloat xoffset = (GLfloat)dPriv->x;
1487 GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h;
1488 const GLfloat *v = ctx->Viewport._WindowMap.m;
1489
1490 float_ui32_type sx = { v[MAT_SX] };
1491 float_ui32_type tx = { v[MAT_TX] + xoffset + SUBPIXEL_X };
1492 float_ui32_type sy = { - v[MAT_SY] };
1493 float_ui32_type ty = { (- v[MAT_TY]) + yoffset + SUBPIXEL_Y };
1494 float_ui32_type sz = { v[MAT_SZ] * rmesa->state.depth.scale };
1495 float_ui32_type tz = { v[MAT_TZ] * rmesa->state.depth.scale };
1496
1497 RADEON_FIREVERTICES( rmesa );
1498 RADEON_STATECHANGE( rmesa, vpt );
1499
1500 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XSCALE] = sx.ui32;
1501 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = tx.ui32;
1502 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YSCALE] = sy.ui32;
1503 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = ty.ui32;
1504 rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZSCALE] = sz.ui32;
1505 rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZOFFSET] = tz.ui32;
1506 }
1507
1508
1509 static void radeonViewport( GLcontext *ctx, GLint x, GLint y,
1510 GLsizei width, GLsizei height )
1511 {
1512 /* Don't pipeline viewport changes, conflict with window offset
1513 * setting below. Could apply deltas to rescue pipelined viewport
1514 * values, or keep the originals hanging around.
1515 */
1516 radeonUpdateWindow( ctx );
1517 }
1518
1519 static void radeonDepthRange( GLcontext *ctx, GLclampd nearval,
1520 GLclampd farval )
1521 {
1522 radeonUpdateWindow( ctx );
1523 }
1524
1525 void radeonUpdateViewportOffset( GLcontext *ctx )
1526 {
1527 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1528 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
1529 GLfloat xoffset = (GLfloat)dPriv->x;
1530 GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h;
1531 const GLfloat *v = ctx->Viewport._WindowMap.m;
1532
1533 float_ui32_type tx;
1534 float_ui32_type ty;
1535
1536 tx.f = v[MAT_TX] + xoffset + SUBPIXEL_X;
1537 ty.f = (- v[MAT_TY]) + yoffset + SUBPIXEL_Y;
1538
1539 if ( rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] != tx.ui32 ||
1540 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] != ty.ui32 )
1541 {
1542 /* Note: this should also modify whatever data the context reset
1543 * code uses...
1544 */
1545 RADEON_STATECHANGE( rmesa, vpt );
1546 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = tx.ui32;
1547 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = ty.ui32;
1548
1549 /* update polygon stipple x/y screen offset */
1550 {
1551 GLuint stx, sty;
1552 GLuint m = rmesa->hw.msc.cmd[MSC_RE_MISC];
1553
1554 m &= ~(RADEON_STIPPLE_X_OFFSET_MASK |
1555 RADEON_STIPPLE_Y_OFFSET_MASK);
1556
1557 /* add magic offsets, then invert */
1558 stx = 31 - ((rmesa->dri.drawable->x - 1) & RADEON_STIPPLE_COORD_MASK);
1559 sty = 31 - ((rmesa->dri.drawable->y + rmesa->dri.drawable->h - 1)
1560 & RADEON_STIPPLE_COORD_MASK);
1561
1562 m |= ((stx << RADEON_STIPPLE_X_OFFSET_SHIFT) |
1563 (sty << RADEON_STIPPLE_Y_OFFSET_SHIFT));
1564
1565 if ( rmesa->hw.msc.cmd[MSC_RE_MISC] != m ) {
1566 RADEON_STATECHANGE( rmesa, msc );
1567 rmesa->hw.msc.cmd[MSC_RE_MISC] = m;
1568 }
1569 }
1570 }
1571
1572 radeonUpdateScissor( ctx );
1573 }
1574
1575
1576
1577 /* =============================================================
1578 * Miscellaneous
1579 */
1580
1581 static void radeonClearColor( GLcontext *ctx, const GLfloat color[4] )
1582 {
1583 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1584 GLubyte c[4];
1585 CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]);
1586 CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]);
1587 CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]);
1588 CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]);
1589 rmesa->state.color.clear = radeonPackColor( rmesa->radeonScreen->cpp,
1590 c[0], c[1], c[2], c[3] );
1591 }
1592
1593
1594 static void radeonRenderMode( GLcontext *ctx, GLenum mode )
1595 {
1596 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1597 FALLBACK( rmesa, RADEON_FALLBACK_RENDER_MODE, (mode != GL_RENDER) );
1598 }
1599
1600
1601 static GLuint radeon_rop_tab[] = {
1602 RADEON_ROP_CLEAR,
1603 RADEON_ROP_AND,
1604 RADEON_ROP_AND_REVERSE,
1605 RADEON_ROP_COPY,
1606 RADEON_ROP_AND_INVERTED,
1607 RADEON_ROP_NOOP,
1608 RADEON_ROP_XOR,
1609 RADEON_ROP_OR,
1610 RADEON_ROP_NOR,
1611 RADEON_ROP_EQUIV,
1612 RADEON_ROP_INVERT,
1613 RADEON_ROP_OR_REVERSE,
1614 RADEON_ROP_COPY_INVERTED,
1615 RADEON_ROP_OR_INVERTED,
1616 RADEON_ROP_NAND,
1617 RADEON_ROP_SET,
1618 };
1619
1620 static void radeonLogicOpCode( GLcontext *ctx, GLenum opcode )
1621 {
1622 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1623 GLuint rop = (GLuint)opcode - GL_CLEAR;
1624
1625 ASSERT( rop < 16 );
1626
1627 RADEON_STATECHANGE( rmesa, msk );
1628 rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = radeon_rop_tab[rop];
1629 }
1630
1631
1632 /**
1633 * Set up the cliprects for either front or back-buffer drawing.
1634 */
1635 void radeonSetCliprects( radeonContextPtr rmesa )
1636 {
1637 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
1638
1639 if (rmesa->glCtx->DrawBuffer->_ColorDrawBufferMask[0]
1640 == BUFFER_BIT_BACK_LEFT) {
1641 /* Can't ignore 2d windows if we are page flipping.
1642 */
1643 if ( dPriv->numBackClipRects == 0 || rmesa->doPageFlip ) {
1644 rmesa->numClipRects = dPriv->numClipRects;
1645 rmesa->pClipRects = dPriv->pClipRects;
1646 }
1647 else {
1648 rmesa->numClipRects = dPriv->numBackClipRects;
1649 rmesa->pClipRects = dPriv->pBackClipRects;
1650 }
1651 }
1652 else {
1653 /* front buffer (or none, or multiple buffers */
1654 rmesa->numClipRects = dPriv->numClipRects;
1655 rmesa->pClipRects = dPriv->pClipRects;
1656 }
1657
1658 if (rmesa->state.scissor.enabled)
1659 radeonRecalcScissorRects( rmesa );
1660 }
1661
1662
1663 /**
1664 * Called via glDrawBuffer.
1665 */
1666 static void radeonDrawBuffer( GLcontext *ctx, GLenum mode )
1667 {
1668 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1669
1670 if (RADEON_DEBUG & DEBUG_DRI)
1671 fprintf(stderr, "%s %s\n", __FUNCTION__,
1672 _mesa_lookup_enum_by_nr( mode ));
1673
1674 RADEON_FIREVERTICES(rmesa); /* don't pipeline cliprect changes */
1675
1676 /*
1677 * _ColorDrawBufferMask is easier to cope with than <mode>.
1678 * Check for software fallback, update cliprects.
1679 */
1680 switch ( ctx->DrawBuffer->_ColorDrawBufferMask[0] ) {
1681 case BUFFER_BIT_FRONT_LEFT:
1682 case BUFFER_BIT_BACK_LEFT:
1683 FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_FALSE );
1684 break;
1685 default:
1686 /* 0 (GL_NONE) buffers or multiple color drawing buffers */
1687 FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_TRUE );
1688 return;
1689 }
1690
1691 radeonSetCliprects( rmesa );
1692
1693 /* We'll set the drawing engine's offset/pitch parameters later
1694 * when we update other state.
1695 */
1696 }
1697
1698 static void radeonReadBuffer( GLcontext *ctx, GLenum mode )
1699 {
1700 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
1701 }
1702
1703
1704 /* =============================================================
1705 * State enable/disable
1706 */
1707
1708 static void radeonEnable( GLcontext *ctx, GLenum cap, GLboolean state )
1709 {
1710 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1711 GLuint p, flag;
1712
1713 if ( RADEON_DEBUG & DEBUG_STATE )
1714 fprintf( stderr, "%s( %s = %s )\n", __FUNCTION__,
1715 _mesa_lookup_enum_by_nr( cap ),
1716 state ? "GL_TRUE" : "GL_FALSE" );
1717
1718 switch ( cap ) {
1719 /* Fast track this one...
1720 */
1721 case GL_TEXTURE_1D:
1722 case GL_TEXTURE_2D:
1723 case GL_TEXTURE_3D:
1724 break;
1725
1726 case GL_ALPHA_TEST:
1727 RADEON_STATECHANGE( rmesa, ctx );
1728 if (state) {
1729 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_ALPHA_TEST_ENABLE;
1730 } else {
1731 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_ALPHA_TEST_ENABLE;
1732 }
1733 break;
1734
1735 case GL_BLEND:
1736 RADEON_STATECHANGE( rmesa, ctx );
1737 if (state) {
1738 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_ALPHA_BLEND_ENABLE;
1739 } else {
1740 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ALPHA_BLEND_ENABLE;
1741 }
1742 if ( ctx->Color._LogicOpEnabled ) {
1743 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_ROP_ENABLE;
1744 } else {
1745 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ROP_ENABLE;
1746 }
1747
1748 /* Catch a possible fallback:
1749 */
1750 if (state) {
1751 ctx->Driver.BlendEquationSeparate( ctx,
1752 ctx->Color.BlendEquationRGB,
1753 ctx->Color.BlendEquationA );
1754 ctx->Driver.BlendFuncSeparate( ctx, ctx->Color.BlendSrcRGB,
1755 ctx->Color.BlendDstRGB,
1756 ctx->Color.BlendSrcA,
1757 ctx->Color.BlendDstA );
1758 }
1759 else {
1760 FALLBACK( rmesa, RADEON_FALLBACK_BLEND_FUNC, GL_FALSE );
1761 FALLBACK( rmesa, RADEON_FALLBACK_BLEND_EQ, GL_FALSE );
1762 }
1763 break;
1764
1765 case GL_CLIP_PLANE0:
1766 case GL_CLIP_PLANE1:
1767 case GL_CLIP_PLANE2:
1768 case GL_CLIP_PLANE3:
1769 case GL_CLIP_PLANE4:
1770 case GL_CLIP_PLANE5:
1771 p = cap-GL_CLIP_PLANE0;
1772 RADEON_STATECHANGE( rmesa, tcl );
1773 if (state) {
1774 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (RADEON_UCP_ENABLE_0<<p);
1775 radeonClipPlane( ctx, cap, NULL );
1776 }
1777 else {
1778 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(RADEON_UCP_ENABLE_0<<p);
1779 }
1780 break;
1781
1782 case GL_COLOR_MATERIAL:
1783 radeonColorMaterial( ctx, 0, 0 );
1784 radeonUpdateMaterial( ctx );
1785 break;
1786
1787 case GL_CULL_FACE:
1788 radeonCullFace( ctx, 0 );
1789 break;
1790
1791 case GL_DEPTH_TEST:
1792 RADEON_STATECHANGE(rmesa, ctx );
1793 if ( state ) {
1794 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_Z_ENABLE;
1795 } else {
1796 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_Z_ENABLE;
1797 }
1798 break;
1799
1800 case GL_DITHER:
1801 RADEON_STATECHANGE(rmesa, ctx );
1802 if ( state ) {
1803 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_DITHER_ENABLE;
1804 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~rmesa->state.color.roundEnable;
1805 } else {
1806 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_DITHER_ENABLE;
1807 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= rmesa->state.color.roundEnable;
1808 }
1809 break;
1810
1811 case GL_FOG:
1812 RADEON_STATECHANGE(rmesa, ctx );
1813 if ( state ) {
1814 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_FOG_ENABLE;
1815 radeonFogfv( ctx, GL_FOG_MODE, NULL );
1816 } else {
1817 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_FOG_ENABLE;
1818 RADEON_STATECHANGE(rmesa, tcl);
1819 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_TCL_FOG_MASK;
1820 }
1821 radeonUpdateSpecular( ctx ); /* for PK_SPEC */
1822 _mesa_allow_light_in_model( ctx, !state );
1823 break;
1824
1825 case GL_LIGHT0:
1826 case GL_LIGHT1:
1827 case GL_LIGHT2:
1828 case GL_LIGHT3:
1829 case GL_LIGHT4:
1830 case GL_LIGHT5:
1831 case GL_LIGHT6:
1832 case GL_LIGHT7:
1833 RADEON_STATECHANGE(rmesa, tcl);
1834 p = cap - GL_LIGHT0;
1835 if (p&1)
1836 flag = (RADEON_LIGHT_1_ENABLE |
1837 RADEON_LIGHT_1_ENABLE_AMBIENT |
1838 RADEON_LIGHT_1_ENABLE_SPECULAR);
1839 else
1840 flag = (RADEON_LIGHT_0_ENABLE |
1841 RADEON_LIGHT_0_ENABLE_AMBIENT |
1842 RADEON_LIGHT_0_ENABLE_SPECULAR);
1843
1844 if (state)
1845 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] |= flag;
1846 else
1847 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] &= ~flag;
1848
1849 /*
1850 */
1851 update_light_colors( ctx, p );
1852 break;
1853
1854 case GL_LIGHTING:
1855 RADEON_STATECHANGE(rmesa, tcl);
1856 radeonUpdateSpecular(ctx);
1857 check_twoside_fallback( ctx );
1858 break;
1859
1860 case GL_LINE_SMOOTH:
1861 RADEON_STATECHANGE( rmesa, ctx );
1862 if ( state ) {
1863 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_ANTI_ALIAS_LINE;
1864 } else {
1865 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_ANTI_ALIAS_LINE;
1866 }
1867 break;
1868
1869 case GL_LINE_STIPPLE:
1870 RADEON_STATECHANGE( rmesa, ctx );
1871 if ( state ) {
1872 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_PATTERN_ENABLE;
1873 } else {
1874 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_PATTERN_ENABLE;
1875 }
1876 break;
1877
1878 case GL_COLOR_LOGIC_OP:
1879 RADEON_STATECHANGE( rmesa, ctx );
1880 if ( ctx->Color._LogicOpEnabled ) {
1881 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_ROP_ENABLE;
1882 } else {
1883 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ROP_ENABLE;
1884 }
1885 break;
1886
1887 case GL_NORMALIZE:
1888 RADEON_STATECHANGE( rmesa, tcl );
1889 if ( state ) {
1890 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_NORMALIZE_NORMALS;
1891 } else {
1892 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_NORMALIZE_NORMALS;
1893 }
1894 break;
1895
1896 case GL_POLYGON_OFFSET_POINT:
1897 RADEON_STATECHANGE( rmesa, set );
1898 if ( state ) {
1899 rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_ZBIAS_ENABLE_POINT;
1900 } else {
1901 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_ZBIAS_ENABLE_POINT;
1902 }
1903 break;
1904
1905 case GL_POLYGON_OFFSET_LINE:
1906 RADEON_STATECHANGE( rmesa, set );
1907 if ( state ) {
1908 rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_ZBIAS_ENABLE_LINE;
1909 } else {
1910 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_ZBIAS_ENABLE_LINE;
1911 }
1912 break;
1913
1914 case GL_POLYGON_OFFSET_FILL:
1915 RADEON_STATECHANGE( rmesa, set );
1916 if ( state ) {
1917 rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_ZBIAS_ENABLE_TRI;
1918 } else {
1919 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_ZBIAS_ENABLE_TRI;
1920 }
1921 break;
1922
1923 case GL_POLYGON_SMOOTH:
1924 RADEON_STATECHANGE( rmesa, ctx );
1925 if ( state ) {
1926 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_ANTI_ALIAS_POLY;
1927 } else {
1928 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_ANTI_ALIAS_POLY;
1929 }
1930 break;
1931
1932 case GL_POLYGON_STIPPLE:
1933 RADEON_STATECHANGE(rmesa, ctx );
1934 if ( state ) {
1935 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_STIPPLE_ENABLE;
1936 } else {
1937 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_STIPPLE_ENABLE;
1938 }
1939 break;
1940
1941 case GL_RESCALE_NORMAL_EXT: {
1942 GLboolean tmp = ctx->_NeedEyeCoords ? state : !state;
1943 RADEON_STATECHANGE( rmesa, tcl );
1944 if ( tmp ) {
1945 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_RESCALE_NORMALS;
1946 } else {
1947 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_RESCALE_NORMALS;
1948 }
1949 break;
1950 }
1951
1952 case GL_SCISSOR_TEST:
1953 RADEON_FIREVERTICES( rmesa );
1954 rmesa->state.scissor.enabled = state;
1955 radeonUpdateScissor( ctx );
1956 break;
1957
1958 case GL_STENCIL_TEST:
1959 if ( rmesa->state.stencil.hwBuffer ) {
1960 RADEON_STATECHANGE( rmesa, ctx );
1961 if ( state ) {
1962 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_STENCIL_ENABLE;
1963 } else {
1964 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_STENCIL_ENABLE;
1965 }
1966 } else {
1967 FALLBACK( rmesa, RADEON_FALLBACK_STENCIL, state );
1968 }
1969 break;
1970
1971 case GL_TEXTURE_GEN_Q:
1972 case GL_TEXTURE_GEN_R:
1973 case GL_TEXTURE_GEN_S:
1974 case GL_TEXTURE_GEN_T:
1975 /* Picked up in radeonUpdateTextureState.
1976 */
1977 rmesa->recheck_texgen[ctx->Texture.CurrentUnit] = GL_TRUE;
1978 break;
1979
1980 case GL_COLOR_SUM_EXT:
1981 radeonUpdateSpecular ( ctx );
1982 break;
1983
1984 default:
1985 return;
1986 }
1987 }
1988
1989
1990 static void radeonLightingSpaceChange( GLcontext *ctx )
1991 {
1992 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1993 GLboolean tmp;
1994 RADEON_STATECHANGE( rmesa, tcl );
1995
1996 if (RADEON_DEBUG & DEBUG_STATE)
1997 fprintf(stderr, "%s %d BEFORE %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
1998 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]);
1999
2000 if (ctx->_NeedEyeCoords)
2001 tmp = ctx->Transform.RescaleNormals;
2002 else
2003 tmp = !ctx->Transform.RescaleNormals;
2004
2005 if ( tmp ) {
2006 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_RESCALE_NORMALS;
2007 } else {
2008 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_RESCALE_NORMALS;
2009 }
2010
2011 if (RADEON_DEBUG & DEBUG_STATE)
2012 fprintf(stderr, "%s %d AFTER %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
2013 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]);
2014 }
2015
2016 /* =============================================================
2017 * Deferred state management - matrices, textures, other?
2018 */
2019
2020 static void texmat_set_texrect( radeonContextPtr rmesa,
2021 struct gl_texture_object *tObj, GLuint unit )
2022 {
2023 const struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel];
2024 _math_matrix_set_identity( &rmesa->tmpmat[unit] );
2025 rmesa->tmpmat[unit].m[0] = 1.0 / baseImage->Width;
2026 rmesa->tmpmat[unit].m[5] = 1.0 / baseImage->Height;
2027
2028 }
2029
2030 static void texmat_fixup_texrect( radeonContextPtr rmesa,
2031 struct gl_texture_object *tObj, GLuint unit )
2032 {
2033 const struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel];
2034 GLuint i;
2035 for (i = 0; i < 4; i++) {
2036 rmesa->tmpmat[unit].m[i] = rmesa->tmpmat[unit].m[i] / baseImage->Width;
2037 rmesa->tmpmat[unit].m[i+4] = rmesa->tmpmat[unit].m[i+4] / baseImage->Height;
2038 }}
2039
2040
2041 void radeonUploadTexMatrix( radeonContextPtr rmesa,
2042 int unit, GLboolean swapcols )
2043 {
2044 /* Here's how this works: on r100, only 3 tex coords can be submitted, so the
2045 vector looks like this probably: (s t r|q 0) (not sure if the last coord
2046 is hardwired to 0, could be 1 too). Interestingly, it actually looks like
2047 texgen generates all 4 coords, at least tests with projtex indicated that.
2048 So: if we need the q coord in the end (solely determined by the texture
2049 target, i.e. 2d / 1d / texrect targets) we swap the third and 4th row.
2050 Additionally, if we don't have texgen but 4 tex coords submitted, we swap
2051 column 3 and 4 (for the 2d / 1d / texrect targets) since the the q coord
2052 will get submitted in the "wrong", i.e. 3rd, slot.
2053 If an app submits 3 coords for 2d targets, we assume it is saving on vertex
2054 size and using the texture matrix to swap the r and q coords around (ut2k3
2055 does exactly that), so we don't need the 3rd / 4th column swap - still need
2056 the 3rd / 4th row swap of course. This will potentially break for apps which
2057 use TexCoord3x just for fun. Additionally, it will never work if an app uses
2058 an "advanced" texture matrix and relies on all 4 texcoord inputs to generate
2059 the maximum needed 3. This seems impossible to do with hw tcl on r100, and
2060 incredibly hard to detect so we can't just fallback in such a case. Assume
2061 it never happens... - rs
2062 */
2063
2064 int idx = TEXMAT_0 + unit;
2065 float *dest = ((float *)RADEON_DB_STATE( mat[idx] )) + MAT_ELT_0;
2066 int i;
2067 struct gl_texture_unit tUnit = rmesa->glCtx->Texture.Unit[unit];
2068 GLfloat *src = rmesa->tmpmat[unit].m;
2069
2070 rmesa->TexMatColSwap &= ~(1 << unit);
2071 if ((tUnit._ReallyEnabled & (TEXTURE_3D_BIT | TEXTURE_CUBE_BIT)) == 0) {
2072 if (swapcols) {
2073 rmesa->TexMatColSwap |= 1 << unit;
2074 /* attention some elems are swapped 2 times! */
2075 *dest++ = src[0];
2076 *dest++ = src[4];
2077 *dest++ = src[12];
2078 *dest++ = src[8];
2079 *dest++ = src[1];
2080 *dest++ = src[5];
2081 *dest++ = src[13];
2082 *dest++ = src[9];
2083 *dest++ = src[2];
2084 *dest++ = src[6];
2085 *dest++ = src[15];
2086 *dest++ = src[11];
2087 /* those last 4 are probably never used */
2088 *dest++ = src[3];
2089 *dest++ = src[7];
2090 *dest++ = src[14];
2091 *dest++ = src[10];
2092 }
2093 else {
2094 for (i = 0; i < 2; i++) {
2095 *dest++ = src[i];
2096 *dest++ = src[i+4];
2097 *dest++ = src[i+8];
2098 *dest++ = src[i+12];
2099 }
2100 for (i = 3; i >= 2; i--) {
2101 *dest++ = src[i];
2102 *dest++ = src[i+4];
2103 *dest++ = src[i+8];
2104 *dest++ = src[i+12];
2105 }
2106 }
2107 }
2108 else {
2109 for (i = 0 ; i < 4 ; i++) {
2110 *dest++ = src[i];
2111 *dest++ = src[i+4];
2112 *dest++ = src[i+8];
2113 *dest++ = src[i+12];
2114 }
2115 }
2116
2117 RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2118 }
2119
2120
2121 static void upload_matrix( radeonContextPtr rmesa, GLfloat *src, int idx )
2122 {
2123 float *dest = ((float *)RADEON_DB_STATE( mat[idx] ))+MAT_ELT_0;
2124 int i;
2125
2126
2127 for (i = 0 ; i < 4 ; i++) {
2128 *dest++ = src[i];
2129 *dest++ = src[i+4];
2130 *dest++ = src[i+8];
2131 *dest++ = src[i+12];
2132 }
2133
2134 RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2135 }
2136
2137 static void upload_matrix_t( radeonContextPtr rmesa, GLfloat *src, int idx )
2138 {
2139 float *dest = ((float *)RADEON_DB_STATE( mat[idx] ))+MAT_ELT_0;
2140 memcpy(dest, src, 16*sizeof(float));
2141 RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2142 }
2143
2144
2145 static void update_texturematrix( GLcontext *ctx )
2146 {
2147 radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
2148 GLuint tpc = rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL];
2149 GLuint vs = rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL];
2150 int unit;
2151 GLuint texMatEnabled = 0;
2152 rmesa->NeedTexMatrix = 0;
2153 rmesa->TexMatColSwap = 0;
2154
2155 for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++) {
2156 if (ctx->Texture.Unit[unit]._ReallyEnabled) {
2157 GLboolean needMatrix = GL_FALSE;
2158 if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY) {
2159 needMatrix = GL_TRUE;
2160 texMatEnabled |= (RADEON_TEXGEN_TEXMAT_0_ENABLE |
2161 RADEON_TEXMAT_0_ENABLE) << unit;
2162
2163 if (rmesa->TexGenEnabled & (RADEON_TEXMAT_0_ENABLE << unit)) {
2164 /* Need to preconcatenate any active texgen
2165 * obj/eyeplane matrices:
2166 */
2167 _math_matrix_mul_matrix( &rmesa->tmpmat[unit],
2168 ctx->TextureMatrixStack[unit].Top,
2169 &rmesa->TexGenMatrix[unit] );
2170 }
2171 else {
2172 _math_matrix_copy( &rmesa->tmpmat[unit],
2173 ctx->TextureMatrixStack[unit].Top );
2174 }
2175 }
2176 else if (rmesa->TexGenEnabled & (RADEON_TEXMAT_0_ENABLE << unit)) {
2177 _math_matrix_copy( &rmesa->tmpmat[unit], &rmesa->TexGenMatrix[unit] );
2178 needMatrix = GL_TRUE;
2179 }
2180 if (ctx->Texture.Unit[unit]._ReallyEnabled == TEXTURE_RECT_BIT) {
2181 texMatEnabled |= (RADEON_TEXGEN_TEXMAT_0_ENABLE |
2182 RADEON_TEXMAT_0_ENABLE) << unit;
2183 if (needMatrix)
2184 texmat_fixup_texrect( rmesa, ctx->Texture.Unit[unit]._Current, unit );
2185 else
2186 texmat_set_texrect( rmesa, ctx->Texture.Unit[unit]._Current, unit );
2187 needMatrix = GL_TRUE;
2188 }
2189 if (needMatrix) {
2190 rmesa->NeedTexMatrix |= 1 << unit;
2191 radeonUploadTexMatrix( rmesa, unit,
2192 !ctx->Texture.Unit[unit].TexGenEnabled );
2193 }
2194 }
2195 }
2196
2197 tpc = (texMatEnabled | rmesa->TexGenEnabled);
2198
2199 /* TCL_TEX_COMPUTED_x is TCL_TEX_INPUT_x | 0x8 */
2200 vs &= ~((RADEON_TCL_TEX_COMPUTED_TEX_0 << RADEON_TCL_TEX_0_OUTPUT_SHIFT) |
2201 (RADEON_TCL_TEX_COMPUTED_TEX_0 << RADEON_TCL_TEX_1_OUTPUT_SHIFT) |
2202 (RADEON_TCL_TEX_COMPUTED_TEX_0 << RADEON_TCL_TEX_2_OUTPUT_SHIFT));
2203
2204 vs |= (((tpc & RADEON_TEXGEN_TEXMAT_0_ENABLE) <<
2205 (RADEON_TCL_TEX_0_OUTPUT_SHIFT + 3)) |
2206 ((tpc & RADEON_TEXGEN_TEXMAT_1_ENABLE) <<
2207 (RADEON_TCL_TEX_1_OUTPUT_SHIFT + 2)) |
2208 ((tpc & RADEON_TEXGEN_TEXMAT_2_ENABLE) <<
2209 (RADEON_TCL_TEX_2_OUTPUT_SHIFT + 1)));
2210
2211 if (tpc != rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL] ||
2212 vs != rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL]) {
2213
2214 RADEON_STATECHANGE(rmesa, tcl);
2215 rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL] = tpc;
2216 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] = vs;
2217 }
2218 }
2219
2220
2221 /**
2222 * Tell the card where to render (offset, pitch).
2223 * Effected by glDrawBuffer, etc
2224 */
2225 void
2226 radeonUpdateDrawBuffer(GLcontext *ctx)
2227 {
2228 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
2229 struct gl_framebuffer *fb = ctx->DrawBuffer;
2230 driRenderbuffer *drb;
2231
2232 if (fb->_ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT) {
2233 /* draw to front */
2234 drb = (driRenderbuffer *) fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
2235 }
2236 else if (fb->_ColorDrawBufferMask[0] == BUFFER_BIT_BACK_LEFT) {
2237 /* draw to back */
2238 drb = (driRenderbuffer *) fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
2239 }
2240 else {
2241 /* drawing to multiple buffers, or none */
2242 return;
2243 }
2244
2245 assert(drb);
2246 assert(drb->flippedPitch);
2247
2248 RADEON_STATECHANGE( rmesa, ctx );
2249
2250 /* Note: we used the (possibly) page-flipped values */
2251 rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET]
2252 = ((drb->flippedOffset + rmesa->radeonScreen->fbLocation)
2253 & RADEON_COLOROFFSET_MASK);
2254 rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = drb->flippedPitch;
2255 if (rmesa->sarea->tiling_enabled) {
2256 rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] |= RADEON_COLOR_TILE_ENABLE;
2257 }
2258 }
2259
2260
2261 void radeonValidateState( GLcontext *ctx )
2262 {
2263 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
2264 GLuint new_state = rmesa->NewGLState;
2265
2266 if (new_state & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) {
2267 radeonUpdateDrawBuffer(ctx);
2268 }
2269
2270 if (new_state & _NEW_TEXTURE) {
2271 radeonUpdateTextureState( ctx );
2272 new_state |= rmesa->NewGLState; /* may add TEXTURE_MATRIX */
2273 }
2274
2275 /* Need an event driven matrix update?
2276 */
2277 if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION))
2278 upload_matrix( rmesa, ctx->_ModelProjectMatrix.m, MODEL_PROJ );
2279
2280 /* Need these for lighting (shouldn't upload otherwise)
2281 */
2282 if (new_state & (_NEW_MODELVIEW)) {
2283 upload_matrix( rmesa, ctx->ModelviewMatrixStack.Top->m, MODEL );
2284 upload_matrix_t( rmesa, ctx->ModelviewMatrixStack.Top->inv, MODEL_IT );
2285 }
2286
2287 /* Does this need to be triggered on eg. modelview for
2288 * texgen-derived objplane/eyeplane matrices?
2289 */
2290 if (new_state & _NEW_TEXTURE_MATRIX) {
2291 update_texturematrix( ctx );
2292 }
2293
2294 if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW|_MESA_NEW_NEED_EYE_COORDS)) {
2295 update_light( ctx );
2296 }
2297
2298 /* emit all active clip planes if projection matrix changes.
2299 */
2300 if (new_state & (_NEW_PROJECTION)) {
2301 if (ctx->Transform.ClipPlanesEnabled)
2302 radeonUpdateClipPlanes( ctx );
2303 }
2304
2305
2306 rmesa->NewGLState = 0;
2307 }
2308
2309
2310 static void radeonInvalidateState( GLcontext *ctx, GLuint new_state )
2311 {
2312 _swrast_InvalidateState( ctx, new_state );
2313 _swsetup_InvalidateState( ctx, new_state );
2314 _ac_InvalidateState( ctx, new_state );
2315 _tnl_InvalidateState( ctx, new_state );
2316 _ae_invalidate_state( ctx, new_state );
2317 RADEON_CONTEXT(ctx)->NewGLState |= new_state;
2318 radeonVtxfmtInvalidate( ctx );
2319 }
2320
2321
2322 /* A hack. Need a faster way to find this out.
2323 */
2324 static GLboolean check_material( GLcontext *ctx )
2325 {
2326 TNLcontext *tnl = TNL_CONTEXT(ctx);
2327 GLint i;
2328
2329 for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT;
2330 i < _TNL_ATTRIB_MAT_BACK_INDEXES;
2331 i++)
2332 if (tnl->vb.AttribPtr[i] &&
2333 tnl->vb.AttribPtr[i]->stride)
2334 return GL_TRUE;
2335
2336 return GL_FALSE;
2337 }
2338
2339
2340 static void radeonWrapRunPipeline( GLcontext *ctx )
2341 {
2342 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
2343 GLboolean has_material;
2344
2345 if (0)
2346 fprintf(stderr, "%s, newstate: %x\n", __FUNCTION__, rmesa->NewGLState);
2347
2348 /* Validate state:
2349 */
2350 if (rmesa->NewGLState)
2351 radeonValidateState( ctx );
2352
2353 has_material = (ctx->Light.Enabled && check_material( ctx ));
2354
2355 if (has_material) {
2356 TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_MATERIAL, GL_TRUE );
2357 }
2358
2359 /* Run the pipeline.
2360 */
2361 _tnl_run_pipeline( ctx );
2362
2363 if (has_material) {
2364 TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_MATERIAL, GL_FALSE );
2365 }
2366 }
2367
2368
2369 /* Initialize the driver's state functions.
2370 * Many of the ctx->Driver functions might have been initialized to
2371 * software defaults in the earlier _mesa_init_driver_functions() call.
2372 */
2373 void radeonInitStateFuncs( GLcontext *ctx )
2374 {
2375 ctx->Driver.UpdateState = radeonInvalidateState;
2376 ctx->Driver.LightingSpaceChange = radeonLightingSpaceChange;
2377
2378 ctx->Driver.DrawBuffer = radeonDrawBuffer;
2379 ctx->Driver.ReadBuffer = radeonReadBuffer;
2380
2381 ctx->Driver.AlphaFunc = radeonAlphaFunc;
2382 ctx->Driver.BlendEquationSeparate = radeonBlendEquationSeparate;
2383 ctx->Driver.BlendFuncSeparate = radeonBlendFuncSeparate;
2384 ctx->Driver.ClearColor = radeonClearColor;
2385 ctx->Driver.ClearDepth = radeonClearDepth;
2386 ctx->Driver.ClearIndex = NULL;
2387 ctx->Driver.ClearStencil = radeonClearStencil;
2388 ctx->Driver.ClipPlane = radeonClipPlane;
2389 ctx->Driver.ColorMask = radeonColorMask;
2390 ctx->Driver.CullFace = radeonCullFace;
2391 ctx->Driver.DepthFunc = radeonDepthFunc;
2392 ctx->Driver.DepthMask = radeonDepthMask;
2393 ctx->Driver.DepthRange = radeonDepthRange;
2394 ctx->Driver.Enable = radeonEnable;
2395 ctx->Driver.Fogfv = radeonFogfv;
2396 ctx->Driver.FrontFace = radeonFrontFace;
2397 ctx->Driver.Hint = NULL;
2398 ctx->Driver.IndexMask = NULL;
2399 ctx->Driver.LightModelfv = radeonLightModelfv;
2400 ctx->Driver.Lightfv = radeonLightfv;
2401 ctx->Driver.LineStipple = radeonLineStipple;
2402 ctx->Driver.LineWidth = radeonLineWidth;
2403 ctx->Driver.LogicOpcode = radeonLogicOpCode;
2404 ctx->Driver.PolygonMode = radeonPolygonMode;
2405 ctx->Driver.PolygonOffset = radeonPolygonOffset;
2406 ctx->Driver.PolygonStipple = radeonPolygonStipple;
2407 ctx->Driver.RenderMode = radeonRenderMode;
2408 ctx->Driver.Scissor = radeonScissor;
2409 ctx->Driver.ShadeModel = radeonShadeModel;
2410 ctx->Driver.StencilFuncSeparate = radeonStencilFuncSeparate;
2411 ctx->Driver.StencilMaskSeparate = radeonStencilMaskSeparate;
2412 ctx->Driver.StencilOpSeparate = radeonStencilOpSeparate;
2413 ctx->Driver.Viewport = radeonViewport;
2414
2415 TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange = radeonUpdateMaterial;
2416 TNL_CONTEXT(ctx)->Driver.RunPipeline = radeonWrapRunPipeline;
2417 }