Merge branch 'mesa_7_7_branch'
[mesa.git] / src / mesa / drivers / dri / mga / mgastate.c
1 /*
2 * Copyright 2000-2001 VA Linux Systems, Inc.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * on the rights to use, copy, modify, merge, publish, distribute, sub
9 * license, and/or sell copies of the Software, and to permit persons to whom
10 * the Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 * Keith Whitwell <keith@tungstengraphics.com>
26 */
27
28
29 #include "main/mtypes.h"
30 #include "main/colormac.h"
31 #include "main/dd.h"
32 #include "main/mm.h"
33
34 #include "mgacontext.h"
35 #include "mgadd.h"
36 #include "mgastate.h"
37 #include "mgatex.h"
38 #include "mgavb.h"
39 #include "mgatris.h"
40 #include "mgaioctl.h"
41 #include "mgaregs.h"
42
43 #include "swrast/swrast.h"
44 #include "vbo/vbo.h"
45 #include "tnl/tnl.h"
46 #include "tnl/t_context.h"
47 #include "tnl/t_pipeline.h"
48 #include "swrast_setup/swrast_setup.h"
49
50 #include "xmlpool.h"
51 #include "drirenderbuffer.h"
52
53
54 static void updateSpecularLighting( GLcontext *ctx );
55
56 static const GLuint mgarop_NoBLK[16] = {
57 DC_atype_rpl | 0x00000000, DC_atype_rstr | 0x00080000,
58 DC_atype_rstr | 0x00040000, DC_atype_rpl | 0x000c0000,
59 DC_atype_rstr | 0x00020000, DC_atype_rstr | 0x000a0000,
60 DC_atype_rstr | 0x00060000, DC_atype_rstr | 0x000e0000,
61 DC_atype_rstr | 0x00010000, DC_atype_rstr | 0x00090000,
62 DC_atype_rstr | 0x00050000, DC_atype_rstr | 0x000d0000,
63 DC_atype_rpl | 0x00030000, DC_atype_rstr | 0x000b0000,
64 DC_atype_rstr | 0x00070000, DC_atype_rpl | 0x000f0000
65 };
66
67 /* =============================================================
68 * Alpha blending
69 */
70
71 static void mgaDDAlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref)
72 {
73 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
74 GLubyte refByte;
75 GLuint a;
76
77 CLAMPED_FLOAT_TO_UBYTE(refByte, ref);
78
79 switch ( func ) {
80 case GL_NEVER:
81 a = AC_atmode_alt;
82 refByte = 0;
83 break;
84 case GL_LESS:
85 a = AC_atmode_alt;
86 break;
87 case GL_GEQUAL:
88 a = AC_atmode_agte;
89 break;
90 case GL_LEQUAL:
91 a = AC_atmode_alte;
92 break;
93 case GL_GREATER:
94 a = AC_atmode_agt;
95 break;
96 case GL_NOTEQUAL:
97 a = AC_atmode_ane;
98 break;
99 case GL_EQUAL:
100 a = AC_atmode_ae;
101 break;
102 case GL_ALWAYS:
103 a = AC_atmode_noacmp;
104 break;
105 default:
106 a = 0;
107 break;
108 }
109
110 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
111 mmesa->hw.alpha_func = a | MGA_FIELD( AC_atref, refByte );
112 }
113
114 static void updateBlendLogicOp(GLcontext *ctx)
115 {
116 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
117 GLboolean logicOp = RGBA_LOGICOP_ENABLED(ctx);
118
119 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
120
121 mmesa->hw.blend_func_enable =
122 (ctx->Color.BlendEnabled && !logicOp) ? ~0 : 0;
123
124 FALLBACK( ctx, MGA_FALLBACK_BLEND,
125 ctx->Color.BlendEnabled && !logicOp &&
126 mmesa->hw.blend_func == (AC_src_src_alpha_sat | AC_dst_zero) );
127 }
128
129 static void mgaDDBlendEquationSeparate(GLcontext *ctx,
130 GLenum modeRGB, GLenum modeA)
131 {
132 assert( modeRGB == modeA );
133 updateBlendLogicOp( ctx );
134 }
135
136 static void mgaDDBlendFuncSeparate( GLcontext *ctx, GLenum sfactorRGB,
137 GLenum dfactorRGB, GLenum sfactorA,
138 GLenum dfactorA )
139 {
140 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
141 GLuint src;
142 GLuint dst;
143
144 switch (ctx->Color.BlendSrcRGB) {
145 case GL_ZERO:
146 src = AC_src_zero; break;
147 case GL_SRC_ALPHA:
148 src = AC_src_src_alpha; break;
149 case GL_ONE:
150 default: /* never happens */
151 src = AC_src_one; break;
152 case GL_DST_COLOR:
153 src = AC_src_dst_color; break;
154 case GL_ONE_MINUS_DST_COLOR:
155 src = AC_src_om_dst_color; break;
156 case GL_ONE_MINUS_SRC_ALPHA:
157 src = AC_src_om_src_alpha; break;
158 case GL_DST_ALPHA:
159 src = (ctx->Visual.alphaBits > 0)
160 ? AC_src_dst_alpha : AC_src_one;
161 break;
162 case GL_ONE_MINUS_DST_ALPHA:
163 src = (ctx->Visual.alphaBits > 0)
164 ? AC_src_om_dst_alpha : AC_src_zero;
165 break;
166 case GL_SRC_ALPHA_SATURATE:
167 src = (ctx->Visual.alphaBits > 0)
168 ? AC_src_src_alpha_sat : AC_src_zero;
169 break;
170 }
171
172 switch (ctx->Color.BlendDstRGB) {
173 case GL_SRC_ALPHA:
174 dst = AC_dst_src_alpha; break;
175 case GL_ONE_MINUS_SRC_ALPHA:
176 dst = AC_dst_om_src_alpha; break;
177 default: /* never happens */
178 case GL_ZERO:
179 dst = AC_dst_zero; break;
180 case GL_ONE:
181 dst = AC_dst_one; break;
182 case GL_SRC_COLOR:
183 dst = AC_dst_src_color; break;
184 case GL_ONE_MINUS_SRC_COLOR:
185 dst = AC_dst_om_src_color; break;
186 case GL_DST_ALPHA:
187 dst = (ctx->Visual.alphaBits > 0)
188 ? AC_dst_dst_alpha : AC_dst_one;
189 break;
190 case GL_ONE_MINUS_DST_ALPHA:
191 dst = (ctx->Visual.alphaBits > 0)
192 ? AC_dst_om_dst_alpha : AC_dst_zero;
193 break;
194 }
195
196 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
197 mmesa->hw.blend_func = (src | dst);
198
199 FALLBACK( ctx, MGA_FALLBACK_BLEND,
200 ctx->Color.BlendEnabled && !RGBA_LOGICOP_ENABLED(ctx) &&
201 mmesa->hw.blend_func == (AC_src_src_alpha_sat | AC_dst_zero) );
202 }
203
204 /* =============================================================
205 * Depth testing
206 */
207
208 static void mgaDDDepthFunc(GLcontext *ctx, GLenum func)
209 {
210 mgaContextPtr mmesa = MGA_CONTEXT( ctx );
211 int zmode;
212
213 switch (func) {
214 case GL_NEVER:
215 /* can't do this in h/w, we'll use a s/w fallback */
216 FALLBACK (ctx, MGA_FALLBACK_DEPTH, ctx->Depth.Test);
217
218 /* FALLTHROUGH */
219 case GL_ALWAYS:
220 zmode = DC_zmode_nozcmp; break;
221 case GL_LESS:
222 zmode = DC_zmode_zlt; break;
223 case GL_LEQUAL:
224 zmode = DC_zmode_zlte; break;
225 case GL_EQUAL:
226 zmode = DC_zmode_ze; break;
227 case GL_GREATER:
228 zmode = DC_zmode_zgt; break;
229 case GL_GEQUAL:
230 zmode = DC_zmode_zgte; break;
231 case GL_NOTEQUAL:
232 zmode = DC_zmode_zne; break;
233 default:
234 zmode = 0; break;
235 }
236
237 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
238 mmesa->hw.zmode &= DC_zmode_MASK;
239 mmesa->hw.zmode |= zmode;
240 }
241
242 static void mgaDDDepthMask(GLcontext *ctx, GLboolean flag)
243 {
244 mgaContextPtr mmesa = MGA_CONTEXT( ctx );
245
246
247 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
248 mmesa->hw.zmode &= DC_atype_MASK;
249 mmesa->hw.zmode |= (flag) ? DC_atype_zi : DC_atype_i;
250 }
251
252
253 static void mgaDDClearDepth(GLcontext *ctx, GLclampd d)
254 {
255 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
256
257 /* Select the Z depth. The ~ is used because the _MASK values in the
258 * MGA driver are used to mask OFF the selected bits. In this case,
259 * we want to mask off everything except the MA_zwidth bits.
260 */
261 switch (mmesa->setup.maccess & ~MA_zwidth_MASK) {
262 case MA_zwidth_16: mmesa->ClearDepth = d * 0x0000ffff; break;
263 case MA_zwidth_24: mmesa->ClearDepth = d * 0xffffff00; break;
264 case MA_zwidth_32: mmesa->ClearDepth = d * 0xffffffff; break;
265 default: return;
266 }
267 }
268
269
270 /* =============================================================
271 * Fog
272 */
273
274
275 static void mgaDDFogfv(GLcontext *ctx, GLenum pname, const GLfloat *param)
276 {
277 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
278
279 if (pname == GL_FOG_COLOR) {
280 GLuint color = PACK_COLOR_888((GLubyte)(ctx->Fog.Color[0]*255.0F),
281 (GLubyte)(ctx->Fog.Color[1]*255.0F),
282 (GLubyte)(ctx->Fog.Color[2]*255.0F));
283
284 MGA_STATECHANGE(mmesa, MGA_UPLOAD_CONTEXT);
285 mmesa->setup.fogcolor = color;
286 }
287 }
288
289
290 /* =============================================================
291 * Scissoring
292 */
293
294
295 void mgaUpdateClipping(const GLcontext *ctx)
296 {
297 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
298
299 if (mmesa->driDrawable)
300 {
301 int x1 = mmesa->driDrawable->x + ctx->Scissor.X;
302 int y1 = mmesa->driDrawable->y + mmesa->driDrawable->h
303 - (ctx->Scissor.Y + ctx->Scissor.Height);
304 int x2 = x1 + ctx->Scissor.Width;
305 int y2 = y1 + ctx->Scissor.Height;
306
307 if (x1 < 0) x1 = 0;
308 if (y1 < 0) y1 = 0;
309 if (x2 < 0) x2 = 0;
310 if (y2 < 0) y2 = 0;
311
312 mmesa->scissor_rect.x1 = x1;
313 mmesa->scissor_rect.y1 = y1;
314 mmesa->scissor_rect.x2 = x2;
315 mmesa->scissor_rect.y2 = y2;
316
317 mmesa->dirty |= MGA_UPLOAD_CLIPRECTS;
318 }
319 }
320
321
322 static void mgaDDScissor( GLcontext *ctx, GLint x, GLint y,
323 GLsizei w, GLsizei h )
324 {
325 if ( ctx->Scissor.Enabled ) {
326 FLUSH_BATCH( MGA_CONTEXT(ctx) ); /* don't pipeline cliprect changes */
327 mgaUpdateClipping( ctx );
328 }
329 }
330
331
332 /* =============================================================
333 * Culling
334 */
335
336
337 #define _CULL_DISABLE 0
338 #define _CULL_NEGATIVE ((1<<11)|(1<<5)|(1<<16))
339 #define _CULL_POSITIVE (1<<11)
340
341 static void mgaDDCullFaceFrontFace(GLcontext *ctx, GLenum unused)
342 {
343 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
344
345 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
346 if (ctx->Polygon.CullFlag &&
347 ctx->Polygon.CullFaceMode != GL_FRONT_AND_BACK)
348 {
349 mmesa->hw.cull = _CULL_NEGATIVE;
350
351 if (ctx->Polygon.CullFaceMode == GL_FRONT)
352 mmesa->hw.cull ^= (_CULL_POSITIVE ^ _CULL_NEGATIVE);
353
354 if (ctx->Polygon.FrontFace != GL_CCW)
355 mmesa->hw.cull ^= (_CULL_POSITIVE ^ _CULL_NEGATIVE);
356
357 mmesa->hw.cull_dualtex = mmesa->hw.cull ^
358 (_CULL_POSITIVE ^ _CULL_NEGATIVE); /* warp bug? */
359 }
360 else {
361 mmesa->hw.cull = _CULL_DISABLE;
362 mmesa->hw.cull_dualtex = _CULL_DISABLE;
363 }
364 }
365
366
367 /* =============================================================
368 * Masks
369 */
370
371 static void mgaDDColorMask(GLcontext *ctx,
372 GLboolean r, GLboolean g,
373 GLboolean b, GLboolean a )
374 {
375 mgaContextPtr mmesa = MGA_CONTEXT( ctx );
376 mgaScreenPrivate *mgaScreen = mmesa->mgaScreen;
377 GLuint mask = mgaPackColor(mgaScreen->cpp,
378 ctx->Color.ColorMask[0][RCOMP],
379 ctx->Color.ColorMask[0][GCOMP],
380 ctx->Color.ColorMask[0][BCOMP],
381 ctx->Color.ColorMask[0][ACOMP]);
382
383 if (mgaScreen->cpp == 2)
384 mask = mask | (mask << 16);
385
386 if (mmesa->setup.plnwt != mask) {
387 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
388 mmesa->setup.plnwt = mask;
389 }
390 }
391
392
393 /* =============================================================
394 * Polygon state
395 */
396
397 static int mgaStipples[16] = {
398 0xffff,
399 0xa5a5,
400 0x5a5a,
401 0xa0a0,
402 0x5050,
403 0x0a0a,
404 0x0505,
405 0x8020,
406 0x0401,
407 0x1040,
408 0x0208,
409 0x0802,
410 0x4010,
411 0x0104,
412 0x2080,
413 0x0000
414 };
415
416 /**
417 * The MGA supports a subset of possible 4x4 stipples natively, GL
418 * wants 32x32. Fortunately stipple is usually a repeating pattern.
419 *
420 * \param ctx GL rendering context to be affected
421 * \param mask Pointer to the 32x32 stipple mask
422 */
423
424 static void mgaDDPolygonStipple( GLcontext *ctx, const GLubyte *mask )
425 {
426 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
427 const GLubyte *m = mask;
428 GLubyte p[4];
429 int i,j,k;
430 int active = (ctx->Polygon.StippleFlag &&
431 mmesa->raster_primitive == GL_TRIANGLES);
432 GLuint stipple;
433
434 FLUSH_BATCH(mmesa);
435 mmesa->haveHwStipple = 0;
436
437 if (active) {
438 mmesa->dirty |= MGA_UPLOAD_CONTEXT;
439 mmesa->setup.dwgctl &= ~(0xf<<20);
440 }
441
442 p[0] = mask[0] & 0xf; p[0] |= p[0] << 4;
443 p[1] = mask[4] & 0xf; p[1] |= p[1] << 4;
444 p[2] = mask[8] & 0xf; p[2] |= p[2] << 4;
445 p[3] = mask[12] & 0xf; p[3] |= p[3] << 4;
446
447 for (k = 0 ; k < 8 ; k++)
448 for (j = 0 ; j < 4; j++)
449 for (i = 0 ; i < 4 ; i++)
450 if (*m++ != p[j]) {
451 return;
452 }
453
454 stipple = ( ((p[0] & 0xf) << 0) |
455 ((p[1] & 0xf) << 4) |
456 ((p[2] & 0xf) << 8) |
457 ((p[3] & 0xf) << 12) );
458
459 for (i = 0 ; i < 16 ; i++)
460 if (mgaStipples[i] == stipple) {
461 mmesa->poly_stipple = i<<20;
462 mmesa->haveHwStipple = 1;
463 break;
464 }
465
466 if (active) {
467 mmesa->setup.dwgctl &= ~(0xf<<20);
468 mmesa->setup.dwgctl |= mmesa->poly_stipple;
469 }
470 }
471
472
473 /* =============================================================
474 * Rendering attributes
475 *
476 * We really don't want to recalculate all this every time we bind a
477 * texture. These things shouldn't change all that often, so it makes
478 * sense to break them out of the core texture state update routines.
479 */
480
481 static void updateSpecularLighting( GLcontext *ctx )
482 {
483 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
484 unsigned int specen;
485
486 specen = NEED_SECONDARY_COLOR(ctx) ? TMC_specen_enable : 0;
487
488 if ( specen != mmesa->hw.specen ) {
489 mmesa->hw.specen = specen;
490 mmesa->dirty |= MGA_UPLOAD_TEX0 | MGA_UPLOAD_TEX1;
491 }
492 }
493
494
495 /* =============================================================
496 * Materials
497 */
498
499
500 static void mgaDDLightModelfv(GLcontext *ctx, GLenum pname,
501 const GLfloat *param)
502 {
503 if (pname == GL_LIGHT_MODEL_COLOR_CONTROL) {
504 FLUSH_BATCH( MGA_CONTEXT(ctx) );
505 updateSpecularLighting( ctx );
506 }
507 }
508
509
510 /* =============================================================
511 * Stencil
512 */
513
514
515 static void
516 mgaDDStencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func, GLint ref,
517 GLuint mask)
518 {
519 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
520 GLuint stencil;
521 GLuint stencilctl;
522
523 stencil = MGA_FIELD( S_sref, ref ) | MGA_FIELD( S_smsk, mask );
524 switch (func)
525 {
526 case GL_NEVER:
527 stencilctl = SC_smode_snever;
528 break;
529 case GL_LESS:
530 stencilctl = SC_smode_slt;
531 break;
532 case GL_LEQUAL:
533 stencilctl = SC_smode_slte;
534 break;
535 case GL_GREATER:
536 stencilctl = SC_smode_sgt;
537 break;
538 case GL_GEQUAL:
539 stencilctl = SC_smode_sgte;
540 break;
541 case GL_NOTEQUAL:
542 stencilctl = SC_smode_sne;
543 break;
544 case GL_EQUAL:
545 stencilctl = SC_smode_se;
546 break;
547 case GL_ALWAYS:
548 default:
549 stencilctl = SC_smode_salways;
550 break;
551 }
552
553 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
554 mmesa->hw.stencil &= (S_sref_MASK & S_smsk_MASK);
555 mmesa->hw.stencil |= stencil;
556 mmesa->hw.stencilctl &= SC_smode_MASK;
557 mmesa->hw.stencilctl |= stencilctl;
558 }
559
560 static void
561 mgaDDStencilMaskSeparate(GLcontext *ctx, GLenum face, GLuint mask)
562 {
563 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
564
565 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
566 mmesa->hw.stencil &= S_swtmsk_MASK;
567 mmesa->hw.stencil |= MGA_FIELD( S_swtmsk, mask );
568 }
569
570 static void
571 mgaDDStencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail, GLenum zfail,
572 GLenum zpass)
573 {
574 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
575 GLuint stencilctl;
576
577 stencilctl = 0;
578 switch (ctx->Stencil.FailFunc[0])
579 {
580 case GL_KEEP:
581 stencilctl |= SC_sfailop_keep;
582 break;
583 case GL_ZERO:
584 stencilctl |= SC_sfailop_zero;
585 break;
586 case GL_REPLACE:
587 stencilctl |= SC_sfailop_replace;
588 break;
589 case GL_INCR:
590 stencilctl |= SC_sfailop_incrsat;
591 break;
592 case GL_DECR:
593 stencilctl |= SC_sfailop_decrsat;
594 break;
595 case GL_INCR_WRAP:
596 stencilctl |= SC_sfailop_incr;
597 break;
598 case GL_DECR_WRAP:
599 stencilctl |= SC_sfailop_decr;
600 break;
601 case GL_INVERT:
602 stencilctl |= SC_sfailop_invert;
603 break;
604 default:
605 break;
606 }
607
608 switch (ctx->Stencil.ZFailFunc[0])
609 {
610 case GL_KEEP:
611 stencilctl |= SC_szfailop_keep;
612 break;
613 case GL_ZERO:
614 stencilctl |= SC_szfailop_zero;
615 break;
616 case GL_REPLACE:
617 stencilctl |= SC_szfailop_replace;
618 break;
619 case GL_INCR:
620 stencilctl |= SC_szfailop_incrsat;
621 break;
622 case GL_DECR:
623 stencilctl |= SC_szfailop_decrsat;
624 break;
625 case GL_INCR_WRAP:
626 stencilctl |= SC_szfailop_incr;
627 break;
628 case GL_DECR_WRAP:
629 stencilctl |= SC_szfailop_decr;
630 break;
631 case GL_INVERT:
632 stencilctl |= SC_szfailop_invert;
633 break;
634 default:
635 break;
636 }
637
638 switch (ctx->Stencil.ZPassFunc[0])
639 {
640 case GL_KEEP:
641 stencilctl |= SC_szpassop_keep;
642 break;
643 case GL_ZERO:
644 stencilctl |= SC_szpassop_zero;
645 break;
646 case GL_REPLACE:
647 stencilctl |= SC_szpassop_replace;
648 break;
649 case GL_INCR:
650 stencilctl |= SC_szpassop_incrsat;
651 break;
652 case GL_DECR:
653 stencilctl |= SC_szpassop_decrsat;
654 break;
655 case GL_INCR_WRAP:
656 stencilctl |= SC_szpassop_incr;
657 break;
658 case GL_DECR_WRAP:
659 stencilctl |= SC_szpassop_decr;
660 break;
661 case GL_INVERT:
662 stencilctl |= SC_szpassop_invert;
663 break;
664 default:
665 break;
666 }
667
668 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
669 mmesa->hw.stencilctl &= (SC_sfailop_MASK & SC_szfailop_MASK
670 & SC_szpassop_MASK);
671 mmesa->hw.stencilctl |= stencilctl;
672 }
673
674
675 /* =============================================================
676 * Window position and viewport transformation
677 */
678
679 void mgaCalcViewport( GLcontext *ctx )
680 {
681 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
682 const GLfloat *v = ctx->Viewport._WindowMap.m;
683 GLfloat *m = mmesa->hw_viewport;
684
685 /* See also mga_translate_vertex.
686 */
687 m[MAT_SX] = v[MAT_SX];
688 m[MAT_TX] = v[MAT_TX] + mmesa->drawX + SUBPIXEL_X;
689 m[MAT_SY] = - v[MAT_SY];
690 m[MAT_TY] = - v[MAT_TY] + mmesa->driDrawable->h + mmesa->drawY + SUBPIXEL_Y;
691 m[MAT_SZ] = v[MAT_SZ] * mmesa->depth_scale;
692 m[MAT_TZ] = v[MAT_TZ] * mmesa->depth_scale;
693
694 mmesa->SetupNewInputs = ~0;
695 }
696
697 static void mgaViewport( GLcontext *ctx,
698 GLint x, GLint y,
699 GLsizei width, GLsizei height )
700 {
701 mgaCalcViewport( ctx );
702 }
703
704 static void mgaDepthRange( GLcontext *ctx,
705 GLclampd nearval, GLclampd farval )
706 {
707 mgaCalcViewport( ctx );
708 }
709
710
711 /* =============================================================
712 * Miscellaneous
713 */
714
715 static void mgaDDClearColor(GLcontext *ctx,
716 const GLfloat color[4] )
717 {
718 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
719 GLubyte c[4];
720 CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]);
721 CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]);
722 CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]);
723 CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]);
724
725 mmesa->ClearColor = mgaPackColor( mmesa->mgaScreen->cpp,
726 c[0], c[1], c[2], c[3]);
727 }
728
729
730 /* Fallback to swrast for select and feedback.
731 */
732 static void mgaRenderMode( GLcontext *ctx, GLenum mode )
733 {
734 FALLBACK( ctx, MGA_FALLBACK_RENDERMODE, (mode != GL_RENDER) );
735 }
736
737
738 static void mgaDDLogicOp( GLcontext *ctx, GLenum opcode )
739 {
740 mgaContextPtr mmesa = MGA_CONTEXT( ctx );
741
742 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
743 mmesa->hw.rop = mgarop_NoBLK[ opcode & 0x0f ];
744 }
745
746
747 static void mga_set_cliprects(mgaContextPtr mmesa)
748 {
749 __DRIdrawable *driDrawable = mmesa->driDrawable;
750
751 if ((mmesa->draw_buffer != MGA_FRONT)
752 || (driDrawable->numBackClipRects == 0)) {
753 if (driDrawable->numClipRects == 0) {
754 static drm_clip_rect_t zeroareacliprect = {0,0,0,0};
755 mmesa->numClipRects = 1;
756 mmesa->pClipRects = &zeroareacliprect;
757 } else {
758 mmesa->numClipRects = driDrawable->numClipRects;
759 mmesa->pClipRects = driDrawable->pClipRects;
760 }
761 mmesa->drawX = driDrawable->x;
762 mmesa->drawY = driDrawable->y;
763 } else {
764 mmesa->numClipRects = driDrawable->numBackClipRects;
765 mmesa->pClipRects = driDrawable->pBackClipRects;
766 mmesa->drawX = driDrawable->backX;
767 mmesa->drawY = driDrawable->backY;
768 }
769
770 mmesa->setup.dstorg = mmesa->drawOffset;
771 mmesa->dirty |= MGA_UPLOAD_CONTEXT | MGA_UPLOAD_CLIPRECTS;
772 }
773
774
775 void mgaUpdateRects( mgaContextPtr mmesa, GLuint buffers )
776 {
777 __DRIdrawable *const driDrawable = mmesa->driDrawable;
778 __DRIdrawable *const driReadable = mmesa->driReadable;
779
780 mmesa->dirty_cliprects = 0;
781
782 driUpdateFramebufferSize(mmesa->glCtx, driDrawable);
783 if (driDrawable != driReadable) {
784 driUpdateFramebufferSize(mmesa->glCtx, driReadable);
785 }
786
787 mga_set_cliprects(mmesa);
788
789 mgaUpdateClipping( mmesa->glCtx );
790 mgaCalcViewport( mmesa->glCtx );
791 }
792
793
794 static void mgaDDDrawBuffer(GLcontext *ctx, GLenum mode )
795 {
796 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
797
798 FLUSH_BATCH( mmesa );
799
800 if (ctx->DrawBuffer->_NumColorDrawBuffers != 1) {
801 /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */
802 FALLBACK( ctx, MGA_FALLBACK_DRAW_BUFFER, GL_TRUE );
803 return;
804 }
805
806 switch ( ctx->DrawBuffer->_ColorDrawBufferIndexes[0] ) {
807 case BUFFER_FRONT_LEFT:
808 mmesa->setup.dstorg = mmesa->mgaScreen->frontOffset;
809 mmesa->draw_buffer = MGA_FRONT;
810 break;
811 case BUFFER_BACK_LEFT:
812 mmesa->setup.dstorg = mmesa->mgaScreen->backOffset;
813 mmesa->draw_buffer = MGA_BACK;
814 break;
815 default:
816 FALLBACK( ctx, MGA_FALLBACK_DRAW_BUFFER, GL_TRUE );
817 return;
818 }
819
820 mmesa->dirty |= MGA_UPLOAD_CONTEXT;
821 mga_set_cliprects(mmesa);
822 FALLBACK(ctx, MGA_FALLBACK_DRAW_BUFFER, GL_FALSE);
823 }
824
825
826 static void mgaDDReadBuffer(GLcontext *ctx, GLenum mode )
827 {
828 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
829 }
830
831
832 /* =============================================================
833 * State enable/disable
834 */
835
836
837 static void mgaDDEnable(GLcontext *ctx, GLenum cap, GLboolean state)
838 {
839 mgaContextPtr mmesa = MGA_CONTEXT( ctx );
840
841 switch(cap) {
842 case GL_DITHER:
843 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
844 if (!ctx->Color.DitherFlag)
845 mmesa->setup.maccess |= MA_nodither_enable;
846 else
847 mmesa->setup.maccess &= ~MA_nodither_enable;
848 break;
849 case GL_LIGHTING:
850 case GL_COLOR_SUM_EXT:
851 FLUSH_BATCH( mmesa );
852 updateSpecularLighting( ctx );
853 break;
854 case GL_ALPHA_TEST:
855 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
856 mmesa->hw.alpha_func_enable = (state) ? ~0 : 0;
857 break;
858 case GL_DEPTH_TEST:
859 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
860 FALLBACK (ctx, MGA_FALLBACK_DEPTH,
861 ctx->Depth.Func == GL_NEVER && ctx->Depth.Test);
862 break;
863
864 case GL_SCISSOR_TEST:
865 FLUSH_BATCH( mmesa );
866 mmesa->scissor = state;
867 mgaUpdateClipping( ctx );
868 break;
869
870 case GL_FOG:
871 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
872 if (ctx->Fog.Enabled)
873 mmesa->setup.maccess |= MA_fogen_enable;
874 else
875 mmesa->setup.maccess &= ~MA_fogen_enable;
876 break;
877 case GL_CULL_FACE:
878 mgaDDCullFaceFrontFace( ctx, 0 );
879 break;
880 case GL_TEXTURE_1D:
881 case GL_TEXTURE_2D:
882 case GL_TEXTURE_3D:
883 break;
884 case GL_POLYGON_STIPPLE:
885 if (mmesa->haveHwStipple && mmesa->raster_primitive == GL_TRIANGLES) {
886 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
887 mmesa->setup.dwgctl &= ~(0xf<<20);
888 if (state)
889 mmesa->setup.dwgctl |= mmesa->poly_stipple;
890 }
891 break;
892
893 case GL_BLEND:
894 case GL_COLOR_LOGIC_OP:
895 updateBlendLogicOp( ctx );
896 break;
897
898 case GL_STENCIL_TEST:
899 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
900 if (mmesa->hw_stencil) {
901 mmesa->hw.stencil_enable = ( state ) ? ~0 : 0;
902 }
903 else {
904 FALLBACK( ctx, MGA_FALLBACK_STENCIL, state );
905 }
906 default:
907 break;
908 }
909 }
910
911
912 /* =============================================================
913 */
914
915 static void mgaDDPrintDirty( const char *msg, GLuint state )
916 {
917 fprintf(stderr, "%s (0x%03x): %s%s%s%s%s%s%s\n",
918 msg,
919 (unsigned int) state,
920 (state & MGA_WAIT_AGE) ? "wait-age " : "",
921 (state & MGA_UPLOAD_TEX0IMAGE) ? "upload-tex0-img " : "",
922 (state & MGA_UPLOAD_TEX1IMAGE) ? "upload-tex1-img " : "",
923 (state & MGA_UPLOAD_CONTEXT) ? "upload-ctx " : "",
924 (state & MGA_UPLOAD_TEX0) ? "upload-tex0 " : "",
925 (state & MGA_UPLOAD_TEX1) ? "upload-tex1 " : "",
926 (state & MGA_UPLOAD_PIPE) ? "upload-pipe " : ""
927 );
928 }
929
930 /* Push the state into the sarea and/or texture memory.
931 */
932 void mgaEmitHwStateLocked( mgaContextPtr mmesa )
933 {
934 drm_mga_sarea_t *sarea = mmesa->sarea;
935 GLcontext * ctx = mmesa->glCtx;
936
937 if (MGA_DEBUG & DEBUG_VERBOSE_MSG)
938 mgaDDPrintDirty( __FUNCTION__, mmesa->dirty );
939
940 if (mmesa->dirty & MGA_UPLOAD_CONTEXT) {
941 mmesa->setup.wflag = _CULL_DISABLE;
942 if (mmesa->raster_primitive == GL_TRIANGLES) {
943 if ((ctx->Texture.Unit[0]._ReallyEnabled == TEXTURE_2D_BIT &&
944 ctx->Texture.Unit[1]._ReallyEnabled == TEXTURE_2D_BIT)) {
945 mmesa->setup.wflag = mmesa->hw.cull_dualtex;
946 }
947 else {
948 mmesa->setup.wflag = mmesa->hw.cull;
949 }
950 }
951
952 mmesa->setup.stencil = mmesa->hw.stencil
953 & mmesa->hw.stencil_enable;
954 mmesa->setup.stencilctl = mmesa->hw.stencilctl
955 & mmesa->hw.stencil_enable;
956
957 /* If depth testing is not enabled, then use the no Z-compare / no
958 * Z-write mode. Otherwise, use whatever is set in hw.zmode.
959 */
960 mmesa->setup.dwgctl &= (DC_zmode_MASK & DC_atype_MASK);
961 mmesa->setup.dwgctl |= (ctx->Depth.Test)
962 ? mmesa->hw.zmode : (DC_zmode_nozcmp | DC_atype_i);
963
964 mmesa->setup.dwgctl &= DC_bop_MASK;
965 mmesa->setup.dwgctl |= RGBA_LOGICOP_ENABLED(ctx)
966 ? mmesa->hw.rop : mgarop_NoBLK[ GL_COPY & 0x0f ];
967
968 mmesa->setup.alphactrl &= AC_src_MASK & AC_dst_MASK & AC_atmode_MASK
969 & AC_atref_MASK & AC_alphasel_MASK;
970 mmesa->setup.alphactrl |=
971 (mmesa->hw.alpha_func & mmesa->hw.alpha_func_enable) |
972 (mmesa->hw.blend_func & mmesa->hw.blend_func_enable) |
973 ((AC_src_one | AC_dst_zero) & ~mmesa->hw.blend_func_enable) |
974 mmesa->hw.alpha_sel;
975
976 memcpy( &sarea->context_state, &mmesa->setup, sizeof(mmesa->setup));
977 }
978
979 if ((mmesa->dirty & MGA_UPLOAD_TEX0) && mmesa->CurrentTexObj[0]) {
980 memcpy(&sarea->tex_state[0],
981 &mmesa->CurrentTexObj[0]->setup,
982 sizeof(sarea->tex_state[0]));
983 }
984
985 if ((mmesa->dirty & MGA_UPLOAD_TEX1) && mmesa->CurrentTexObj[1]) {
986 memcpy(&sarea->tex_state[1],
987 &mmesa->CurrentTexObj[1]->setup,
988 sizeof(sarea->tex_state[1]));
989 }
990
991 if (mmesa->dirty & (MGA_UPLOAD_TEX0 | MGA_UPLOAD_TEX1)) {
992 sarea->tex_state[0].texctl2 &= ~TMC_specen_enable;
993 sarea->tex_state[1].texctl2 &= ~TMC_specen_enable;
994 sarea->tex_state[0].texctl2 |= mmesa->hw.specen;
995 sarea->tex_state[1].texctl2 |= mmesa->hw.specen;
996 }
997
998 if (mmesa->dirty & MGA_UPLOAD_PIPE) {
999 /* mmesa->sarea->wacceptseq = mmesa->hw_primitive; */
1000 mmesa->sarea->warp_pipe = mmesa->vertex_format;
1001 mmesa->sarea->vertsize = mmesa->vertex_size;
1002 }
1003
1004 mmesa->sarea->dirty |= mmesa->dirty;
1005 mmesa->dirty &= MGA_UPLOAD_CLIPRECTS;
1006 }
1007
1008 /* =============================================================
1009 */
1010
1011
1012 static void mgaDDValidateState( GLcontext *ctx )
1013 {
1014 mgaContextPtr mmesa = MGA_CONTEXT( ctx );
1015
1016 FLUSH_BATCH( mmesa );
1017
1018 if (mmesa->NewGLState & _NEW_TEXTURE) {
1019 mgaUpdateTextureState(ctx);
1020 }
1021
1022 if (!mmesa->Fallback) {
1023 if (mmesa->NewGLState & _MGA_NEW_RASTERSETUP) {
1024 mgaChooseVertexState( ctx );
1025 }
1026
1027 if (mmesa->NewGLState & _MGA_NEW_RENDERSTATE) {
1028 mgaChooseRenderState( ctx );
1029 }
1030 }
1031
1032 mmesa->NewGLState = 0;
1033 }
1034
1035
1036 static void mgaDDInvalidateState( GLcontext *ctx, GLuint new_state )
1037 {
1038 _swrast_InvalidateState( ctx, new_state );
1039 _swsetup_InvalidateState( ctx, new_state );
1040 _vbo_InvalidateState( ctx, new_state );
1041 _tnl_InvalidateState( ctx, new_state );
1042 MGA_CONTEXT(ctx)->NewGLState |= new_state;
1043 }
1044
1045
1046 static void mgaRunPipeline( GLcontext *ctx )
1047 {
1048 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
1049
1050 if (mmesa->NewGLState) {
1051 mgaDDValidateState( ctx );
1052 }
1053
1054 if (mmesa->dirty) {
1055 mgaEmitHwStateLocked( mmesa );
1056 }
1057
1058 _tnl_run_pipeline( ctx );
1059 }
1060
1061
1062 void mgaInitState( mgaContextPtr mmesa )
1063 {
1064 mgaScreenPrivate *mgaScreen = mmesa->mgaScreen;
1065 GLcontext *ctx = mmesa->glCtx;
1066
1067 if (ctx->Visual.doubleBufferMode) {
1068 /* use back buffer by default */
1069 mmesa->draw_buffer = MGA_BACK;
1070 mmesa->drawOffset = mmesa->mgaScreen->backOffset;
1071 mmesa->readOffset = mmesa->mgaScreen->backOffset;
1072 mmesa->setup.dstorg = mgaScreen->backOffset;
1073 } else {
1074 /* use front buffer by default */
1075 mmesa->draw_buffer = MGA_FRONT;
1076 mmesa->drawOffset = mmesa->mgaScreen->frontOffset;
1077 mmesa->readOffset = mmesa->mgaScreen->frontOffset;
1078 mmesa->setup.dstorg = mgaScreen->frontOffset;
1079 }
1080
1081 mmesa->setup.maccess = (MA_memreset_disable |
1082 MA_fogen_disable |
1083 MA_tlutload_disable |
1084 MA_nodither_disable |
1085 MA_dit555_disable);
1086 if (driQueryOptioni (&mmesa->optionCache, "color_reduction") !=
1087 DRI_CONF_COLOR_REDUCTION_DITHER)
1088 mmesa->setup.maccess |= MA_nodither_enable;
1089
1090 switch (mmesa->mgaScreen->cpp) {
1091 case 2:
1092 mmesa->setup.maccess |= MA_pwidth_16;
1093 break;
1094 case 4:
1095 mmesa->setup.maccess |= MA_pwidth_32;
1096 break;
1097 default:
1098 fprintf( stderr, "Error: unknown cpp %d, exiting...\n",
1099 mmesa->mgaScreen->cpp );
1100 exit( 1 );
1101 }
1102
1103 switch (mmesa->glCtx->Visual.depthBits) {
1104 case 16:
1105 mmesa->setup.maccess |= MA_zwidth_16;
1106 break;
1107 case 24:
1108 mmesa->setup.maccess |= MA_zwidth_24;
1109 break;
1110 case 32:
1111 mmesa->setup.maccess |= MA_zwidth_32;
1112 break;
1113 }
1114
1115 mmesa->hw.blend_func = AC_src_one | AC_dst_zero;
1116 mmesa->hw.blend_func_enable = 0;
1117 mmesa->hw.alpha_func = AC_atmode_noacmp | MGA_FIELD( AC_atref, 0x00 );
1118 mmesa->hw.alpha_func_enable = 0;
1119 mmesa->hw.rop = mgarop_NoBLK[ GL_COPY & 0x0f ];
1120 mmesa->hw.zmode = DC_zmode_zlt | DC_atype_zi;
1121 mmesa->hw.stencil = MGA_FIELD( S_sref, 0x00) | MGA_FIELD( S_smsk, 0xff ) |
1122 MGA_FIELD( S_swtmsk, 0xff );
1123 mmesa->hw.stencilctl = SC_smode_salways | SC_sfailop_keep
1124 | SC_szfailop_keep | SC_szpassop_keep;
1125 mmesa->hw.stencil_enable = 0;
1126 mmesa->hw.cull = _CULL_DISABLE;
1127 mmesa->hw.cull_dualtex = _CULL_DISABLE;
1128 mmesa->hw.specen = 0;
1129 mmesa->hw.alpha_sel = AC_alphasel_diffused;
1130
1131 mmesa->setup.dwgctl = (DC_opcod_trap |
1132 DC_linear_xy |
1133 DC_solid_disable |
1134 DC_arzero_disable |
1135 DC_sgnzero_disable |
1136 DC_shftzero_enable |
1137 MGA_FIELD( DC_bop, 0xC ) |
1138 MGA_FIELD( DC_trans, 0x0 ) |
1139 DC_bltmod_bmonolef |
1140 DC_pattern_disable |
1141 DC_transc_disable |
1142 DC_clipdis_disable);
1143
1144 mmesa->setup.plnwt = ~0;
1145 mmesa->setup.alphactrl = (AC_amode_alpha_channel |
1146 AC_astipple_disable |
1147 AC_aten_disable);
1148
1149 mmesa->setup.fogcolor = PACK_COLOR_888((GLubyte)(ctx->Fog.Color[0]*255.0F),
1150 (GLubyte)(ctx->Fog.Color[1]*255.0F),
1151 (GLubyte)(ctx->Fog.Color[2]*255.0F));
1152
1153 mmesa->setup.wflag = 0;
1154 mmesa->setup.tdualstage0 = 0;
1155 mmesa->setup.tdualstage1 = 0;
1156 mmesa->setup.fcol = 0;
1157 mmesa->dirty |= MGA_UPLOAD_CONTEXT;
1158
1159 mmesa->envcolor[0] = 0;
1160 mmesa->envcolor[1] = 0;
1161 }
1162
1163
1164 void mgaDDInitStateFuncs( GLcontext *ctx )
1165 {
1166 ctx->Driver.UpdateState = mgaDDInvalidateState;
1167 ctx->Driver.Enable = mgaDDEnable;
1168 ctx->Driver.LightModelfv = mgaDDLightModelfv;
1169 ctx->Driver.AlphaFunc = mgaDDAlphaFunc;
1170 ctx->Driver.BlendEquationSeparate = mgaDDBlendEquationSeparate;
1171 ctx->Driver.BlendFuncSeparate = mgaDDBlendFuncSeparate;
1172 ctx->Driver.DepthFunc = mgaDDDepthFunc;
1173 ctx->Driver.DepthMask = mgaDDDepthMask;
1174 ctx->Driver.Fogfv = mgaDDFogfv;
1175 ctx->Driver.Scissor = mgaDDScissor;
1176 ctx->Driver.CullFace = mgaDDCullFaceFrontFace;
1177 ctx->Driver.FrontFace = mgaDDCullFaceFrontFace;
1178 ctx->Driver.ColorMask = mgaDDColorMask;
1179
1180 ctx->Driver.DrawBuffer = mgaDDDrawBuffer;
1181 ctx->Driver.ReadBuffer = mgaDDReadBuffer;
1182 ctx->Driver.ClearColor = mgaDDClearColor;
1183 ctx->Driver.ClearDepth = mgaDDClearDepth;
1184 ctx->Driver.LogicOpcode = mgaDDLogicOp;
1185
1186 ctx->Driver.PolygonStipple = mgaDDPolygonStipple;
1187
1188 ctx->Driver.StencilFuncSeparate = mgaDDStencilFuncSeparate;
1189 ctx->Driver.StencilMaskSeparate = mgaDDStencilMaskSeparate;
1190 ctx->Driver.StencilOpSeparate = mgaDDStencilOpSeparate;
1191
1192 ctx->Driver.DepthRange = mgaDepthRange;
1193 ctx->Driver.Viewport = mgaViewport;
1194 ctx->Driver.RenderMode = mgaRenderMode;
1195
1196 ctx->Driver.ClearIndex = 0;
1197 ctx->Driver.IndexMask = 0;
1198
1199 TNL_CONTEXT(ctx)->Driver.RunPipeline = mgaRunPipeline;
1200 }