gallium: fix refcount bug introduced in eb20e2984
[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 drm_mga_sarea_t *sarea = mmesa->sarea;
782
783
784 mmesa->dirty_cliprects = 0;
785
786 driUpdateFramebufferSize(mmesa->glCtx, driDrawable);
787 if (driDrawable != driReadable) {
788 driUpdateFramebufferSize(mmesa->glCtx, driReadable);
789 }
790
791 mga_set_cliprects(mmesa);
792
793 sarea->req_drawable = driDrawable->draw;
794 sarea->req_draw_buffer = mmesa->draw_buffer;
795
796 mgaUpdateClipping( mmesa->glCtx );
797 mgaCalcViewport( mmesa->glCtx );
798 }
799
800
801 static void mgaDDDrawBuffer(GLcontext *ctx, GLenum mode )
802 {
803 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
804
805 FLUSH_BATCH( mmesa );
806
807 /*
808 * _DrawDestMask is easier to cope with than <mode>.
809 */
810 switch ( ctx->DrawBuffer->_ColorDrawBufferMask[0] ) {
811 case BUFFER_BIT_FRONT_LEFT:
812 mmesa->setup.dstorg = mmesa->mgaScreen->frontOffset;
813 mmesa->draw_buffer = MGA_FRONT;
814 break;
815 case BUFFER_BIT_BACK_LEFT:
816 mmesa->setup.dstorg = mmesa->mgaScreen->backOffset;
817 mmesa->draw_buffer = MGA_BACK;
818 break;
819 default:
820 /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */
821 FALLBACK( ctx, MGA_FALLBACK_DRAW_BUFFER, GL_TRUE );
822 return;
823 }
824
825 mmesa->dirty |= MGA_UPLOAD_CONTEXT;
826 mga_set_cliprects(mmesa);
827 FALLBACK(ctx, MGA_FALLBACK_DRAW_BUFFER, GL_FALSE);
828 }
829
830
831 static void mgaDDReadBuffer(GLcontext *ctx, GLenum mode )
832 {
833 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
834 }
835
836
837 /* =============================================================
838 * State enable/disable
839 */
840
841
842 static void mgaDDEnable(GLcontext *ctx, GLenum cap, GLboolean state)
843 {
844 mgaContextPtr mmesa = MGA_CONTEXT( ctx );
845
846 switch(cap) {
847 case GL_DITHER:
848 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
849 if (!ctx->Color.DitherFlag)
850 mmesa->setup.maccess |= MA_nodither_enable;
851 else
852 mmesa->setup.maccess &= ~MA_nodither_enable;
853 break;
854 case GL_LIGHTING:
855 case GL_COLOR_SUM_EXT:
856 FLUSH_BATCH( mmesa );
857 updateSpecularLighting( ctx );
858 break;
859 case GL_ALPHA_TEST:
860 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
861 mmesa->hw.alpha_func_enable = (state) ? ~0 : 0;
862 break;
863 case GL_DEPTH_TEST:
864 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
865 FALLBACK (ctx, MGA_FALLBACK_DEPTH,
866 ctx->Depth.Func == GL_NEVER && ctx->Depth.Test);
867 break;
868
869 case GL_SCISSOR_TEST:
870 FLUSH_BATCH( mmesa );
871 mmesa->scissor = state;
872 mgaUpdateClipping( ctx );
873 break;
874
875 case GL_FOG:
876 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
877 if (ctx->Fog.Enabled)
878 mmesa->setup.maccess |= MA_fogen_enable;
879 else
880 mmesa->setup.maccess &= ~MA_fogen_enable;
881 break;
882 case GL_CULL_FACE:
883 mgaDDCullFaceFrontFace( ctx, 0 );
884 break;
885 case GL_TEXTURE_1D:
886 case GL_TEXTURE_2D:
887 case GL_TEXTURE_3D:
888 break;
889 case GL_POLYGON_STIPPLE:
890 if (mmesa->haveHwStipple && mmesa->raster_primitive == GL_TRIANGLES) {
891 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
892 mmesa->setup.dwgctl &= ~(0xf<<20);
893 if (state)
894 mmesa->setup.dwgctl |= mmesa->poly_stipple;
895 }
896 break;
897
898 case GL_BLEND:
899 case GL_COLOR_LOGIC_OP:
900 updateBlendLogicOp( ctx );
901 break;
902
903 case GL_STENCIL_TEST:
904 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
905 if (mmesa->hw_stencil) {
906 mmesa->hw.stencil_enable = ( state ) ? ~0 : 0;
907 }
908 else {
909 FALLBACK( ctx, MGA_FALLBACK_STENCIL, state );
910 }
911 default:
912 break;
913 }
914 }
915
916
917 /* =============================================================
918 */
919
920 static void mgaDDPrintDirty( const char *msg, GLuint state )
921 {
922 fprintf(stderr, "%s (0x%03x): %s%s%s%s%s%s%s\n",
923 msg,
924 (unsigned int) state,
925 (state & MGA_WAIT_AGE) ? "wait-age " : "",
926 (state & MGA_UPLOAD_TEX0IMAGE) ? "upload-tex0-img " : "",
927 (state & MGA_UPLOAD_TEX1IMAGE) ? "upload-tex1-img " : "",
928 (state & MGA_UPLOAD_CONTEXT) ? "upload-ctx " : "",
929 (state & MGA_UPLOAD_TEX0) ? "upload-tex0 " : "",
930 (state & MGA_UPLOAD_TEX1) ? "upload-tex1 " : "",
931 (state & MGA_UPLOAD_PIPE) ? "upload-pipe " : ""
932 );
933 }
934
935 /* Push the state into the sarea and/or texture memory.
936 */
937 void mgaEmitHwStateLocked( mgaContextPtr mmesa )
938 {
939 drm_mga_sarea_t *sarea = mmesa->sarea;
940 GLcontext * ctx = mmesa->glCtx;
941
942 if (MGA_DEBUG & DEBUG_VERBOSE_MSG)
943 mgaDDPrintDirty( __FUNCTION__, mmesa->dirty );
944
945 if (mmesa->dirty & MGA_UPLOAD_CONTEXT) {
946 mmesa->setup.wflag = _CULL_DISABLE;
947 if (mmesa->raster_primitive == GL_TRIANGLES) {
948 if ((ctx->Texture.Unit[0]._ReallyEnabled == TEXTURE_2D_BIT &&
949 ctx->Texture.Unit[1]._ReallyEnabled == TEXTURE_2D_BIT)) {
950 mmesa->setup.wflag = mmesa->hw.cull_dualtex;
951 }
952 else {
953 mmesa->setup.wflag = mmesa->hw.cull;
954 }
955 }
956
957 mmesa->setup.stencil = mmesa->hw.stencil
958 & mmesa->hw.stencil_enable;
959 mmesa->setup.stencilctl = mmesa->hw.stencilctl
960 & mmesa->hw.stencil_enable;
961
962 /* If depth testing is not enabled, then use the no Z-compare / no
963 * Z-write mode. Otherwise, use whatever is set in hw.zmode.
964 */
965 mmesa->setup.dwgctl &= (DC_zmode_MASK & DC_atype_MASK);
966 mmesa->setup.dwgctl |= (ctx->Depth.Test)
967 ? mmesa->hw.zmode : (DC_zmode_nozcmp | DC_atype_i);
968
969 mmesa->setup.dwgctl &= DC_bop_MASK;
970 mmesa->setup.dwgctl |= RGBA_LOGICOP_ENABLED(ctx)
971 ? mmesa->hw.rop : mgarop_NoBLK[ GL_COPY & 0x0f ];
972
973 mmesa->setup.alphactrl &= AC_src_MASK & AC_dst_MASK & AC_atmode_MASK
974 & AC_atref_MASK & AC_alphasel_MASK;
975 mmesa->setup.alphactrl |=
976 (mmesa->hw.alpha_func & mmesa->hw.alpha_func_enable) |
977 (mmesa->hw.blend_func & mmesa->hw.blend_func_enable) |
978 ((AC_src_one | AC_dst_zero) & ~mmesa->hw.blend_func_enable) |
979 mmesa->hw.alpha_sel;
980
981 memcpy( &sarea->context_state, &mmesa->setup, sizeof(mmesa->setup));
982 }
983
984 if ((mmesa->dirty & MGA_UPLOAD_TEX0) && mmesa->CurrentTexObj[0]) {
985 memcpy(&sarea->tex_state[0],
986 &mmesa->CurrentTexObj[0]->setup,
987 sizeof(sarea->tex_state[0]));
988 }
989
990 if ((mmesa->dirty & MGA_UPLOAD_TEX1) && mmesa->CurrentTexObj[1]) {
991 memcpy(&sarea->tex_state[1],
992 &mmesa->CurrentTexObj[1]->setup,
993 sizeof(sarea->tex_state[1]));
994 }
995
996 if (mmesa->dirty & (MGA_UPLOAD_TEX0 | MGA_UPLOAD_TEX1)) {
997 sarea->tex_state[0].texctl2 &= ~TMC_specen_enable;
998 sarea->tex_state[1].texctl2 &= ~TMC_specen_enable;
999 sarea->tex_state[0].texctl2 |= mmesa->hw.specen;
1000 sarea->tex_state[1].texctl2 |= mmesa->hw.specen;
1001 }
1002
1003 if (mmesa->dirty & MGA_UPLOAD_PIPE) {
1004 /* mmesa->sarea->wacceptseq = mmesa->hw_primitive; */
1005 mmesa->sarea->warp_pipe = mmesa->vertex_format;
1006 mmesa->sarea->vertsize = mmesa->vertex_size;
1007 }
1008
1009 mmesa->sarea->dirty |= mmesa->dirty;
1010 mmesa->dirty &= MGA_UPLOAD_CLIPRECTS;
1011 }
1012
1013 /* =============================================================
1014 */
1015
1016
1017 static void mgaDDValidateState( GLcontext *ctx )
1018 {
1019 mgaContextPtr mmesa = MGA_CONTEXT( ctx );
1020
1021 FLUSH_BATCH( mmesa );
1022
1023 if (mmesa->NewGLState & _NEW_TEXTURE) {
1024 mgaUpdateTextureState(ctx);
1025 }
1026
1027 if (!mmesa->Fallback) {
1028 if (mmesa->NewGLState & _MGA_NEW_RASTERSETUP) {
1029 mgaChooseVertexState( ctx );
1030 }
1031
1032 if (mmesa->NewGLState & _MGA_NEW_RENDERSTATE) {
1033 mgaChooseRenderState( ctx );
1034 }
1035 }
1036
1037 mmesa->NewGLState = 0;
1038 }
1039
1040
1041 static void mgaDDInvalidateState( GLcontext *ctx, GLuint new_state )
1042 {
1043 _swrast_InvalidateState( ctx, new_state );
1044 _swsetup_InvalidateState( ctx, new_state );
1045 _vbo_InvalidateState( ctx, new_state );
1046 _tnl_InvalidateState( ctx, new_state );
1047 MGA_CONTEXT(ctx)->NewGLState |= new_state;
1048 }
1049
1050
1051 static void mgaRunPipeline( GLcontext *ctx )
1052 {
1053 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
1054
1055 if (mmesa->NewGLState) {
1056 mgaDDValidateState( ctx );
1057 }
1058
1059 if (mmesa->dirty) {
1060 mgaEmitHwStateLocked( mmesa );
1061 }
1062
1063 _tnl_run_pipeline( ctx );
1064 }
1065
1066
1067 void mgaInitState( mgaContextPtr mmesa )
1068 {
1069 mgaScreenPrivate *mgaScreen = mmesa->mgaScreen;
1070 GLcontext *ctx = mmesa->glCtx;
1071
1072 if (ctx->Visual.doubleBufferMode) {
1073 /* use back buffer by default */
1074 mmesa->draw_buffer = MGA_BACK;
1075 mmesa->drawOffset = mmesa->mgaScreen->backOffset;
1076 mmesa->readOffset = mmesa->mgaScreen->backOffset;
1077 mmesa->setup.dstorg = mgaScreen->backOffset;
1078 } else {
1079 /* use front buffer by default */
1080 mmesa->draw_buffer = MGA_FRONT;
1081 mmesa->drawOffset = mmesa->mgaScreen->frontOffset;
1082 mmesa->readOffset = mmesa->mgaScreen->frontOffset;
1083 mmesa->setup.dstorg = mgaScreen->frontOffset;
1084 }
1085
1086 mmesa->setup.maccess = (MA_memreset_disable |
1087 MA_fogen_disable |
1088 MA_tlutload_disable |
1089 MA_nodither_disable |
1090 MA_dit555_disable);
1091 if (driQueryOptioni (&mmesa->optionCache, "color_reduction") !=
1092 DRI_CONF_COLOR_REDUCTION_DITHER)
1093 mmesa->setup.maccess |= MA_nodither_enable;
1094
1095 switch (mmesa->mgaScreen->cpp) {
1096 case 2:
1097 mmesa->setup.maccess |= MA_pwidth_16;
1098 break;
1099 case 4:
1100 mmesa->setup.maccess |= MA_pwidth_32;
1101 break;
1102 default:
1103 fprintf( stderr, "Error: unknown cpp %d, exiting...\n",
1104 mmesa->mgaScreen->cpp );
1105 exit( 1 );
1106 }
1107
1108 switch (mmesa->glCtx->Visual.depthBits) {
1109 case 16:
1110 mmesa->setup.maccess |= MA_zwidth_16;
1111 break;
1112 case 24:
1113 mmesa->setup.maccess |= MA_zwidth_24;
1114 break;
1115 case 32:
1116 mmesa->setup.maccess |= MA_zwidth_32;
1117 break;
1118 }
1119
1120 mmesa->hw.blend_func = AC_src_one | AC_dst_zero;
1121 mmesa->hw.blend_func_enable = 0;
1122 mmesa->hw.alpha_func = AC_atmode_noacmp | MGA_FIELD( AC_atref, 0x00 );
1123 mmesa->hw.alpha_func_enable = 0;
1124 mmesa->hw.rop = mgarop_NoBLK[ GL_COPY & 0x0f ];
1125 mmesa->hw.zmode = DC_zmode_zlt | DC_atype_zi;
1126 mmesa->hw.stencil = MGA_FIELD( S_sref, 0x00) | MGA_FIELD( S_smsk, 0xff ) |
1127 MGA_FIELD( S_swtmsk, 0xff );
1128 mmesa->hw.stencilctl = SC_smode_salways | SC_sfailop_keep
1129 | SC_szfailop_keep | SC_szpassop_keep;
1130 mmesa->hw.stencil_enable = 0;
1131 mmesa->hw.cull = _CULL_DISABLE;
1132 mmesa->hw.cull_dualtex = _CULL_DISABLE;
1133 mmesa->hw.specen = 0;
1134 mmesa->hw.alpha_sel = AC_alphasel_diffused;
1135
1136 mmesa->setup.dwgctl = (DC_opcod_trap |
1137 DC_linear_xy |
1138 DC_solid_disable |
1139 DC_arzero_disable |
1140 DC_sgnzero_disable |
1141 DC_shftzero_enable |
1142 MGA_FIELD( DC_bop, 0xC ) |
1143 MGA_FIELD( DC_trans, 0x0 ) |
1144 DC_bltmod_bmonolef |
1145 DC_pattern_disable |
1146 DC_transc_disable |
1147 DC_clipdis_disable);
1148
1149 mmesa->setup.plnwt = ~0;
1150 mmesa->setup.alphactrl = (AC_amode_alpha_channel |
1151 AC_astipple_disable |
1152 AC_aten_disable);
1153
1154 mmesa->setup.fogcolor = PACK_COLOR_888((GLubyte)(ctx->Fog.Color[0]*255.0F),
1155 (GLubyte)(ctx->Fog.Color[1]*255.0F),
1156 (GLubyte)(ctx->Fog.Color[2]*255.0F));
1157
1158 mmesa->setup.wflag = 0;
1159 mmesa->setup.tdualstage0 = 0;
1160 mmesa->setup.tdualstage1 = 0;
1161 mmesa->setup.fcol = 0;
1162 mmesa->dirty |= MGA_UPLOAD_CONTEXT;
1163
1164 mmesa->envcolor[0] = 0;
1165 mmesa->envcolor[1] = 0;
1166 }
1167
1168
1169 void mgaDDInitStateFuncs( GLcontext *ctx )
1170 {
1171 ctx->Driver.UpdateState = mgaDDInvalidateState;
1172 ctx->Driver.Enable = mgaDDEnable;
1173 ctx->Driver.LightModelfv = mgaDDLightModelfv;
1174 ctx->Driver.AlphaFunc = mgaDDAlphaFunc;
1175 ctx->Driver.BlendEquationSeparate = mgaDDBlendEquationSeparate;
1176 ctx->Driver.BlendFuncSeparate = mgaDDBlendFuncSeparate;
1177 ctx->Driver.DepthFunc = mgaDDDepthFunc;
1178 ctx->Driver.DepthMask = mgaDDDepthMask;
1179 ctx->Driver.Fogfv = mgaDDFogfv;
1180 ctx->Driver.Scissor = mgaDDScissor;
1181 ctx->Driver.CullFace = mgaDDCullFaceFrontFace;
1182 ctx->Driver.FrontFace = mgaDDCullFaceFrontFace;
1183 ctx->Driver.ColorMask = mgaDDColorMask;
1184
1185 ctx->Driver.DrawBuffer = mgaDDDrawBuffer;
1186 ctx->Driver.ReadBuffer = mgaDDReadBuffer;
1187 ctx->Driver.ClearColor = mgaDDClearColor;
1188 ctx->Driver.ClearDepth = mgaDDClearDepth;
1189 ctx->Driver.LogicOpcode = mgaDDLogicOp;
1190
1191 ctx->Driver.PolygonStipple = mgaDDPolygonStipple;
1192
1193 ctx->Driver.StencilFuncSeparate = mgaDDStencilFuncSeparate;
1194 ctx->Driver.StencilMaskSeparate = mgaDDStencilMaskSeparate;
1195 ctx->Driver.StencilOpSeparate = mgaDDStencilOpSeparate;
1196
1197 ctx->Driver.DepthRange = mgaDepthRange;
1198 ctx->Driver.Viewport = mgaViewport;
1199 ctx->Driver.RenderMode = mgaRenderMode;
1200
1201 ctx->Driver.ClearIndex = 0;
1202 ctx->Driver.IndexMask = 0;
1203
1204 TNL_CONTEXT(ctx)->Driver.RunPipeline = mgaRunPipeline;
1205 }