fix GL_LINE_LOOP with drivers using own render pipeline stage (#12410, #13527)
[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 "mtypes.h"
30 #include "colormac.h"
31 #include "dd.h"
32
33 #include "mm.h"
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 /*
803 * _DrawDestMask is easier to cope with than <mode>.
804 */
805 switch ( ctx->DrawBuffer->_ColorDrawBufferMask[0] ) {
806 case BUFFER_BIT_FRONT_LEFT:
807 mmesa->setup.dstorg = mmesa->mgaScreen->frontOffset;
808 mmesa->draw_buffer = MGA_FRONT;
809 break;
810 case BUFFER_BIT_BACK_LEFT:
811 mmesa->setup.dstorg = mmesa->mgaScreen->backOffset;
812 mmesa->draw_buffer = MGA_BACK;
813 break;
814 default:
815 /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */
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 }