update r300 drm minimum to 20
[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 GLfloat constant = units * rmesa->state.depth.scale;
628
629 RADEON_STATECHANGE( rmesa, zbs );
630 rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_FACTOR] = *(GLuint *)&factor;
631 rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_CONSTANT] = *(GLuint *)&constant;
632 }
633
634 static void radeonPolygonStipple( GLcontext *ctx, const GLubyte *mask )
635 {
636 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
637 GLuint i;
638 drm_radeon_stipple_t stipple;
639
640 /* Must flip pattern upside down.
641 */
642 for ( i = 0 ; i < 32 ; i++ ) {
643 rmesa->state.stipple.mask[31 - i] = ((GLuint *) mask)[i];
644 }
645
646 /* TODO: push this into cmd mechanism
647 */
648 RADEON_FIREVERTICES( rmesa );
649 LOCK_HARDWARE( rmesa );
650
651 /* FIXME: Use window x,y offsets into stipple RAM.
652 */
653 stipple.mask = rmesa->state.stipple.mask;
654 drmCommandWrite( rmesa->dri.fd, DRM_RADEON_STIPPLE,
655 &stipple, sizeof(drm_radeon_stipple_t) );
656 UNLOCK_HARDWARE( rmesa );
657 }
658
659 static void radeonPolygonMode( GLcontext *ctx, GLenum face, GLenum mode )
660 {
661 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
662 GLboolean flag = (ctx->_TriangleCaps & DD_TRI_UNFILLED) != 0;
663
664 /* Can't generally do unfilled via tcl, but some good special
665 * cases work.
666 */
667 TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_UNFILLED, flag);
668 if (rmesa->TclFallback) {
669 radeonChooseRenderState( ctx );
670 radeonChooseVertexState( ctx );
671 }
672 }
673
674
675 /* =============================================================
676 * Rendering attributes
677 *
678 * We really don't want to recalculate all this every time we bind a
679 * texture. These things shouldn't change all that often, so it makes
680 * sense to break them out of the core texture state update routines.
681 */
682
683 /* Examine lighting and texture state to determine if separate specular
684 * should be enabled.
685 */
686 static void radeonUpdateSpecular( GLcontext *ctx )
687 {
688 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
689 u_int32_t p = rmesa->hw.ctx.cmd[CTX_PP_CNTL];
690 GLuint flag = 0;
691
692 RADEON_STATECHANGE( rmesa, tcl );
693
694 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &= ~RADEON_TCL_COMPUTE_SPECULAR;
695 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &= ~RADEON_TCL_COMPUTE_DIFFUSE;
696 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &= ~RADEON_TCL_VTX_PK_SPEC;
697 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &= ~RADEON_TCL_VTX_PK_DIFFUSE;
698 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_LIGHTING_ENABLE;
699
700 p &= ~RADEON_SPECULAR_ENABLE;
701
702 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_DIFFUSE_SPECULAR_COMBINE;
703
704
705 if (ctx->Light.Enabled &&
706 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) {
707 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_SPECULAR;
708 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_DIFFUSE;
709 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC;
710 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE;
711 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE;
712 p |= RADEON_SPECULAR_ENABLE;
713 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &=
714 ~RADEON_DIFFUSE_SPECULAR_COMBINE;
715 }
716 else if (ctx->Light.Enabled) {
717 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_DIFFUSE;
718 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE;
719 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE;
720 } else if (ctx->Fog.ColorSumEnabled ) {
721 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC;
722 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE;
723 p |= RADEON_SPECULAR_ENABLE;
724 } else {
725 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE;
726 }
727
728 if (ctx->Fog.Enabled) {
729 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC;
730 if (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH) {
731 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_SPECULAR;
732 /* Bizzare: have to leave lighting enabled to get fog. */
733 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE;
734 }
735 else {
736 /* cannot do tcl fog factor calculation with fog coord source
737 * (send precomputed factors). Cannot use precomputed fog
738 * factors together with tcl spec light (need tcl fallback) */
739 flag = (rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &
740 RADEON_TCL_COMPUTE_SPECULAR) != 0;
741 }
742 }
743
744 TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_FOGCOORDSPEC, flag);
745
746 if (NEED_SECONDARY_COLOR(ctx)) {
747 assert( (p & RADEON_SPECULAR_ENABLE) != 0 );
748 } else {
749 assert( (p & RADEON_SPECULAR_ENABLE) == 0 );
750 }
751
752 if ( rmesa->hw.ctx.cmd[CTX_PP_CNTL] != p ) {
753 RADEON_STATECHANGE( rmesa, ctx );
754 rmesa->hw.ctx.cmd[CTX_PP_CNTL] = p;
755 }
756
757 /* Update vertex/render formats
758 */
759 if (rmesa->TclFallback) {
760 radeonChooseRenderState( ctx );
761 radeonChooseVertexState( ctx );
762 }
763 }
764
765
766 /* =============================================================
767 * Materials
768 */
769
770
771 /* Update on colormaterial, material emmissive/ambient,
772 * lightmodel.globalambient
773 */
774 static void update_global_ambient( GLcontext *ctx )
775 {
776 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
777 float *fcmd = (float *)RADEON_DB_STATE( glt );
778
779 /* Need to do more if both emmissive & ambient are PREMULT:
780 * Hope this is not needed for MULT
781 */
782 if ((rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &
783 ((3 << RADEON_EMISSIVE_SOURCE_SHIFT) |
784 (3 << RADEON_AMBIENT_SOURCE_SHIFT))) == 0)
785 {
786 COPY_3V( &fcmd[GLT_RED],
787 ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION]);
788 ACC_SCALE_3V( &fcmd[GLT_RED],
789 ctx->Light.Model.Ambient,
790 ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT]);
791 }
792 else
793 {
794 COPY_3V( &fcmd[GLT_RED], ctx->Light.Model.Ambient );
795 }
796
797 RADEON_DB_STATECHANGE(rmesa, &rmesa->hw.glt);
798 }
799
800 /* Update on change to
801 * - light[p].colors
802 * - light[p].enabled
803 */
804 static void update_light_colors( GLcontext *ctx, GLuint p )
805 {
806 struct gl_light *l = &ctx->Light.Light[p];
807
808 /* fprintf(stderr, "%s\n", __FUNCTION__); */
809
810 if (l->Enabled) {
811 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
812 float *fcmd = (float *)RADEON_DB_STATE( lit[p] );
813
814 COPY_4V( &fcmd[LIT_AMBIENT_RED], l->Ambient );
815 COPY_4V( &fcmd[LIT_DIFFUSE_RED], l->Diffuse );
816 COPY_4V( &fcmd[LIT_SPECULAR_RED], l->Specular );
817
818 RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
819 }
820 }
821
822 /* Also fallback for asym colormaterial mode in twoside lighting...
823 */
824 static void check_twoside_fallback( GLcontext *ctx )
825 {
826 GLboolean fallback = GL_FALSE;
827 GLint i;
828
829 if (ctx->Light.Enabled && ctx->Light.Model.TwoSide) {
830 if (ctx->Light.ColorMaterialEnabled &&
831 (ctx->Light.ColorMaterialBitmask & BACK_MATERIAL_BITS) !=
832 ((ctx->Light.ColorMaterialBitmask & FRONT_MATERIAL_BITS)<<1))
833 fallback = GL_TRUE;
834 else {
835 for (i = MAT_ATTRIB_FRONT_AMBIENT; i < MAT_ATTRIB_FRONT_INDEXES; i+=2)
836 if (memcmp( ctx->Light.Material.Attrib[i],
837 ctx->Light.Material.Attrib[i+1],
838 sizeof(GLfloat)*4) != 0) {
839 fallback = GL_TRUE;
840 break;
841 }
842 }
843 }
844
845 TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_LIGHT_TWOSIDE, fallback );
846 }
847
848
849 static void radeonColorMaterial( GLcontext *ctx, GLenum face, GLenum mode )
850 {
851 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
852 GLuint light_model_ctl1 = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL];
853
854 light_model_ctl1 &= ~((3 << RADEON_EMISSIVE_SOURCE_SHIFT) |
855 (3 << RADEON_AMBIENT_SOURCE_SHIFT) |
856 (3 << RADEON_DIFFUSE_SOURCE_SHIFT) |
857 (3 << RADEON_SPECULAR_SOURCE_SHIFT));
858
859 if (ctx->Light.ColorMaterialEnabled) {
860 GLuint mask = ctx->Light.ColorMaterialBitmask;
861
862 if (mask & MAT_BIT_FRONT_EMISSION) {
863 light_model_ctl1 |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE <<
864 RADEON_EMISSIVE_SOURCE_SHIFT);
865 }
866 else {
867 light_model_ctl1 |= (RADEON_LM_SOURCE_STATE_MULT <<
868 RADEON_EMISSIVE_SOURCE_SHIFT);
869 }
870
871 if (mask & MAT_BIT_FRONT_AMBIENT) {
872 light_model_ctl1 |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE <<
873 RADEON_AMBIENT_SOURCE_SHIFT);
874 }
875 else {
876 light_model_ctl1 |= (RADEON_LM_SOURCE_STATE_MULT <<
877 RADEON_AMBIENT_SOURCE_SHIFT);
878 }
879
880 if (mask & MAT_BIT_FRONT_DIFFUSE) {
881 light_model_ctl1 |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE <<
882 RADEON_DIFFUSE_SOURCE_SHIFT);
883 }
884 else {
885 light_model_ctl1 |= (RADEON_LM_SOURCE_STATE_MULT <<
886 RADEON_DIFFUSE_SOURCE_SHIFT);
887 }
888
889 if (mask & MAT_BIT_FRONT_SPECULAR) {
890 light_model_ctl1 |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE <<
891 RADEON_SPECULAR_SOURCE_SHIFT);
892 }
893 else {
894 light_model_ctl1 |= (RADEON_LM_SOURCE_STATE_MULT <<
895 RADEON_SPECULAR_SOURCE_SHIFT);
896 }
897 }
898 else {
899 /* Default to MULT:
900 */
901 light_model_ctl1 |= (RADEON_LM_SOURCE_STATE_MULT << RADEON_EMISSIVE_SOURCE_SHIFT) |
902 (RADEON_LM_SOURCE_STATE_MULT << RADEON_AMBIENT_SOURCE_SHIFT) |
903 (RADEON_LM_SOURCE_STATE_MULT << RADEON_DIFFUSE_SOURCE_SHIFT) |
904 (RADEON_LM_SOURCE_STATE_MULT << RADEON_SPECULAR_SOURCE_SHIFT);
905 }
906
907 if (light_model_ctl1 != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]) {
908 RADEON_STATECHANGE( rmesa, tcl );
909 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] = light_model_ctl1;
910 }
911 }
912
913 void radeonUpdateMaterial( GLcontext *ctx )
914 {
915 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
916 GLfloat (*mat)[4] = ctx->Light.Material.Attrib;
917 GLfloat *fcmd = (GLfloat *)RADEON_DB_STATE( mtl );
918 GLuint mask = ~0;
919
920 if (ctx->Light.ColorMaterialEnabled)
921 mask &= ~ctx->Light.ColorMaterialBitmask;
922
923 if (RADEON_DEBUG & DEBUG_STATE)
924 fprintf(stderr, "%s\n", __FUNCTION__);
925
926
927 if (mask & MAT_BIT_FRONT_EMISSION) {
928 fcmd[MTL_EMMISSIVE_RED] = mat[MAT_ATTRIB_FRONT_EMISSION][0];
929 fcmd[MTL_EMMISSIVE_GREEN] = mat[MAT_ATTRIB_FRONT_EMISSION][1];
930 fcmd[MTL_EMMISSIVE_BLUE] = mat[MAT_ATTRIB_FRONT_EMISSION][2];
931 fcmd[MTL_EMMISSIVE_ALPHA] = mat[MAT_ATTRIB_FRONT_EMISSION][3];
932 }
933 if (mask & MAT_BIT_FRONT_AMBIENT) {
934 fcmd[MTL_AMBIENT_RED] = mat[MAT_ATTRIB_FRONT_AMBIENT][0];
935 fcmd[MTL_AMBIENT_GREEN] = mat[MAT_ATTRIB_FRONT_AMBIENT][1];
936 fcmd[MTL_AMBIENT_BLUE] = mat[MAT_ATTRIB_FRONT_AMBIENT][2];
937 fcmd[MTL_AMBIENT_ALPHA] = mat[MAT_ATTRIB_FRONT_AMBIENT][3];
938 }
939 if (mask & MAT_BIT_FRONT_DIFFUSE) {
940 fcmd[MTL_DIFFUSE_RED] = mat[MAT_ATTRIB_FRONT_DIFFUSE][0];
941 fcmd[MTL_DIFFUSE_GREEN] = mat[MAT_ATTRIB_FRONT_DIFFUSE][1];
942 fcmd[MTL_DIFFUSE_BLUE] = mat[MAT_ATTRIB_FRONT_DIFFUSE][2];
943 fcmd[MTL_DIFFUSE_ALPHA] = mat[MAT_ATTRIB_FRONT_DIFFUSE][3];
944 }
945 if (mask & MAT_BIT_FRONT_SPECULAR) {
946 fcmd[MTL_SPECULAR_RED] = mat[MAT_ATTRIB_FRONT_SPECULAR][0];
947 fcmd[MTL_SPECULAR_GREEN] = mat[MAT_ATTRIB_FRONT_SPECULAR][1];
948 fcmd[MTL_SPECULAR_BLUE] = mat[MAT_ATTRIB_FRONT_SPECULAR][2];
949 fcmd[MTL_SPECULAR_ALPHA] = mat[MAT_ATTRIB_FRONT_SPECULAR][3];
950 }
951 if (mask & MAT_BIT_FRONT_SHININESS) {
952 fcmd[MTL_SHININESS] = mat[MAT_ATTRIB_FRONT_SHININESS][0];
953 }
954
955 RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mtl );
956
957 check_twoside_fallback( ctx );
958 /* update_global_ambient( ctx );*/
959 }
960
961 /* _NEW_LIGHT
962 * _NEW_MODELVIEW
963 * _MESA_NEW_NEED_EYE_COORDS
964 *
965 * Uses derived state from mesa:
966 * _VP_inf_norm
967 * _h_inf_norm
968 * _Position
969 * _NormDirection
970 * _ModelViewInvScale
971 * _NeedEyeCoords
972 * _EyeZDir
973 *
974 * which are calculated in light.c and are correct for the current
975 * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
976 * and _MESA_NEW_NEED_EYE_COORDS.
977 */
978 static void update_light( GLcontext *ctx )
979 {
980 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
981
982 /* Have to check these, or have an automatic shortcircuit mechanism
983 * to remove noop statechanges. (Or just do a better job on the
984 * front end).
985 */
986 {
987 GLuint tmp = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL];
988
989 if (ctx->_NeedEyeCoords)
990 tmp &= ~RADEON_LIGHT_IN_MODELSPACE;
991 else
992 tmp |= RADEON_LIGHT_IN_MODELSPACE;
993
994
995 /* Leave this test disabled: (unexplained q3 lockup) (even with
996 new packets)
997 */
998 if (tmp != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL])
999 {
1000 RADEON_STATECHANGE( rmesa, tcl );
1001 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] = tmp;
1002 }
1003 }
1004
1005 {
1006 GLfloat *fcmd = (GLfloat *)RADEON_DB_STATE( eye );
1007 fcmd[EYE_X] = ctx->_EyeZDir[0];
1008 fcmd[EYE_Y] = ctx->_EyeZDir[1];
1009 fcmd[EYE_Z] = - ctx->_EyeZDir[2];
1010 fcmd[EYE_RESCALE_FACTOR] = ctx->_ModelViewInvScale;
1011 RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.eye );
1012 }
1013
1014
1015
1016 if (ctx->Light.Enabled) {
1017 GLint p;
1018 for (p = 0 ; p < MAX_LIGHTS; p++) {
1019 if (ctx->Light.Light[p].Enabled) {
1020 struct gl_light *l = &ctx->Light.Light[p];
1021 GLfloat *fcmd = (GLfloat *)RADEON_DB_STATE( lit[p] );
1022
1023 if (l->EyePosition[3] == 0.0) {
1024 COPY_3FV( &fcmd[LIT_POSITION_X], l->_VP_inf_norm );
1025 COPY_3FV( &fcmd[LIT_DIRECTION_X], l->_h_inf_norm );
1026 fcmd[LIT_POSITION_W] = 0;
1027 fcmd[LIT_DIRECTION_W] = 0;
1028 } else {
1029 COPY_4V( &fcmd[LIT_POSITION_X], l->_Position );
1030 fcmd[LIT_DIRECTION_X] = -l->_NormDirection[0];
1031 fcmd[LIT_DIRECTION_Y] = -l->_NormDirection[1];
1032 fcmd[LIT_DIRECTION_Z] = -l->_NormDirection[2];
1033 fcmd[LIT_DIRECTION_W] = 0;
1034 }
1035
1036 RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
1037 }
1038 }
1039 }
1040 }
1041
1042 static void radeonLightfv( GLcontext *ctx, GLenum light,
1043 GLenum pname, const GLfloat *params )
1044 {
1045 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1046 GLint p = light - GL_LIGHT0;
1047 struct gl_light *l = &ctx->Light.Light[p];
1048 GLfloat *fcmd = (GLfloat *)rmesa->hw.lit[p].cmd;
1049
1050
1051 switch (pname) {
1052 case GL_AMBIENT:
1053 case GL_DIFFUSE:
1054 case GL_SPECULAR:
1055 update_light_colors( ctx, p );
1056 break;
1057
1058 case GL_SPOT_DIRECTION:
1059 /* picked up in update_light */
1060 break;
1061
1062 case GL_POSITION: {
1063 /* positions picked up in update_light, but can do flag here */
1064 GLuint flag;
1065 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1066
1067 /* FIXME: Set RANGE_ATTEN only when needed */
1068 if (p&1)
1069 flag = RADEON_LIGHT_1_IS_LOCAL;
1070 else
1071 flag = RADEON_LIGHT_0_IS_LOCAL;
1072
1073 RADEON_STATECHANGE(rmesa, tcl);
1074 if (l->EyePosition[3] != 0.0F)
1075 rmesa->hw.tcl.cmd[idx] |= flag;
1076 else
1077 rmesa->hw.tcl.cmd[idx] &= ~flag;
1078 break;
1079 }
1080
1081 case GL_SPOT_EXPONENT:
1082 RADEON_STATECHANGE(rmesa, lit[p]);
1083 fcmd[LIT_SPOT_EXPONENT] = params[0];
1084 break;
1085
1086 case GL_SPOT_CUTOFF: {
1087 GLuint flag = (p&1) ? RADEON_LIGHT_1_IS_SPOT : RADEON_LIGHT_0_IS_SPOT;
1088 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1089
1090 RADEON_STATECHANGE(rmesa, lit[p]);
1091 fcmd[LIT_SPOT_CUTOFF] = l->_CosCutoff;
1092
1093 RADEON_STATECHANGE(rmesa, tcl);
1094 if (l->SpotCutoff != 180.0F)
1095 rmesa->hw.tcl.cmd[idx] |= flag;
1096 else
1097 rmesa->hw.tcl.cmd[idx] &= ~flag;
1098
1099 break;
1100 }
1101
1102 case GL_CONSTANT_ATTENUATION:
1103 RADEON_STATECHANGE(rmesa, lit[p]);
1104 fcmd[LIT_ATTEN_CONST] = params[0];
1105 if ( params[0] == 0.0 )
1106 fcmd[LIT_ATTEN_CONST_INV] = FLT_MAX;
1107 else
1108 fcmd[LIT_ATTEN_CONST_INV] = 1.0 / params[0];
1109 break;
1110 case GL_LINEAR_ATTENUATION:
1111 RADEON_STATECHANGE(rmesa, lit[p]);
1112 fcmd[LIT_ATTEN_LINEAR] = params[0];
1113 break;
1114 case GL_QUADRATIC_ATTENUATION:
1115 RADEON_STATECHANGE(rmesa, lit[p]);
1116 fcmd[LIT_ATTEN_QUADRATIC] = params[0];
1117 break;
1118 default:
1119 return;
1120 }
1121
1122 /* Set RANGE_ATTEN only when needed */
1123 switch (pname) {
1124 case GL_POSITION:
1125 case GL_CONSTANT_ATTENUATION:
1126 case GL_LINEAR_ATTENUATION:
1127 case GL_QUADRATIC_ATTENUATION:
1128 {
1129 GLuint *icmd = (GLuint *)RADEON_DB_STATE( tcl );
1130 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1131 GLuint atten_flag = ( p&1 ) ? RADEON_LIGHT_1_ENABLE_RANGE_ATTEN
1132 : RADEON_LIGHT_0_ENABLE_RANGE_ATTEN;
1133 GLuint atten_const_flag = ( p&1 ) ? RADEON_LIGHT_1_CONSTANT_RANGE_ATTEN
1134 : RADEON_LIGHT_0_CONSTANT_RANGE_ATTEN;
1135
1136 if ( l->EyePosition[3] == 0.0F ||
1137 ( ( fcmd[LIT_ATTEN_CONST] == 0.0 || fcmd[LIT_ATTEN_CONST] == 1.0 ) &&
1138 fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) ) {
1139 /* Disable attenuation */
1140 icmd[idx] &= ~atten_flag;
1141 } else {
1142 if ( fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) {
1143 /* Enable only constant portion of attenuation calculation */
1144 icmd[idx] |= ( atten_flag | atten_const_flag );
1145 } else {
1146 /* Enable full attenuation calculation */
1147 icmd[idx] &= ~atten_const_flag;
1148 icmd[idx] |= atten_flag;
1149 }
1150 }
1151
1152 RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.tcl );
1153 break;
1154 }
1155 default:
1156 break;
1157 }
1158 }
1159
1160
1161
1162
1163 static void radeonLightModelfv( GLcontext *ctx, GLenum pname,
1164 const GLfloat *param )
1165 {
1166 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1167
1168 switch (pname) {
1169 case GL_LIGHT_MODEL_AMBIENT:
1170 update_global_ambient( ctx );
1171 break;
1172
1173 case GL_LIGHT_MODEL_LOCAL_VIEWER:
1174 RADEON_STATECHANGE( rmesa, tcl );
1175 if (ctx->Light.Model.LocalViewer)
1176 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LOCAL_VIEWER;
1177 else
1178 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_LOCAL_VIEWER;
1179 break;
1180
1181 case GL_LIGHT_MODEL_TWO_SIDE:
1182 RADEON_STATECHANGE( rmesa, tcl );
1183 if (ctx->Light.Model.TwoSide)
1184 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_LIGHT_TWOSIDE;
1185 else
1186 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_LIGHT_TWOSIDE;
1187
1188 check_twoside_fallback( ctx );
1189
1190 if (rmesa->TclFallback) {
1191 radeonChooseRenderState( ctx );
1192 radeonChooseVertexState( ctx );
1193 }
1194 break;
1195
1196 case GL_LIGHT_MODEL_COLOR_CONTROL:
1197 radeonUpdateSpecular(ctx);
1198 break;
1199
1200 default:
1201 break;
1202 }
1203 }
1204
1205 static void radeonShadeModel( GLcontext *ctx, GLenum mode )
1206 {
1207 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1208 GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL];
1209
1210 s &= ~(RADEON_DIFFUSE_SHADE_MASK |
1211 RADEON_ALPHA_SHADE_MASK |
1212 RADEON_SPECULAR_SHADE_MASK |
1213 RADEON_FOG_SHADE_MASK);
1214
1215 switch ( mode ) {
1216 case GL_FLAT:
1217 s |= (RADEON_DIFFUSE_SHADE_FLAT |
1218 RADEON_ALPHA_SHADE_FLAT |
1219 RADEON_SPECULAR_SHADE_FLAT |
1220 RADEON_FOG_SHADE_FLAT);
1221 break;
1222 case GL_SMOOTH:
1223 s |= (RADEON_DIFFUSE_SHADE_GOURAUD |
1224 RADEON_ALPHA_SHADE_GOURAUD |
1225 RADEON_SPECULAR_SHADE_GOURAUD |
1226 RADEON_FOG_SHADE_GOURAUD);
1227 break;
1228 default:
1229 return;
1230 }
1231
1232 if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) {
1233 RADEON_STATECHANGE( rmesa, set );
1234 rmesa->hw.set.cmd[SET_SE_CNTL] = s;
1235 }
1236 }
1237
1238
1239 /* =============================================================
1240 * User clip planes
1241 */
1242
1243 static void radeonClipPlane( GLcontext *ctx, GLenum plane, const GLfloat *eq )
1244 {
1245 GLint p = (GLint) plane - (GLint) GL_CLIP_PLANE0;
1246 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1247 GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
1248
1249 RADEON_STATECHANGE( rmesa, ucp[p] );
1250 rmesa->hw.ucp[p].cmd[UCP_X] = ip[0];
1251 rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1];
1252 rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2];
1253 rmesa->hw.ucp[p].cmd[UCP_W] = ip[3];
1254 }
1255
1256 static void radeonUpdateClipPlanes( GLcontext *ctx )
1257 {
1258 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1259 GLuint p;
1260
1261 for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
1262 if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
1263 GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
1264
1265 RADEON_STATECHANGE( rmesa, ucp[p] );
1266 rmesa->hw.ucp[p].cmd[UCP_X] = ip[0];
1267 rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1];
1268 rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2];
1269 rmesa->hw.ucp[p].cmd[UCP_W] = ip[3];
1270 }
1271 }
1272 }
1273
1274
1275 /* =============================================================
1276 * Stencil
1277 */
1278
1279 static void
1280 radeonStencilFuncSeparate( GLcontext *ctx, GLenum face, GLenum func,
1281 GLint ref, GLuint mask )
1282 {
1283 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1284 GLuint refmask = ((ctx->Stencil.Ref[0] << RADEON_STENCIL_REF_SHIFT) |
1285 (ctx->Stencil.ValueMask[0] << RADEON_STENCIL_MASK_SHIFT));
1286
1287 RADEON_STATECHANGE( rmesa, ctx );
1288 RADEON_STATECHANGE( rmesa, msk );
1289
1290 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~RADEON_STENCIL_TEST_MASK;
1291 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~(RADEON_STENCIL_REF_MASK|
1292 RADEON_STENCIL_VALUE_MASK);
1293
1294 switch ( ctx->Stencil.Function[0] ) {
1295 case GL_NEVER:
1296 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_NEVER;
1297 break;
1298 case GL_LESS:
1299 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_LESS;
1300 break;
1301 case GL_EQUAL:
1302 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_EQUAL;
1303 break;
1304 case GL_LEQUAL:
1305 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_LEQUAL;
1306 break;
1307 case GL_GREATER:
1308 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_GREATER;
1309 break;
1310 case GL_NOTEQUAL:
1311 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_NEQUAL;
1312 break;
1313 case GL_GEQUAL:
1314 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_GEQUAL;
1315 break;
1316 case GL_ALWAYS:
1317 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_ALWAYS;
1318 break;
1319 }
1320
1321 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |= refmask;
1322 }
1323
1324 static void
1325 radeonStencilMaskSeparate( GLcontext *ctx, GLenum face, GLuint mask )
1326 {
1327 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1328
1329 RADEON_STATECHANGE( rmesa, msk );
1330 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~RADEON_STENCIL_WRITE_MASK;
1331 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |=
1332 (ctx->Stencil.WriteMask[0] << RADEON_STENCIL_WRITEMASK_SHIFT);
1333 }
1334
1335 static void radeonStencilOpSeparate( GLcontext *ctx, GLenum face, GLenum fail,
1336 GLenum zfail, GLenum zpass )
1337 {
1338 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1339
1340 /* radeon 7200 have stencil bug, DEC and INC_WRAP will actually both do DEC_WRAP,
1341 and DEC_WRAP (and INVERT) will do INVERT. No way to get correct INC_WRAP and DEC,
1342 but DEC_WRAP can be fixed by using DEC and INC_WRAP at least use INC. */
1343
1344 GLuint tempRADEON_STENCIL_FAIL_DEC_WRAP;
1345 GLuint tempRADEON_STENCIL_FAIL_INC_WRAP;
1346 GLuint tempRADEON_STENCIL_ZFAIL_DEC_WRAP;
1347 GLuint tempRADEON_STENCIL_ZFAIL_INC_WRAP;
1348 GLuint tempRADEON_STENCIL_ZPASS_DEC_WRAP;
1349 GLuint tempRADEON_STENCIL_ZPASS_INC_WRAP;
1350
1351 if (rmesa->radeonScreen->chip_flags & RADEON_CHIPSET_BROKEN_STENCIL) {
1352 tempRADEON_STENCIL_FAIL_DEC_WRAP = RADEON_STENCIL_FAIL_DEC;
1353 tempRADEON_STENCIL_FAIL_INC_WRAP = RADEON_STENCIL_FAIL_INC;
1354 tempRADEON_STENCIL_ZFAIL_DEC_WRAP = RADEON_STENCIL_ZFAIL_DEC;
1355 tempRADEON_STENCIL_ZFAIL_INC_WRAP = RADEON_STENCIL_ZFAIL_INC;
1356 tempRADEON_STENCIL_ZPASS_DEC_WRAP = RADEON_STENCIL_ZPASS_DEC;
1357 tempRADEON_STENCIL_ZPASS_INC_WRAP = RADEON_STENCIL_ZPASS_INC;
1358 }
1359 else {
1360 tempRADEON_STENCIL_FAIL_DEC_WRAP = RADEON_STENCIL_FAIL_DEC_WRAP;
1361 tempRADEON_STENCIL_FAIL_INC_WRAP = RADEON_STENCIL_FAIL_INC_WRAP;
1362 tempRADEON_STENCIL_ZFAIL_DEC_WRAP = RADEON_STENCIL_ZFAIL_DEC_WRAP;
1363 tempRADEON_STENCIL_ZFAIL_INC_WRAP = RADEON_STENCIL_ZFAIL_INC_WRAP;
1364 tempRADEON_STENCIL_ZPASS_DEC_WRAP = RADEON_STENCIL_ZPASS_DEC_WRAP;
1365 tempRADEON_STENCIL_ZPASS_INC_WRAP = RADEON_STENCIL_ZPASS_INC_WRAP;
1366 }
1367
1368 RADEON_STATECHANGE( rmesa, ctx );
1369 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~(RADEON_STENCIL_FAIL_MASK |
1370 RADEON_STENCIL_ZFAIL_MASK |
1371 RADEON_STENCIL_ZPASS_MASK);
1372
1373 switch ( ctx->Stencil.FailFunc[0] ) {
1374 case GL_KEEP:
1375 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_KEEP;
1376 break;
1377 case GL_ZERO:
1378 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_ZERO;
1379 break;
1380 case GL_REPLACE:
1381 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_REPLACE;
1382 break;
1383 case GL_INCR:
1384 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_INC;
1385 break;
1386 case GL_DECR:
1387 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_DEC;
1388 break;
1389 case GL_INCR_WRAP:
1390 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= tempRADEON_STENCIL_FAIL_INC_WRAP;
1391 break;
1392 case GL_DECR_WRAP:
1393 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= tempRADEON_STENCIL_FAIL_DEC_WRAP;
1394 break;
1395 case GL_INVERT:
1396 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_INVERT;
1397 break;
1398 }
1399
1400 switch ( ctx->Stencil.ZFailFunc[0] ) {
1401 case GL_KEEP:
1402 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_KEEP;
1403 break;
1404 case GL_ZERO:
1405 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_ZERO;
1406 break;
1407 case GL_REPLACE:
1408 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_REPLACE;
1409 break;
1410 case GL_INCR:
1411 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_INC;
1412 break;
1413 case GL_DECR:
1414 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_DEC;
1415 break;
1416 case GL_INCR_WRAP:
1417 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= tempRADEON_STENCIL_ZFAIL_INC_WRAP;
1418 break;
1419 case GL_DECR_WRAP:
1420 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= tempRADEON_STENCIL_ZFAIL_DEC_WRAP;
1421 break;
1422 case GL_INVERT:
1423 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_INVERT;
1424 break;
1425 }
1426
1427 switch ( ctx->Stencil.ZPassFunc[0] ) {
1428 case GL_KEEP:
1429 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_KEEP;
1430 break;
1431 case GL_ZERO:
1432 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_ZERO;
1433 break;
1434 case GL_REPLACE:
1435 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_REPLACE;
1436 break;
1437 case GL_INCR:
1438 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_INC;
1439 break;
1440 case GL_DECR:
1441 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_DEC;
1442 break;
1443 case GL_INCR_WRAP:
1444 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= tempRADEON_STENCIL_ZPASS_INC_WRAP;
1445 break;
1446 case GL_DECR_WRAP:
1447 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= tempRADEON_STENCIL_ZPASS_DEC_WRAP;
1448 break;
1449 case GL_INVERT:
1450 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_INVERT;
1451 break;
1452 }
1453 }
1454
1455 static void radeonClearStencil( GLcontext *ctx, GLint s )
1456 {
1457 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1458
1459 rmesa->state.stencil.clear =
1460 ((GLuint) ctx->Stencil.Clear |
1461 (0xff << RADEON_STENCIL_MASK_SHIFT) |
1462 (ctx->Stencil.WriteMask[0] << RADEON_STENCIL_WRITEMASK_SHIFT));
1463 }
1464
1465
1466 /* =============================================================
1467 * Window position and viewport transformation
1468 */
1469
1470 /*
1471 * To correctly position primitives:
1472 */
1473 #define SUBPIXEL_X 0.125
1474 #define SUBPIXEL_Y 0.125
1475
1476
1477 /**
1478 * Called when window size or position changes or viewport or depth range
1479 * state is changed. We update the hardware viewport state here.
1480 */
1481 void radeonUpdateWindow( GLcontext *ctx )
1482 {
1483 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1484 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
1485 GLfloat xoffset = (GLfloat)dPriv->x;
1486 GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h;
1487 const GLfloat *v = ctx->Viewport._WindowMap.m;
1488
1489 GLfloat sx = v[MAT_SX];
1490 GLfloat tx = v[MAT_TX] + xoffset + SUBPIXEL_X;
1491 GLfloat sy = - v[MAT_SY];
1492 GLfloat ty = (- v[MAT_TY]) + yoffset + SUBPIXEL_Y;
1493 GLfloat sz = v[MAT_SZ] * rmesa->state.depth.scale;
1494 GLfloat tz = v[MAT_TZ] * rmesa->state.depth.scale;
1495 RADEON_FIREVERTICES( rmesa );
1496 RADEON_STATECHANGE( rmesa, vpt );
1497
1498 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XSCALE] = *(GLuint *)&sx;
1499 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = *(GLuint *)&tx;
1500 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YSCALE] = *(GLuint *)&sy;
1501 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = *(GLuint *)&ty;
1502 rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZSCALE] = *(GLuint *)&sz;
1503 rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZOFFSET] = *(GLuint *)&tz;
1504 }
1505
1506
1507 static void radeonViewport( GLcontext *ctx, GLint x, GLint y,
1508 GLsizei width, GLsizei height )
1509 {
1510 /* Don't pipeline viewport changes, conflict with window offset
1511 * setting below. Could apply deltas to rescue pipelined viewport
1512 * values, or keep the originals hanging around.
1513 */
1514 RADEON_FIREVERTICES( RADEON_CONTEXT(ctx) );
1515 radeonUpdateWindow( ctx );
1516 }
1517
1518 static void radeonDepthRange( GLcontext *ctx, GLclampd nearval,
1519 GLclampd farval )
1520 {
1521 radeonUpdateWindow( ctx );
1522 }
1523
1524 void radeonUpdateViewportOffset( GLcontext *ctx )
1525 {
1526 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1527 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
1528 GLfloat xoffset = (GLfloat)dPriv->x;
1529 GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h;
1530 const GLfloat *v = ctx->Viewport._WindowMap.m;
1531
1532 GLfloat tx = v[MAT_TX] + xoffset + SUBPIXEL_X;
1533 GLfloat ty = (- v[MAT_TY]) + yoffset + SUBPIXEL_Y;
1534
1535 if ( rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] != *(GLuint *)&tx ||
1536 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] != *(GLuint *)&ty )
1537 {
1538 /* Note: this should also modify whatever data the context reset
1539 * code uses...
1540 */
1541 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = *(GLuint *)&tx;
1542 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = *(GLuint *)&ty;
1543
1544 /* update polygon stipple x/y screen offset */
1545 {
1546 GLuint stx, sty;
1547 GLuint m = rmesa->hw.msc.cmd[MSC_RE_MISC];
1548
1549 m &= ~(RADEON_STIPPLE_X_OFFSET_MASK |
1550 RADEON_STIPPLE_Y_OFFSET_MASK);
1551
1552 /* add magic offsets, then invert */
1553 stx = 31 - ((rmesa->dri.drawable->x - 1) & RADEON_STIPPLE_COORD_MASK);
1554 sty = 31 - ((rmesa->dri.drawable->y + rmesa->dri.drawable->h - 1)
1555 & RADEON_STIPPLE_COORD_MASK);
1556
1557 m |= ((stx << RADEON_STIPPLE_X_OFFSET_SHIFT) |
1558 (sty << RADEON_STIPPLE_Y_OFFSET_SHIFT));
1559
1560 if ( rmesa->hw.msc.cmd[MSC_RE_MISC] != m ) {
1561 RADEON_STATECHANGE( rmesa, msc );
1562 rmesa->hw.msc.cmd[MSC_RE_MISC] = m;
1563 }
1564 }
1565 }
1566
1567 radeonUpdateScissor( ctx );
1568 }
1569
1570
1571
1572 /* =============================================================
1573 * Miscellaneous
1574 */
1575
1576 static void radeonClearColor( GLcontext *ctx, const GLfloat color[4] )
1577 {
1578 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1579 GLubyte c[4];
1580 CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]);
1581 CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]);
1582 CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]);
1583 CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]);
1584 rmesa->state.color.clear = radeonPackColor( rmesa->radeonScreen->cpp,
1585 c[0], c[1], c[2], c[3] );
1586 }
1587
1588
1589 static void radeonRenderMode( GLcontext *ctx, GLenum mode )
1590 {
1591 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1592 FALLBACK( rmesa, RADEON_FALLBACK_RENDER_MODE, (mode != GL_RENDER) );
1593 }
1594
1595
1596 static GLuint radeon_rop_tab[] = {
1597 RADEON_ROP_CLEAR,
1598 RADEON_ROP_AND,
1599 RADEON_ROP_AND_REVERSE,
1600 RADEON_ROP_COPY,
1601 RADEON_ROP_AND_INVERTED,
1602 RADEON_ROP_NOOP,
1603 RADEON_ROP_XOR,
1604 RADEON_ROP_OR,
1605 RADEON_ROP_NOR,
1606 RADEON_ROP_EQUIV,
1607 RADEON_ROP_INVERT,
1608 RADEON_ROP_OR_REVERSE,
1609 RADEON_ROP_COPY_INVERTED,
1610 RADEON_ROP_OR_INVERTED,
1611 RADEON_ROP_NAND,
1612 RADEON_ROP_SET,
1613 };
1614
1615 static void radeonLogicOpCode( GLcontext *ctx, GLenum opcode )
1616 {
1617 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1618 GLuint rop = (GLuint)opcode - GL_CLEAR;
1619
1620 ASSERT( rop < 16 );
1621
1622 RADEON_STATECHANGE( rmesa, msk );
1623 rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = radeon_rop_tab[rop];
1624 }
1625
1626
1627 /**
1628 * Set up the cliprects for either front or back-buffer drawing.
1629 */
1630 void radeonSetCliprects( radeonContextPtr rmesa )
1631 {
1632 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
1633
1634 if (rmesa->glCtx->DrawBuffer->_ColorDrawBufferMask[0]
1635 == BUFFER_BIT_BACK_LEFT) {
1636 /* Can't ignore 2d windows if we are page flipping.
1637 */
1638 if ( dPriv->numBackClipRects == 0 || rmesa->doPageFlip ) {
1639 rmesa->numClipRects = dPriv->numClipRects;
1640 rmesa->pClipRects = dPriv->pClipRects;
1641 }
1642 else {
1643 rmesa->numClipRects = dPriv->numBackClipRects;
1644 rmesa->pClipRects = dPriv->pBackClipRects;
1645 }
1646 }
1647 else {
1648 /* front buffer (or none, or multiple buffers */
1649 rmesa->numClipRects = dPriv->numClipRects;
1650 rmesa->pClipRects = dPriv->pClipRects;
1651 }
1652
1653 if (rmesa->state.scissor.enabled)
1654 radeonRecalcScissorRects( rmesa );
1655 }
1656
1657
1658 /**
1659 * Called via glDrawBuffer.
1660 */
1661 static void radeonDrawBuffer( GLcontext *ctx, GLenum mode )
1662 {
1663 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1664
1665 if (RADEON_DEBUG & DEBUG_DRI)
1666 fprintf(stderr, "%s %s\n", __FUNCTION__,
1667 _mesa_lookup_enum_by_nr( mode ));
1668
1669 RADEON_FIREVERTICES(rmesa); /* don't pipeline cliprect changes */
1670
1671 /*
1672 * _ColorDrawBufferMask is easier to cope with than <mode>.
1673 * Check for software fallback, update cliprects.
1674 */
1675 switch ( ctx->DrawBuffer->_ColorDrawBufferMask[0] ) {
1676 case BUFFER_BIT_FRONT_LEFT:
1677 case BUFFER_BIT_BACK_LEFT:
1678 FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_FALSE );
1679 break;
1680 default:
1681 /* 0 (GL_NONE) buffers or multiple color drawing buffers */
1682 FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_TRUE );
1683 return;
1684 }
1685
1686 radeonSetCliprects( rmesa );
1687
1688 /* We'll set the drawing engine's offset/pitch parameters later
1689 * when we update other state.
1690 */
1691 }
1692
1693 static void radeonReadBuffer( GLcontext *ctx, GLenum mode )
1694 {
1695 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
1696 }
1697
1698
1699 /* =============================================================
1700 * State enable/disable
1701 */
1702
1703 static void radeonEnable( GLcontext *ctx, GLenum cap, GLboolean state )
1704 {
1705 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1706 GLuint p, flag;
1707
1708 if ( RADEON_DEBUG & DEBUG_STATE )
1709 fprintf( stderr, "%s( %s = %s )\n", __FUNCTION__,
1710 _mesa_lookup_enum_by_nr( cap ),
1711 state ? "GL_TRUE" : "GL_FALSE" );
1712
1713 switch ( cap ) {
1714 /* Fast track this one...
1715 */
1716 case GL_TEXTURE_1D:
1717 case GL_TEXTURE_2D:
1718 case GL_TEXTURE_3D:
1719 break;
1720
1721 case GL_ALPHA_TEST:
1722 RADEON_STATECHANGE( rmesa, ctx );
1723 if (state) {
1724 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_ALPHA_TEST_ENABLE;
1725 } else {
1726 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_ALPHA_TEST_ENABLE;
1727 }
1728 break;
1729
1730 case GL_BLEND:
1731 RADEON_STATECHANGE( rmesa, ctx );
1732 if (state) {
1733 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_ALPHA_BLEND_ENABLE;
1734 } else {
1735 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ALPHA_BLEND_ENABLE;
1736 }
1737 if ( ctx->Color._LogicOpEnabled ) {
1738 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_ROP_ENABLE;
1739 } else {
1740 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ROP_ENABLE;
1741 }
1742
1743 /* Catch a possible fallback:
1744 */
1745 if (state) {
1746 ctx->Driver.BlendEquationSeparate( ctx,
1747 ctx->Color.BlendEquationRGB,
1748 ctx->Color.BlendEquationA );
1749 ctx->Driver.BlendFuncSeparate( ctx, ctx->Color.BlendSrcRGB,
1750 ctx->Color.BlendDstRGB,
1751 ctx->Color.BlendSrcA,
1752 ctx->Color.BlendDstA );
1753 }
1754 else {
1755 FALLBACK( rmesa, RADEON_FALLBACK_BLEND_FUNC, GL_FALSE );
1756 FALLBACK( rmesa, RADEON_FALLBACK_BLEND_EQ, GL_FALSE );
1757 }
1758 break;
1759
1760 case GL_CLIP_PLANE0:
1761 case GL_CLIP_PLANE1:
1762 case GL_CLIP_PLANE2:
1763 case GL_CLIP_PLANE3:
1764 case GL_CLIP_PLANE4:
1765 case GL_CLIP_PLANE5:
1766 p = cap-GL_CLIP_PLANE0;
1767 RADEON_STATECHANGE( rmesa, tcl );
1768 if (state) {
1769 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (RADEON_UCP_ENABLE_0<<p);
1770 radeonClipPlane( ctx, cap, NULL );
1771 }
1772 else {
1773 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(RADEON_UCP_ENABLE_0<<p);
1774 }
1775 break;
1776
1777 case GL_COLOR_MATERIAL:
1778 radeonColorMaterial( ctx, 0, 0 );
1779 radeonUpdateMaterial( ctx );
1780 break;
1781
1782 case GL_CULL_FACE:
1783 radeonCullFace( ctx, 0 );
1784 break;
1785
1786 case GL_DEPTH_TEST:
1787 RADEON_STATECHANGE(rmesa, ctx );
1788 if ( state ) {
1789 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_Z_ENABLE;
1790 } else {
1791 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_Z_ENABLE;
1792 }
1793 break;
1794
1795 case GL_DITHER:
1796 RADEON_STATECHANGE(rmesa, ctx );
1797 if ( state ) {
1798 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_DITHER_ENABLE;
1799 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~rmesa->state.color.roundEnable;
1800 } else {
1801 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_DITHER_ENABLE;
1802 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= rmesa->state.color.roundEnable;
1803 }
1804 break;
1805
1806 case GL_FOG:
1807 RADEON_STATECHANGE(rmesa, ctx );
1808 if ( state ) {
1809 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_FOG_ENABLE;
1810 radeonFogfv( ctx, GL_FOG_MODE, NULL );
1811 } else {
1812 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_FOG_ENABLE;
1813 RADEON_STATECHANGE(rmesa, tcl);
1814 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_TCL_FOG_MASK;
1815 }
1816 radeonUpdateSpecular( ctx ); /* for PK_SPEC */
1817 _mesa_allow_light_in_model( ctx, !state );
1818 break;
1819
1820 case GL_LIGHT0:
1821 case GL_LIGHT1:
1822 case GL_LIGHT2:
1823 case GL_LIGHT3:
1824 case GL_LIGHT4:
1825 case GL_LIGHT5:
1826 case GL_LIGHT6:
1827 case GL_LIGHT7:
1828 RADEON_STATECHANGE(rmesa, tcl);
1829 p = cap - GL_LIGHT0;
1830 if (p&1)
1831 flag = (RADEON_LIGHT_1_ENABLE |
1832 RADEON_LIGHT_1_ENABLE_AMBIENT |
1833 RADEON_LIGHT_1_ENABLE_SPECULAR);
1834 else
1835 flag = (RADEON_LIGHT_0_ENABLE |
1836 RADEON_LIGHT_0_ENABLE_AMBIENT |
1837 RADEON_LIGHT_0_ENABLE_SPECULAR);
1838
1839 if (state)
1840 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] |= flag;
1841 else
1842 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] &= ~flag;
1843
1844 /*
1845 */
1846 update_light_colors( ctx, p );
1847 break;
1848
1849 case GL_LIGHTING:
1850 RADEON_STATECHANGE(rmesa, tcl);
1851 radeonUpdateSpecular(ctx);
1852 check_twoside_fallback( ctx );
1853 break;
1854
1855 case GL_LINE_SMOOTH:
1856 RADEON_STATECHANGE( rmesa, ctx );
1857 if ( state ) {
1858 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_ANTI_ALIAS_LINE;
1859 } else {
1860 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_ANTI_ALIAS_LINE;
1861 }
1862 break;
1863
1864 case GL_LINE_STIPPLE:
1865 RADEON_STATECHANGE( rmesa, ctx );
1866 if ( state ) {
1867 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_PATTERN_ENABLE;
1868 } else {
1869 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_PATTERN_ENABLE;
1870 }
1871 break;
1872
1873 case GL_COLOR_LOGIC_OP:
1874 RADEON_STATECHANGE( rmesa, ctx );
1875 if ( ctx->Color._LogicOpEnabled ) {
1876 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_ROP_ENABLE;
1877 } else {
1878 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ROP_ENABLE;
1879 }
1880 break;
1881
1882 case GL_NORMALIZE:
1883 RADEON_STATECHANGE( rmesa, tcl );
1884 if ( state ) {
1885 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_NORMALIZE_NORMALS;
1886 } else {
1887 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_NORMALIZE_NORMALS;
1888 }
1889 break;
1890
1891 case GL_POLYGON_OFFSET_POINT:
1892 RADEON_STATECHANGE( rmesa, set );
1893 if ( state ) {
1894 rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_ZBIAS_ENABLE_POINT;
1895 } else {
1896 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_ZBIAS_ENABLE_POINT;
1897 }
1898 break;
1899
1900 case GL_POLYGON_OFFSET_LINE:
1901 RADEON_STATECHANGE( rmesa, set );
1902 if ( state ) {
1903 rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_ZBIAS_ENABLE_LINE;
1904 } else {
1905 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_ZBIAS_ENABLE_LINE;
1906 }
1907 break;
1908
1909 case GL_POLYGON_OFFSET_FILL:
1910 RADEON_STATECHANGE( rmesa, set );
1911 if ( state ) {
1912 rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_ZBIAS_ENABLE_TRI;
1913 } else {
1914 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_ZBIAS_ENABLE_TRI;
1915 }
1916 break;
1917
1918 case GL_POLYGON_SMOOTH:
1919 RADEON_STATECHANGE( rmesa, ctx );
1920 if ( state ) {
1921 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_ANTI_ALIAS_POLY;
1922 } else {
1923 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_ANTI_ALIAS_POLY;
1924 }
1925 break;
1926
1927 case GL_POLYGON_STIPPLE:
1928 RADEON_STATECHANGE(rmesa, ctx );
1929 if ( state ) {
1930 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_STIPPLE_ENABLE;
1931 } else {
1932 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_STIPPLE_ENABLE;
1933 }
1934 break;
1935
1936 case GL_RESCALE_NORMAL_EXT: {
1937 GLboolean tmp = ctx->_NeedEyeCoords ? state : !state;
1938 RADEON_STATECHANGE( rmesa, tcl );
1939 if ( tmp ) {
1940 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_RESCALE_NORMALS;
1941 } else {
1942 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_RESCALE_NORMALS;
1943 }
1944 break;
1945 }
1946
1947 case GL_SCISSOR_TEST:
1948 RADEON_FIREVERTICES( rmesa );
1949 rmesa->state.scissor.enabled = state;
1950 radeonUpdateScissor( ctx );
1951 break;
1952
1953 case GL_STENCIL_TEST:
1954 if ( rmesa->state.stencil.hwBuffer ) {
1955 RADEON_STATECHANGE( rmesa, ctx );
1956 if ( state ) {
1957 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_STENCIL_ENABLE;
1958 } else {
1959 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_STENCIL_ENABLE;
1960 }
1961 } else {
1962 FALLBACK( rmesa, RADEON_FALLBACK_STENCIL, state );
1963 }
1964 break;
1965
1966 case GL_TEXTURE_GEN_Q:
1967 case GL_TEXTURE_GEN_R:
1968 case GL_TEXTURE_GEN_S:
1969 case GL_TEXTURE_GEN_T:
1970 /* Picked up in radeonUpdateTextureState.
1971 */
1972 rmesa->recheck_texgen[ctx->Texture.CurrentUnit] = GL_TRUE;
1973 break;
1974
1975 case GL_COLOR_SUM_EXT:
1976 radeonUpdateSpecular ( ctx );
1977 break;
1978
1979 default:
1980 return;
1981 }
1982 }
1983
1984
1985 static void radeonLightingSpaceChange( GLcontext *ctx )
1986 {
1987 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1988 GLboolean tmp;
1989 RADEON_STATECHANGE( rmesa, tcl );
1990
1991 if (RADEON_DEBUG & DEBUG_STATE)
1992 fprintf(stderr, "%s %d BEFORE %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
1993 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]);
1994
1995 if (ctx->_NeedEyeCoords)
1996 tmp = ctx->Transform.RescaleNormals;
1997 else
1998 tmp = !ctx->Transform.RescaleNormals;
1999
2000 if ( tmp ) {
2001 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_RESCALE_NORMALS;
2002 } else {
2003 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_RESCALE_NORMALS;
2004 }
2005
2006 if (RADEON_DEBUG & DEBUG_STATE)
2007 fprintf(stderr, "%s %d AFTER %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
2008 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]);
2009 }
2010
2011 /* =============================================================
2012 * Deferred state management - matrices, textures, other?
2013 */
2014
2015 static void texmat_set_texrect( radeonContextPtr rmesa,
2016 struct gl_texture_object *tObj, GLuint unit )
2017 {
2018 const struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel];
2019 _math_matrix_set_identity( &rmesa->tmpmat[unit] );
2020 rmesa->tmpmat[unit].m[0] = 1.0 / baseImage->Width;
2021 rmesa->tmpmat[unit].m[5] = 1.0 / baseImage->Height;
2022
2023 }
2024
2025 static void texmat_fixup_texrect( radeonContextPtr rmesa,
2026 struct gl_texture_object *tObj, GLuint unit )
2027 {
2028 const struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel];
2029 GLuint i;
2030 for (i = 0; i < 4; i++) {
2031 rmesa->tmpmat[unit].m[i] = rmesa->tmpmat[unit].m[i] / baseImage->Width;
2032 rmesa->tmpmat[unit].m[i+4] = rmesa->tmpmat[unit].m[i+4] / baseImage->Height;
2033 }}
2034
2035
2036 void radeonUploadTexMatrix( radeonContextPtr rmesa,
2037 int unit, GLboolean swapcols )
2038 {
2039 /* Here's how this works: on r100, only 3 tex coords can be submitted, so the
2040 vector looks like this probably: (s t r|q 0) (not sure if the last coord
2041 is hardwired to 0, could be 1 too). Interestingly, it actually looks like
2042 texgen generates all 4 coords, at least tests with projtex indicated that.
2043 So: if we need the q coord in the end (solely determined by the texture
2044 target, i.e. 2d / 1d / texrect targets) we swap the third and 4th row.
2045 Additionally, if we don't have texgen but 4 tex coords submitted, we swap
2046 column 3 and 4 (for the 2d / 1d / texrect targets) since the the q coord
2047 will get submitted in the "wrong", i.e. 3rd, slot.
2048 If an app submits 3 coords for 2d targets, we assume it is saving on vertex
2049 size and using the texture matrix to swap the r and q coords around (ut2k3
2050 does exactly that), so we don't need the 3rd / 4th column swap - still need
2051 the 3rd / 4th row swap of course. This will potentially break for apps which
2052 use TexCoord3x just for fun. Additionally, it will never work if an app uses
2053 an "advanced" texture matrix and relies on all 4 texcoord inputs to generate
2054 the maximum needed 3. This seems impossible to do with hw tcl on r100, and
2055 incredibly hard to detect so we can't just fallback in such a case. Assume
2056 it never happens... - rs
2057 */
2058
2059 int idx = TEXMAT_0 + unit;
2060 float *dest = ((float *)RADEON_DB_STATE( mat[idx] )) + MAT_ELT_0;
2061 int i;
2062 struct gl_texture_unit tUnit = rmesa->glCtx->Texture.Unit[unit];
2063 GLfloat *src = rmesa->tmpmat[unit].m;
2064
2065 rmesa->TexMatColSwap &= ~(1 << unit);
2066 if ((tUnit._ReallyEnabled & (TEXTURE_3D_BIT | TEXTURE_CUBE_BIT)) == 0) {
2067 if (swapcols) {
2068 rmesa->TexMatColSwap |= 1 << unit;
2069 /* attention some elems are swapped 2 times! */
2070 *dest++ = src[0];
2071 *dest++ = src[4];
2072 *dest++ = src[12];
2073 *dest++ = src[8];
2074 *dest++ = src[1];
2075 *dest++ = src[5];
2076 *dest++ = src[13];
2077 *dest++ = src[9];
2078 *dest++ = src[2];
2079 *dest++ = src[6];
2080 *dest++ = src[15];
2081 *dest++ = src[11];
2082 /* those last 4 are probably never used */
2083 *dest++ = src[3];
2084 *dest++ = src[7];
2085 *dest++ = src[14];
2086 *dest++ = src[10];
2087 }
2088 else {
2089 for (i = 0; i < 2; i++) {
2090 *dest++ = src[i];
2091 *dest++ = src[i+4];
2092 *dest++ = src[i+8];
2093 *dest++ = src[i+12];
2094 }
2095 for (i = 3; i >= 2; i--) {
2096 *dest++ = src[i];
2097 *dest++ = src[i+4];
2098 *dest++ = src[i+8];
2099 *dest++ = src[i+12];
2100 }
2101 }
2102 }
2103 else {
2104 for (i = 0 ; i < 4 ; i++) {
2105 *dest++ = src[i];
2106 *dest++ = src[i+4];
2107 *dest++ = src[i+8];
2108 *dest++ = src[i+12];
2109 }
2110 }
2111
2112 RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2113 }
2114
2115
2116 static void upload_matrix( radeonContextPtr rmesa, GLfloat *src, int idx )
2117 {
2118 float *dest = ((float *)RADEON_DB_STATE( mat[idx] ))+MAT_ELT_0;
2119 int i;
2120
2121
2122 for (i = 0 ; i < 4 ; i++) {
2123 *dest++ = src[i];
2124 *dest++ = src[i+4];
2125 *dest++ = src[i+8];
2126 *dest++ = src[i+12];
2127 }
2128
2129 RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2130 }
2131
2132 static void upload_matrix_t( radeonContextPtr rmesa, GLfloat *src, int idx )
2133 {
2134 float *dest = ((float *)RADEON_DB_STATE( mat[idx] ))+MAT_ELT_0;
2135 memcpy(dest, src, 16*sizeof(float));
2136 RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2137 }
2138
2139
2140 static void update_texturematrix( GLcontext *ctx )
2141 {
2142 radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
2143 GLuint tpc = rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL];
2144 GLuint vs = rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL];
2145 int unit;
2146 GLuint texMatEnabled = 0;
2147 rmesa->NeedTexMatrix = 0;
2148 rmesa->TexMatColSwap = 0;
2149
2150 for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++) {
2151 if (ctx->Texture.Unit[unit]._ReallyEnabled) {
2152 GLboolean needMatrix = GL_FALSE;
2153 if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY) {
2154 needMatrix = GL_TRUE;
2155 texMatEnabled |= (RADEON_TEXGEN_TEXMAT_0_ENABLE |
2156 RADEON_TEXMAT_0_ENABLE) << unit;
2157
2158 if (rmesa->TexGenEnabled & (RADEON_TEXMAT_0_ENABLE << unit)) {
2159 /* Need to preconcatenate any active texgen
2160 * obj/eyeplane matrices:
2161 */
2162 _math_matrix_mul_matrix( &rmesa->tmpmat[unit],
2163 ctx->TextureMatrixStack[unit].Top,
2164 &rmesa->TexGenMatrix[unit] );
2165 }
2166 else {
2167 _math_matrix_copy( &rmesa->tmpmat[unit],
2168 ctx->TextureMatrixStack[unit].Top );
2169 }
2170 }
2171 else if (rmesa->TexGenEnabled & (RADEON_TEXMAT_0_ENABLE << unit)) {
2172 _math_matrix_copy( &rmesa->tmpmat[unit], &rmesa->TexGenMatrix[unit] );
2173 needMatrix = GL_TRUE;
2174 }
2175 if (ctx->Texture.Unit[unit]._ReallyEnabled == TEXTURE_RECT_BIT) {
2176 texMatEnabled |= (RADEON_TEXGEN_TEXMAT_0_ENABLE |
2177 RADEON_TEXMAT_0_ENABLE) << unit;
2178 if (needMatrix)
2179 texmat_fixup_texrect( rmesa, ctx->Texture.Unit[unit]._Current, unit );
2180 else
2181 texmat_set_texrect( rmesa, ctx->Texture.Unit[unit]._Current, unit );
2182 needMatrix = GL_TRUE;
2183 }
2184 if (needMatrix) {
2185 rmesa->NeedTexMatrix |= 1 << unit;
2186 radeonUploadTexMatrix( rmesa, unit,
2187 !ctx->Texture.Unit[unit].TexGenEnabled );
2188 }
2189 }
2190 }
2191
2192 tpc = (texMatEnabled | rmesa->TexGenEnabled);
2193
2194 /* TCL_TEX_COMPUTED_x is TCL_TEX_INPUT_x | 0x8 */
2195 vs &= ~((RADEON_TCL_TEX_COMPUTED_TEX_0 << RADEON_TCL_TEX_0_OUTPUT_SHIFT) |
2196 (RADEON_TCL_TEX_COMPUTED_TEX_0 << RADEON_TCL_TEX_1_OUTPUT_SHIFT) |
2197 (RADEON_TCL_TEX_COMPUTED_TEX_0 << RADEON_TCL_TEX_2_OUTPUT_SHIFT));
2198
2199 vs |= (((tpc & RADEON_TEXGEN_TEXMAT_0_ENABLE) <<
2200 (RADEON_TCL_TEX_0_OUTPUT_SHIFT + 3)) |
2201 ((tpc & RADEON_TEXGEN_TEXMAT_1_ENABLE) <<
2202 (RADEON_TCL_TEX_1_OUTPUT_SHIFT + 2)) |
2203 ((tpc & RADEON_TEXGEN_TEXMAT_2_ENABLE) <<
2204 (RADEON_TCL_TEX_2_OUTPUT_SHIFT + 1)));
2205
2206 if (tpc != rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL] ||
2207 vs != rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL]) {
2208
2209 RADEON_STATECHANGE(rmesa, tcl);
2210 rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL] = tpc;
2211 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] = vs;
2212 }
2213 }
2214
2215
2216 /**
2217 * Tell the card where to render (offset, pitch).
2218 * Effected by glDrawBuffer, etc
2219 */
2220 void
2221 radeonUpdateDrawBuffer(GLcontext *ctx)
2222 {
2223 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
2224 struct gl_framebuffer *fb = ctx->DrawBuffer;
2225 driRenderbuffer *drb;
2226
2227 if (fb->_ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT) {
2228 /* draw to front */
2229 drb = (driRenderbuffer *) fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
2230 }
2231 else if (fb->_ColorDrawBufferMask[0] == BUFFER_BIT_BACK_LEFT) {
2232 /* draw to back */
2233 drb = (driRenderbuffer *) fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
2234 }
2235 else {
2236 /* drawing to multiple buffers, or none */
2237 return;
2238 }
2239
2240 assert(drb);
2241 assert(drb->flippedPitch);
2242
2243 RADEON_STATECHANGE( rmesa, ctx );
2244
2245 /* Note: we used the (possibly) page-flipped values */
2246 rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET]
2247 = ((drb->flippedOffset + rmesa->radeonScreen->fbLocation)
2248 & RADEON_COLOROFFSET_MASK);
2249 rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = drb->flippedPitch;
2250 if (rmesa->sarea->tiling_enabled) {
2251 rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] |= RADEON_COLOR_TILE_ENABLE;
2252 }
2253 }
2254
2255
2256 void radeonValidateState( GLcontext *ctx )
2257 {
2258 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
2259 GLuint new_state = rmesa->NewGLState;
2260
2261 if (new_state & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) {
2262 radeonUpdateDrawBuffer(ctx);
2263 }
2264
2265 if (new_state & _NEW_TEXTURE) {
2266 radeonUpdateTextureState( ctx );
2267 new_state |= rmesa->NewGLState; /* may add TEXTURE_MATRIX */
2268 }
2269
2270 /* Need an event driven matrix update?
2271 */
2272 if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION))
2273 upload_matrix( rmesa, ctx->_ModelProjectMatrix.m, MODEL_PROJ );
2274
2275 /* Need these for lighting (shouldn't upload otherwise)
2276 */
2277 if (new_state & (_NEW_MODELVIEW)) {
2278 upload_matrix( rmesa, ctx->ModelviewMatrixStack.Top->m, MODEL );
2279 upload_matrix_t( rmesa, ctx->ModelviewMatrixStack.Top->inv, MODEL_IT );
2280 }
2281
2282 /* Does this need to be triggered on eg. modelview for
2283 * texgen-derived objplane/eyeplane matrices?
2284 */
2285 if (new_state & _NEW_TEXTURE_MATRIX) {
2286 update_texturematrix( ctx );
2287 }
2288
2289 if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW|_MESA_NEW_NEED_EYE_COORDS)) {
2290 update_light( ctx );
2291 }
2292
2293 /* emit all active clip planes if projection matrix changes.
2294 */
2295 if (new_state & (_NEW_PROJECTION)) {
2296 if (ctx->Transform.ClipPlanesEnabled)
2297 radeonUpdateClipPlanes( ctx );
2298 }
2299
2300
2301 rmesa->NewGLState = 0;
2302 }
2303
2304
2305 static void radeonInvalidateState( GLcontext *ctx, GLuint new_state )
2306 {
2307 _swrast_InvalidateState( ctx, new_state );
2308 _swsetup_InvalidateState( ctx, new_state );
2309 _ac_InvalidateState( ctx, new_state );
2310 _tnl_InvalidateState( ctx, new_state );
2311 _ae_invalidate_state( ctx, new_state );
2312 RADEON_CONTEXT(ctx)->NewGLState |= new_state;
2313 radeonVtxfmtInvalidate( ctx );
2314 }
2315
2316
2317 /* A hack. Need a faster way to find this out.
2318 */
2319 static GLboolean check_material( GLcontext *ctx )
2320 {
2321 TNLcontext *tnl = TNL_CONTEXT(ctx);
2322 GLint i;
2323
2324 for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT;
2325 i < _TNL_ATTRIB_MAT_BACK_INDEXES;
2326 i++)
2327 if (tnl->vb.AttribPtr[i] &&
2328 tnl->vb.AttribPtr[i]->stride)
2329 return GL_TRUE;
2330
2331 return GL_FALSE;
2332 }
2333
2334
2335 static void radeonWrapRunPipeline( GLcontext *ctx )
2336 {
2337 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
2338 GLboolean has_material;
2339
2340 if (0)
2341 fprintf(stderr, "%s, newstate: %x\n", __FUNCTION__, rmesa->NewGLState);
2342
2343 /* Validate state:
2344 */
2345 if (rmesa->NewGLState)
2346 radeonValidateState( ctx );
2347
2348 has_material = (ctx->Light.Enabled && check_material( ctx ));
2349
2350 if (has_material) {
2351 TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_MATERIAL, GL_TRUE );
2352 }
2353
2354 /* Run the pipeline.
2355 */
2356 _tnl_run_pipeline( ctx );
2357
2358 if (has_material) {
2359 TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_MATERIAL, GL_FALSE );
2360 }
2361 }
2362
2363
2364 /* Initialize the driver's state functions.
2365 * Many of the ctx->Driver functions might have been initialized to
2366 * software defaults in the earlier _mesa_init_driver_functions() call.
2367 */
2368 void radeonInitStateFuncs( GLcontext *ctx )
2369 {
2370 ctx->Driver.UpdateState = radeonInvalidateState;
2371 ctx->Driver.LightingSpaceChange = radeonLightingSpaceChange;
2372
2373 ctx->Driver.DrawBuffer = radeonDrawBuffer;
2374 ctx->Driver.ReadBuffer = radeonReadBuffer;
2375
2376 ctx->Driver.AlphaFunc = radeonAlphaFunc;
2377 ctx->Driver.BlendEquationSeparate = radeonBlendEquationSeparate;
2378 ctx->Driver.BlendFuncSeparate = radeonBlendFuncSeparate;
2379 ctx->Driver.ClearColor = radeonClearColor;
2380 ctx->Driver.ClearDepth = radeonClearDepth;
2381 ctx->Driver.ClearIndex = NULL;
2382 ctx->Driver.ClearStencil = radeonClearStencil;
2383 ctx->Driver.ClipPlane = radeonClipPlane;
2384 ctx->Driver.ColorMask = radeonColorMask;
2385 ctx->Driver.CullFace = radeonCullFace;
2386 ctx->Driver.DepthFunc = radeonDepthFunc;
2387 ctx->Driver.DepthMask = radeonDepthMask;
2388 ctx->Driver.DepthRange = radeonDepthRange;
2389 ctx->Driver.Enable = radeonEnable;
2390 ctx->Driver.Fogfv = radeonFogfv;
2391 ctx->Driver.FrontFace = radeonFrontFace;
2392 ctx->Driver.Hint = NULL;
2393 ctx->Driver.IndexMask = NULL;
2394 ctx->Driver.LightModelfv = radeonLightModelfv;
2395 ctx->Driver.Lightfv = radeonLightfv;
2396 ctx->Driver.LineStipple = radeonLineStipple;
2397 ctx->Driver.LineWidth = radeonLineWidth;
2398 ctx->Driver.LogicOpcode = radeonLogicOpCode;
2399 ctx->Driver.PolygonMode = radeonPolygonMode;
2400 ctx->Driver.PolygonOffset = radeonPolygonOffset;
2401 ctx->Driver.PolygonStipple = radeonPolygonStipple;
2402 ctx->Driver.RenderMode = radeonRenderMode;
2403 ctx->Driver.Scissor = radeonScissor;
2404 ctx->Driver.ShadeModel = radeonShadeModel;
2405 ctx->Driver.StencilFuncSeparate = radeonStencilFuncSeparate;
2406 ctx->Driver.StencilMaskSeparate = radeonStencilMaskSeparate;
2407 ctx->Driver.StencilOpSeparate = radeonStencilOpSeparate;
2408 ctx->Driver.Viewport = radeonViewport;
2409
2410 TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange = radeonUpdateMaterial;
2411 TNL_CONTEXT(ctx)->Driver.RunPipeline = radeonWrapRunPipeline;
2412 }