Merge commit 'origin/master' into gallium-map-range
[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
378
379 GLuint mask = mgaPackColor(mgaScreen->cpp,
380 ctx->Color.ColorMask[RCOMP],
381 ctx->Color.ColorMask[GCOMP],
382 ctx->Color.ColorMask[BCOMP],
383 ctx->Color.ColorMask[ACOMP]);
384
385 if (mgaScreen->cpp == 2)
386 mask = mask | (mask << 16);
387
388 if (mmesa->setup.plnwt != mask) {
389 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
390 mmesa->setup.plnwt = mask;
391 }
392 }
393
394
395 /* =============================================================
396 * Polygon state
397 */
398
399 static int mgaStipples[16] = {
400 0xffff,
401 0xa5a5,
402 0x5a5a,
403 0xa0a0,
404 0x5050,
405 0x0a0a,
406 0x0505,
407 0x8020,
408 0x0401,
409 0x1040,
410 0x0208,
411 0x0802,
412 0x4010,
413 0x0104,
414 0x2080,
415 0x0000
416 };
417
418 /**
419 * The MGA supports a subset of possible 4x4 stipples natively, GL
420 * wants 32x32. Fortunately stipple is usually a repeating pattern.
421 *
422 * \param ctx GL rendering context to be affected
423 * \param mask Pointer to the 32x32 stipple mask
424 */
425
426 static void mgaDDPolygonStipple( GLcontext *ctx, const GLubyte *mask )
427 {
428 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
429 const GLubyte *m = mask;
430 GLubyte p[4];
431 int i,j,k;
432 int active = (ctx->Polygon.StippleFlag &&
433 mmesa->raster_primitive == GL_TRIANGLES);
434 GLuint stipple;
435
436 FLUSH_BATCH(mmesa);
437 mmesa->haveHwStipple = 0;
438
439 if (active) {
440 mmesa->dirty |= MGA_UPLOAD_CONTEXT;
441 mmesa->setup.dwgctl &= ~(0xf<<20);
442 }
443
444 p[0] = mask[0] & 0xf; p[0] |= p[0] << 4;
445 p[1] = mask[4] & 0xf; p[1] |= p[1] << 4;
446 p[2] = mask[8] & 0xf; p[2] |= p[2] << 4;
447 p[3] = mask[12] & 0xf; p[3] |= p[3] << 4;
448
449 for (k = 0 ; k < 8 ; k++)
450 for (j = 0 ; j < 4; j++)
451 for (i = 0 ; i < 4 ; i++)
452 if (*m++ != p[j]) {
453 return;
454 }
455
456 stipple = ( ((p[0] & 0xf) << 0) |
457 ((p[1] & 0xf) << 4) |
458 ((p[2] & 0xf) << 8) |
459 ((p[3] & 0xf) << 12) );
460
461 for (i = 0 ; i < 16 ; i++)
462 if (mgaStipples[i] == stipple) {
463 mmesa->poly_stipple = i<<20;
464 mmesa->haveHwStipple = 1;
465 break;
466 }
467
468 if (active) {
469 mmesa->setup.dwgctl &= ~(0xf<<20);
470 mmesa->setup.dwgctl |= mmesa->poly_stipple;
471 }
472 }
473
474
475 /* =============================================================
476 * Rendering attributes
477 *
478 * We really don't want to recalculate all this every time we bind a
479 * texture. These things shouldn't change all that often, so it makes
480 * sense to break them out of the core texture state update routines.
481 */
482
483 static void updateSpecularLighting( GLcontext *ctx )
484 {
485 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
486 unsigned int specen;
487
488 specen = NEED_SECONDARY_COLOR(ctx) ? TMC_specen_enable : 0;
489
490 if ( specen != mmesa->hw.specen ) {
491 mmesa->hw.specen = specen;
492 mmesa->dirty |= MGA_UPLOAD_TEX0 | MGA_UPLOAD_TEX1;
493 }
494 }
495
496
497 /* =============================================================
498 * Materials
499 */
500
501
502 static void mgaDDLightModelfv(GLcontext *ctx, GLenum pname,
503 const GLfloat *param)
504 {
505 if (pname == GL_LIGHT_MODEL_COLOR_CONTROL) {
506 FLUSH_BATCH( MGA_CONTEXT(ctx) );
507 updateSpecularLighting( ctx );
508 }
509 }
510
511
512 /* =============================================================
513 * Stencil
514 */
515
516
517 static void
518 mgaDDStencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func, GLint ref,
519 GLuint mask)
520 {
521 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
522 GLuint stencil;
523 GLuint stencilctl;
524
525 stencil = MGA_FIELD( S_sref, ref ) | MGA_FIELD( S_smsk, mask );
526 switch (func)
527 {
528 case GL_NEVER:
529 stencilctl = SC_smode_snever;
530 break;
531 case GL_LESS:
532 stencilctl = SC_smode_slt;
533 break;
534 case GL_LEQUAL:
535 stencilctl = SC_smode_slte;
536 break;
537 case GL_GREATER:
538 stencilctl = SC_smode_sgt;
539 break;
540 case GL_GEQUAL:
541 stencilctl = SC_smode_sgte;
542 break;
543 case GL_NOTEQUAL:
544 stencilctl = SC_smode_sne;
545 break;
546 case GL_EQUAL:
547 stencilctl = SC_smode_se;
548 break;
549 case GL_ALWAYS:
550 default:
551 stencilctl = SC_smode_salways;
552 break;
553 }
554
555 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
556 mmesa->hw.stencil &= (S_sref_MASK & S_smsk_MASK);
557 mmesa->hw.stencil |= stencil;
558 mmesa->hw.stencilctl &= SC_smode_MASK;
559 mmesa->hw.stencilctl |= stencilctl;
560 }
561
562 static void
563 mgaDDStencilMaskSeparate(GLcontext *ctx, GLenum face, GLuint mask)
564 {
565 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
566
567 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
568 mmesa->hw.stencil &= S_swtmsk_MASK;
569 mmesa->hw.stencil |= MGA_FIELD( S_swtmsk, mask );
570 }
571
572 static void
573 mgaDDStencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail, GLenum zfail,
574 GLenum zpass)
575 {
576 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
577 GLuint stencilctl;
578
579 stencilctl = 0;
580 switch (ctx->Stencil.FailFunc[0])
581 {
582 case GL_KEEP:
583 stencilctl |= SC_sfailop_keep;
584 break;
585 case GL_ZERO:
586 stencilctl |= SC_sfailop_zero;
587 break;
588 case GL_REPLACE:
589 stencilctl |= SC_sfailop_replace;
590 break;
591 case GL_INCR:
592 stencilctl |= SC_sfailop_incrsat;
593 break;
594 case GL_DECR:
595 stencilctl |= SC_sfailop_decrsat;
596 break;
597 case GL_INCR_WRAP:
598 stencilctl |= SC_sfailop_incr;
599 break;
600 case GL_DECR_WRAP:
601 stencilctl |= SC_sfailop_decr;
602 break;
603 case GL_INVERT:
604 stencilctl |= SC_sfailop_invert;
605 break;
606 default:
607 break;
608 }
609
610 switch (ctx->Stencil.ZFailFunc[0])
611 {
612 case GL_KEEP:
613 stencilctl |= SC_szfailop_keep;
614 break;
615 case GL_ZERO:
616 stencilctl |= SC_szfailop_zero;
617 break;
618 case GL_REPLACE:
619 stencilctl |= SC_szfailop_replace;
620 break;
621 case GL_INCR:
622 stencilctl |= SC_szfailop_incrsat;
623 break;
624 case GL_DECR:
625 stencilctl |= SC_szfailop_decrsat;
626 break;
627 case GL_INCR_WRAP:
628 stencilctl |= SC_szfailop_incr;
629 break;
630 case GL_DECR_WRAP:
631 stencilctl |= SC_szfailop_decr;
632 break;
633 case GL_INVERT:
634 stencilctl |= SC_szfailop_invert;
635 break;
636 default:
637 break;
638 }
639
640 switch (ctx->Stencil.ZPassFunc[0])
641 {
642 case GL_KEEP:
643 stencilctl |= SC_szpassop_keep;
644 break;
645 case GL_ZERO:
646 stencilctl |= SC_szpassop_zero;
647 break;
648 case GL_REPLACE:
649 stencilctl |= SC_szpassop_replace;
650 break;
651 case GL_INCR:
652 stencilctl |= SC_szpassop_incrsat;
653 break;
654 case GL_DECR:
655 stencilctl |= SC_szpassop_decrsat;
656 break;
657 case GL_INCR_WRAP:
658 stencilctl |= SC_szpassop_incr;
659 break;
660 case GL_DECR_WRAP:
661 stencilctl |= SC_szpassop_decr;
662 break;
663 case GL_INVERT:
664 stencilctl |= SC_szpassop_invert;
665 break;
666 default:
667 break;
668 }
669
670 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
671 mmesa->hw.stencilctl &= (SC_sfailop_MASK & SC_szfailop_MASK
672 & SC_szpassop_MASK);
673 mmesa->hw.stencilctl |= stencilctl;
674 }
675
676
677 /* =============================================================
678 * Window position and viewport transformation
679 */
680
681 void mgaCalcViewport( GLcontext *ctx )
682 {
683 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
684 const GLfloat *v = ctx->Viewport._WindowMap.m;
685 GLfloat *m = mmesa->hw_viewport;
686
687 /* See also mga_translate_vertex.
688 */
689 m[MAT_SX] = v[MAT_SX];
690 m[MAT_TX] = v[MAT_TX] + mmesa->drawX + SUBPIXEL_X;
691 m[MAT_SY] = - v[MAT_SY];
692 m[MAT_TY] = - v[MAT_TY] + mmesa->driDrawable->h + mmesa->drawY + SUBPIXEL_Y;
693 m[MAT_SZ] = v[MAT_SZ] * mmesa->depth_scale;
694 m[MAT_TZ] = v[MAT_TZ] * mmesa->depth_scale;
695
696 mmesa->SetupNewInputs = ~0;
697 }
698
699 static void mgaViewport( GLcontext *ctx,
700 GLint x, GLint y,
701 GLsizei width, GLsizei height )
702 {
703 mgaCalcViewport( ctx );
704 }
705
706 static void mgaDepthRange( GLcontext *ctx,
707 GLclampd nearval, GLclampd farval )
708 {
709 mgaCalcViewport( ctx );
710 }
711
712
713 /* =============================================================
714 * Miscellaneous
715 */
716
717 static void mgaDDClearColor(GLcontext *ctx,
718 const GLfloat color[4] )
719 {
720 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
721 GLubyte c[4];
722 CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]);
723 CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]);
724 CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]);
725 CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]);
726
727 mmesa->ClearColor = mgaPackColor( mmesa->mgaScreen->cpp,
728 c[0], c[1], c[2], c[3]);
729 }
730
731
732 /* Fallback to swrast for select and feedback.
733 */
734 static void mgaRenderMode( GLcontext *ctx, GLenum mode )
735 {
736 FALLBACK( ctx, MGA_FALLBACK_RENDERMODE, (mode != GL_RENDER) );
737 }
738
739
740 static void mgaDDLogicOp( GLcontext *ctx, GLenum opcode )
741 {
742 mgaContextPtr mmesa = MGA_CONTEXT( ctx );
743
744 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
745 mmesa->hw.rop = mgarop_NoBLK[ opcode & 0x0f ];
746 }
747
748
749 static void mga_set_cliprects(mgaContextPtr mmesa)
750 {
751 __DRIdrawablePrivate *driDrawable = mmesa->driDrawable;
752
753 if ((mmesa->draw_buffer != MGA_FRONT)
754 || (driDrawable->numBackClipRects == 0)) {
755 if (driDrawable->numClipRects == 0) {
756 static drm_clip_rect_t zeroareacliprect = {0,0,0,0};
757 mmesa->numClipRects = 1;
758 mmesa->pClipRects = &zeroareacliprect;
759 } else {
760 mmesa->numClipRects = driDrawable->numClipRects;
761 mmesa->pClipRects = driDrawable->pClipRects;
762 }
763 mmesa->drawX = driDrawable->x;
764 mmesa->drawY = driDrawable->y;
765 } else {
766 mmesa->numClipRects = driDrawable->numBackClipRects;
767 mmesa->pClipRects = driDrawable->pBackClipRects;
768 mmesa->drawX = driDrawable->backX;
769 mmesa->drawY = driDrawable->backY;
770 }
771
772 mmesa->setup.dstorg = mmesa->drawOffset;
773 mmesa->dirty |= MGA_UPLOAD_CONTEXT | MGA_UPLOAD_CLIPRECTS;
774 }
775
776
777 void mgaUpdateRects( mgaContextPtr mmesa, GLuint buffers )
778 {
779 __DRIdrawablePrivate *const driDrawable = mmesa->driDrawable;
780 __DRIdrawablePrivate *const driReadable = mmesa->driReadable;
781
782 mmesa->dirty_cliprects = 0;
783
784 driUpdateFramebufferSize(mmesa->glCtx, driDrawable);
785 if (driDrawable != driReadable) {
786 driUpdateFramebufferSize(mmesa->glCtx, driReadable);
787 }
788
789 mga_set_cliprects(mmesa);
790
791 mgaUpdateClipping( mmesa->glCtx );
792 mgaCalcViewport( mmesa->glCtx );
793 }
794
795
796 static void mgaDDDrawBuffer(GLcontext *ctx, GLenum mode )
797 {
798 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
799
800 FLUSH_BATCH( mmesa );
801
802 if (ctx->DrawBuffer->_NumColorDrawBuffers != 1) {
803 /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */
804 FALLBACK( ctx, MGA_FALLBACK_DRAW_BUFFER, GL_TRUE );
805 return;
806 }
807
808 switch ( ctx->DrawBuffer->_ColorDrawBufferIndexes[0] ) {
809 case BUFFER_FRONT_LEFT:
810 mmesa->setup.dstorg = mmesa->mgaScreen->frontOffset;
811 mmesa->draw_buffer = MGA_FRONT;
812 break;
813 case BUFFER_BACK_LEFT:
814 mmesa->setup.dstorg = mmesa->mgaScreen->backOffset;
815 mmesa->draw_buffer = MGA_BACK;
816 break;
817 default:
818 FALLBACK( ctx, MGA_FALLBACK_DRAW_BUFFER, GL_TRUE );
819 return;
820 }
821
822 mmesa->dirty |= MGA_UPLOAD_CONTEXT;
823 mga_set_cliprects(mmesa);
824 FALLBACK(ctx, MGA_FALLBACK_DRAW_BUFFER, GL_FALSE);
825 }
826
827
828 static void mgaDDReadBuffer(GLcontext *ctx, GLenum mode )
829 {
830 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
831 }
832
833
834 /* =============================================================
835 * State enable/disable
836 */
837
838
839 static void mgaDDEnable(GLcontext *ctx, GLenum cap, GLboolean state)
840 {
841 mgaContextPtr mmesa = MGA_CONTEXT( ctx );
842
843 switch(cap) {
844 case GL_DITHER:
845 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
846 if (!ctx->Color.DitherFlag)
847 mmesa->setup.maccess |= MA_nodither_enable;
848 else
849 mmesa->setup.maccess &= ~MA_nodither_enable;
850 break;
851 case GL_LIGHTING:
852 case GL_COLOR_SUM_EXT:
853 FLUSH_BATCH( mmesa );
854 updateSpecularLighting( ctx );
855 break;
856 case GL_ALPHA_TEST:
857 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
858 mmesa->hw.alpha_func_enable = (state) ? ~0 : 0;
859 break;
860 case GL_DEPTH_TEST:
861 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
862 FALLBACK (ctx, MGA_FALLBACK_DEPTH,
863 ctx->Depth.Func == GL_NEVER && ctx->Depth.Test);
864 break;
865
866 case GL_SCISSOR_TEST:
867 FLUSH_BATCH( mmesa );
868 mmesa->scissor = state;
869 mgaUpdateClipping( ctx );
870 break;
871
872 case GL_FOG:
873 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
874 if (ctx->Fog.Enabled)
875 mmesa->setup.maccess |= MA_fogen_enable;
876 else
877 mmesa->setup.maccess &= ~MA_fogen_enable;
878 break;
879 case GL_CULL_FACE:
880 mgaDDCullFaceFrontFace( ctx, 0 );
881 break;
882 case GL_TEXTURE_1D:
883 case GL_TEXTURE_2D:
884 case GL_TEXTURE_3D:
885 break;
886 case GL_POLYGON_STIPPLE:
887 if (mmesa->haveHwStipple && mmesa->raster_primitive == GL_TRIANGLES) {
888 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
889 mmesa->setup.dwgctl &= ~(0xf<<20);
890 if (state)
891 mmesa->setup.dwgctl |= mmesa->poly_stipple;
892 }
893 break;
894
895 case GL_BLEND:
896 case GL_COLOR_LOGIC_OP:
897 updateBlendLogicOp( ctx );
898 break;
899
900 case GL_STENCIL_TEST:
901 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
902 if (mmesa->hw_stencil) {
903 mmesa->hw.stencil_enable = ( state ) ? ~0 : 0;
904 }
905 else {
906 FALLBACK( ctx, MGA_FALLBACK_STENCIL, state );
907 }
908 default:
909 break;
910 }
911 }
912
913
914 /* =============================================================
915 */
916
917 static void mgaDDPrintDirty( const char *msg, GLuint state )
918 {
919 fprintf(stderr, "%s (0x%03x): %s%s%s%s%s%s%s\n",
920 msg,
921 (unsigned int) state,
922 (state & MGA_WAIT_AGE) ? "wait-age " : "",
923 (state & MGA_UPLOAD_TEX0IMAGE) ? "upload-tex0-img " : "",
924 (state & MGA_UPLOAD_TEX1IMAGE) ? "upload-tex1-img " : "",
925 (state & MGA_UPLOAD_CONTEXT) ? "upload-ctx " : "",
926 (state & MGA_UPLOAD_TEX0) ? "upload-tex0 " : "",
927 (state & MGA_UPLOAD_TEX1) ? "upload-tex1 " : "",
928 (state & MGA_UPLOAD_PIPE) ? "upload-pipe " : ""
929 );
930 }
931
932 /* Push the state into the sarea and/or texture memory.
933 */
934 void mgaEmitHwStateLocked( mgaContextPtr mmesa )
935 {
936 drm_mga_sarea_t *sarea = mmesa->sarea;
937 GLcontext * ctx = mmesa->glCtx;
938
939 if (MGA_DEBUG & DEBUG_VERBOSE_MSG)
940 mgaDDPrintDirty( __FUNCTION__, mmesa->dirty );
941
942 if (mmesa->dirty & MGA_UPLOAD_CONTEXT) {
943 mmesa->setup.wflag = _CULL_DISABLE;
944 if (mmesa->raster_primitive == GL_TRIANGLES) {
945 if ((ctx->Texture.Unit[0]._ReallyEnabled == TEXTURE_2D_BIT &&
946 ctx->Texture.Unit[1]._ReallyEnabled == TEXTURE_2D_BIT)) {
947 mmesa->setup.wflag = mmesa->hw.cull_dualtex;
948 }
949 else {
950 mmesa->setup.wflag = mmesa->hw.cull;
951 }
952 }
953
954 mmesa->setup.stencil = mmesa->hw.stencil
955 & mmesa->hw.stencil_enable;
956 mmesa->setup.stencilctl = mmesa->hw.stencilctl
957 & mmesa->hw.stencil_enable;
958
959 /* If depth testing is not enabled, then use the no Z-compare / no
960 * Z-write mode. Otherwise, use whatever is set in hw.zmode.
961 */
962 mmesa->setup.dwgctl &= (DC_zmode_MASK & DC_atype_MASK);
963 mmesa->setup.dwgctl |= (ctx->Depth.Test)
964 ? mmesa->hw.zmode : (DC_zmode_nozcmp | DC_atype_i);
965
966 mmesa->setup.dwgctl &= DC_bop_MASK;
967 mmesa->setup.dwgctl |= RGBA_LOGICOP_ENABLED(ctx)
968 ? mmesa->hw.rop : mgarop_NoBLK[ GL_COPY & 0x0f ];
969
970 mmesa->setup.alphactrl &= AC_src_MASK & AC_dst_MASK & AC_atmode_MASK
971 & AC_atref_MASK & AC_alphasel_MASK;
972 mmesa->setup.alphactrl |=
973 (mmesa->hw.alpha_func & mmesa->hw.alpha_func_enable) |
974 (mmesa->hw.blend_func & mmesa->hw.blend_func_enable) |
975 ((AC_src_one | AC_dst_zero) & ~mmesa->hw.blend_func_enable) |
976 mmesa->hw.alpha_sel;
977
978 memcpy( &sarea->context_state, &mmesa->setup, sizeof(mmesa->setup));
979 }
980
981 if ((mmesa->dirty & MGA_UPLOAD_TEX0) && mmesa->CurrentTexObj[0]) {
982 memcpy(&sarea->tex_state[0],
983 &mmesa->CurrentTexObj[0]->setup,
984 sizeof(sarea->tex_state[0]));
985 }
986
987 if ((mmesa->dirty & MGA_UPLOAD_TEX1) && mmesa->CurrentTexObj[1]) {
988 memcpy(&sarea->tex_state[1],
989 &mmesa->CurrentTexObj[1]->setup,
990 sizeof(sarea->tex_state[1]));
991 }
992
993 if (mmesa->dirty & (MGA_UPLOAD_TEX0 | MGA_UPLOAD_TEX1)) {
994 sarea->tex_state[0].texctl2 &= ~TMC_specen_enable;
995 sarea->tex_state[1].texctl2 &= ~TMC_specen_enable;
996 sarea->tex_state[0].texctl2 |= mmesa->hw.specen;
997 sarea->tex_state[1].texctl2 |= mmesa->hw.specen;
998 }
999
1000 if (mmesa->dirty & MGA_UPLOAD_PIPE) {
1001 /* mmesa->sarea->wacceptseq = mmesa->hw_primitive; */
1002 mmesa->sarea->warp_pipe = mmesa->vertex_format;
1003 mmesa->sarea->vertsize = mmesa->vertex_size;
1004 }
1005
1006 mmesa->sarea->dirty |= mmesa->dirty;
1007 mmesa->dirty &= MGA_UPLOAD_CLIPRECTS;
1008 }
1009
1010 /* =============================================================
1011 */
1012
1013
1014 static void mgaDDValidateState( GLcontext *ctx )
1015 {
1016 mgaContextPtr mmesa = MGA_CONTEXT( ctx );
1017
1018 FLUSH_BATCH( mmesa );
1019
1020 if (mmesa->NewGLState & _NEW_TEXTURE) {
1021 mgaUpdateTextureState(ctx);
1022 }
1023
1024 if (!mmesa->Fallback) {
1025 if (mmesa->NewGLState & _MGA_NEW_RASTERSETUP) {
1026 mgaChooseVertexState( ctx );
1027 }
1028
1029 if (mmesa->NewGLState & _MGA_NEW_RENDERSTATE) {
1030 mgaChooseRenderState( ctx );
1031 }
1032 }
1033
1034 mmesa->NewGLState = 0;
1035 }
1036
1037
1038 static void mgaDDInvalidateState( GLcontext *ctx, GLuint new_state )
1039 {
1040 _swrast_InvalidateState( ctx, new_state );
1041 _swsetup_InvalidateState( ctx, new_state );
1042 _vbo_InvalidateState( ctx, new_state );
1043 _tnl_InvalidateState( ctx, new_state );
1044 MGA_CONTEXT(ctx)->NewGLState |= new_state;
1045 }
1046
1047
1048 static void mgaRunPipeline( GLcontext *ctx )
1049 {
1050 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
1051
1052 if (mmesa->NewGLState) {
1053 mgaDDValidateState( ctx );
1054 }
1055
1056 if (mmesa->dirty) {
1057 mgaEmitHwStateLocked( mmesa );
1058 }
1059
1060 _tnl_run_pipeline( ctx );
1061 }
1062
1063
1064 void mgaInitState( mgaContextPtr mmesa )
1065 {
1066 mgaScreenPrivate *mgaScreen = mmesa->mgaScreen;
1067 GLcontext *ctx = mmesa->glCtx;
1068
1069 if (ctx->Visual.doubleBufferMode) {
1070 /* use back buffer by default */
1071 mmesa->draw_buffer = MGA_BACK;
1072 mmesa->drawOffset = mmesa->mgaScreen->backOffset;
1073 mmesa->readOffset = mmesa->mgaScreen->backOffset;
1074 mmesa->setup.dstorg = mgaScreen->backOffset;
1075 } else {
1076 /* use front buffer by default */
1077 mmesa->draw_buffer = MGA_FRONT;
1078 mmesa->drawOffset = mmesa->mgaScreen->frontOffset;
1079 mmesa->readOffset = mmesa->mgaScreen->frontOffset;
1080 mmesa->setup.dstorg = mgaScreen->frontOffset;
1081 }
1082
1083 mmesa->setup.maccess = (MA_memreset_disable |
1084 MA_fogen_disable |
1085 MA_tlutload_disable |
1086 MA_nodither_disable |
1087 MA_dit555_disable);
1088 if (driQueryOptioni (&mmesa->optionCache, "color_reduction") !=
1089 DRI_CONF_COLOR_REDUCTION_DITHER)
1090 mmesa->setup.maccess |= MA_nodither_enable;
1091
1092 switch (mmesa->mgaScreen->cpp) {
1093 case 2:
1094 mmesa->setup.maccess |= MA_pwidth_16;
1095 break;
1096 case 4:
1097 mmesa->setup.maccess |= MA_pwidth_32;
1098 break;
1099 default:
1100 fprintf( stderr, "Error: unknown cpp %d, exiting...\n",
1101 mmesa->mgaScreen->cpp );
1102 exit( 1 );
1103 }
1104
1105 switch (mmesa->glCtx->Visual.depthBits) {
1106 case 16:
1107 mmesa->setup.maccess |= MA_zwidth_16;
1108 break;
1109 case 24:
1110 mmesa->setup.maccess |= MA_zwidth_24;
1111 break;
1112 case 32:
1113 mmesa->setup.maccess |= MA_zwidth_32;
1114 break;
1115 }
1116
1117 mmesa->hw.blend_func = AC_src_one | AC_dst_zero;
1118 mmesa->hw.blend_func_enable = 0;
1119 mmesa->hw.alpha_func = AC_atmode_noacmp | MGA_FIELD( AC_atref, 0x00 );
1120 mmesa->hw.alpha_func_enable = 0;
1121 mmesa->hw.rop = mgarop_NoBLK[ GL_COPY & 0x0f ];
1122 mmesa->hw.zmode = DC_zmode_zlt | DC_atype_zi;
1123 mmesa->hw.stencil = MGA_FIELD( S_sref, 0x00) | MGA_FIELD( S_smsk, 0xff ) |
1124 MGA_FIELD( S_swtmsk, 0xff );
1125 mmesa->hw.stencilctl = SC_smode_salways | SC_sfailop_keep
1126 | SC_szfailop_keep | SC_szpassop_keep;
1127 mmesa->hw.stencil_enable = 0;
1128 mmesa->hw.cull = _CULL_DISABLE;
1129 mmesa->hw.cull_dualtex = _CULL_DISABLE;
1130 mmesa->hw.specen = 0;
1131 mmesa->hw.alpha_sel = AC_alphasel_diffused;
1132
1133 mmesa->setup.dwgctl = (DC_opcod_trap |
1134 DC_linear_xy |
1135 DC_solid_disable |
1136 DC_arzero_disable |
1137 DC_sgnzero_disable |
1138 DC_shftzero_enable |
1139 MGA_FIELD( DC_bop, 0xC ) |
1140 MGA_FIELD( DC_trans, 0x0 ) |
1141 DC_bltmod_bmonolef |
1142 DC_pattern_disable |
1143 DC_transc_disable |
1144 DC_clipdis_disable);
1145
1146 mmesa->setup.plnwt = ~0;
1147 mmesa->setup.alphactrl = (AC_amode_alpha_channel |
1148 AC_astipple_disable |
1149 AC_aten_disable);
1150
1151 mmesa->setup.fogcolor = PACK_COLOR_888((GLubyte)(ctx->Fog.Color[0]*255.0F),
1152 (GLubyte)(ctx->Fog.Color[1]*255.0F),
1153 (GLubyte)(ctx->Fog.Color[2]*255.0F));
1154
1155 mmesa->setup.wflag = 0;
1156 mmesa->setup.tdualstage0 = 0;
1157 mmesa->setup.tdualstage1 = 0;
1158 mmesa->setup.fcol = 0;
1159 mmesa->dirty |= MGA_UPLOAD_CONTEXT;
1160
1161 mmesa->envcolor[0] = 0;
1162 mmesa->envcolor[1] = 0;
1163 }
1164
1165
1166 void mgaDDInitStateFuncs( GLcontext *ctx )
1167 {
1168 ctx->Driver.UpdateState = mgaDDInvalidateState;
1169 ctx->Driver.Enable = mgaDDEnable;
1170 ctx->Driver.LightModelfv = mgaDDLightModelfv;
1171 ctx->Driver.AlphaFunc = mgaDDAlphaFunc;
1172 ctx->Driver.BlendEquationSeparate = mgaDDBlendEquationSeparate;
1173 ctx->Driver.BlendFuncSeparate = mgaDDBlendFuncSeparate;
1174 ctx->Driver.DepthFunc = mgaDDDepthFunc;
1175 ctx->Driver.DepthMask = mgaDDDepthMask;
1176 ctx->Driver.Fogfv = mgaDDFogfv;
1177 ctx->Driver.Scissor = mgaDDScissor;
1178 ctx->Driver.CullFace = mgaDDCullFaceFrontFace;
1179 ctx->Driver.FrontFace = mgaDDCullFaceFrontFace;
1180 ctx->Driver.ColorMask = mgaDDColorMask;
1181
1182 ctx->Driver.DrawBuffer = mgaDDDrawBuffer;
1183 ctx->Driver.ReadBuffer = mgaDDReadBuffer;
1184 ctx->Driver.ClearColor = mgaDDClearColor;
1185 ctx->Driver.ClearDepth = mgaDDClearDepth;
1186 ctx->Driver.LogicOpcode = mgaDDLogicOp;
1187
1188 ctx->Driver.PolygonStipple = mgaDDPolygonStipple;
1189
1190 ctx->Driver.StencilFuncSeparate = mgaDDStencilFuncSeparate;
1191 ctx->Driver.StencilMaskSeparate = mgaDDStencilMaskSeparate;
1192 ctx->Driver.StencilOpSeparate = mgaDDStencilOpSeparate;
1193
1194 ctx->Driver.DepthRange = mgaDepthRange;
1195 ctx->Driver.Viewport = mgaViewport;
1196 ctx->Driver.RenderMode = mgaRenderMode;
1197
1198 ctx->Driver.ClearIndex = 0;
1199 ctx->Driver.IndexMask = 0;
1200
1201 TNL_CONTEXT(ctx)->Driver.RunPipeline = mgaRunPipeline;
1202 }