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