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