fix up radeon span functions using latest r200 code from Brian,
[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;
303 int y2 = y1 + ctx->Scissor.Height;
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
516 mgaDDStencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func, GLint ref,
517 GLuint mask)
518 {
519 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
520 GLuint stencil;
521 GLuint stencilctl;
522
523 stencil = MGA_FIELD( S_sref, ref ) | MGA_FIELD( S_smsk, mask );
524 switch (func)
525 {
526 case GL_NEVER:
527 stencilctl = SC_smode_snever;
528 break;
529 case GL_LESS:
530 stencilctl = SC_smode_slt;
531 break;
532 case GL_LEQUAL:
533 stencilctl = SC_smode_slte;
534 break;
535 case GL_GREATER:
536 stencilctl = SC_smode_sgt;
537 break;
538 case GL_GEQUAL:
539 stencilctl = SC_smode_sgte;
540 break;
541 case GL_NOTEQUAL:
542 stencilctl = SC_smode_sne;
543 break;
544 case GL_EQUAL:
545 stencilctl = SC_smode_se;
546 break;
547 case GL_ALWAYS:
548 default:
549 stencilctl = SC_smode_salways;
550 break;
551 }
552
553 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
554 mmesa->hw.stencil &= (S_sref_MASK & S_smsk_MASK);
555 mmesa->hw.stencil |= stencil;
556 mmesa->hw.stencilctl &= SC_smode_MASK;
557 mmesa->hw.stencilctl |= stencilctl;
558 }
559
560 static void
561 mgaDDStencilMaskSeparate(GLcontext *ctx, GLenum face, GLuint mask)
562 {
563 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
564
565 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
566 mmesa->hw.stencil &= S_swtmsk_MASK;
567 mmesa->hw.stencil |= MGA_FIELD( S_swtmsk, mask );
568 }
569
570 static void
571 mgaDDStencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail, GLenum zfail,
572 GLenum zpass)
573 {
574 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
575 GLuint stencilctl;
576
577 stencilctl = 0;
578 switch (ctx->Stencil.FailFunc[0])
579 {
580 case GL_KEEP:
581 stencilctl |= SC_sfailop_keep;
582 break;
583 case GL_ZERO:
584 stencilctl |= SC_sfailop_zero;
585 break;
586 case GL_REPLACE:
587 stencilctl |= SC_sfailop_replace;
588 break;
589 case GL_INCR:
590 stencilctl |= SC_sfailop_incrsat;
591 break;
592 case GL_DECR:
593 stencilctl |= SC_sfailop_decrsat;
594 break;
595 case GL_INCR_WRAP:
596 stencilctl |= SC_sfailop_incr;
597 break;
598 case GL_DECR_WRAP:
599 stencilctl |= SC_sfailop_decr;
600 break;
601 case GL_INVERT:
602 stencilctl |= SC_sfailop_invert;
603 break;
604 default:
605 break;
606 }
607
608 switch (ctx->Stencil.ZFailFunc[0])
609 {
610 case GL_KEEP:
611 stencilctl |= SC_szfailop_keep;
612 break;
613 case GL_ZERO:
614 stencilctl |= SC_szfailop_zero;
615 break;
616 case GL_REPLACE:
617 stencilctl |= SC_szfailop_replace;
618 break;
619 case GL_INCR:
620 stencilctl |= SC_szfailop_incrsat;
621 break;
622 case GL_DECR:
623 stencilctl |= SC_szfailop_decrsat;
624 break;
625 case GL_INCR_WRAP:
626 stencilctl |= SC_szfailop_incr;
627 break;
628 case GL_DECR_WRAP:
629 stencilctl |= SC_szfailop_decr;
630 break;
631 case GL_INVERT:
632 stencilctl |= SC_szfailop_invert;
633 break;
634 default:
635 break;
636 }
637
638 switch (ctx->Stencil.ZPassFunc[0])
639 {
640 case GL_KEEP:
641 stencilctl |= SC_szpassop_keep;
642 break;
643 case GL_ZERO:
644 stencilctl |= SC_szpassop_zero;
645 break;
646 case GL_REPLACE:
647 stencilctl |= SC_szpassop_replace;
648 break;
649 case GL_INCR:
650 stencilctl |= SC_szpassop_incrsat;
651 break;
652 case GL_DECR:
653 stencilctl |= SC_szpassop_decrsat;
654 break;
655 case GL_INCR_WRAP:
656 stencilctl |= SC_szpassop_incr;
657 break;
658 case GL_DECR_WRAP:
659 stencilctl |= SC_szpassop_decr;
660 break;
661 case GL_INVERT:
662 stencilctl |= SC_szpassop_invert;
663 break;
664 default:
665 break;
666 }
667
668 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
669 mmesa->hw.stencilctl &= (SC_sfailop_MASK & SC_szfailop_MASK
670 & SC_szpassop_MASK);
671 mmesa->hw.stencilctl |= stencilctl;
672 }
673
674
675 /* =============================================================
676 * Window position and viewport transformation
677 */
678
679 void mgaCalcViewport( GLcontext *ctx )
680 {
681 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
682 const GLfloat *v = ctx->Viewport._WindowMap.m;
683 GLfloat *m = mmesa->hw_viewport;
684
685 /* See also mga_translate_vertex.
686 */
687 m[MAT_SX] = v[MAT_SX];
688 m[MAT_TX] = v[MAT_TX] + mmesa->drawX + SUBPIXEL_X;
689 m[MAT_SY] = - v[MAT_SY];
690 m[MAT_TY] = - v[MAT_TY] + mmesa->driDrawable->h + mmesa->drawY + SUBPIXEL_Y;
691 m[MAT_SZ] = v[MAT_SZ] * mmesa->depth_scale;
692 m[MAT_TZ] = v[MAT_TZ] * mmesa->depth_scale;
693
694 mmesa->SetupNewInputs = ~0;
695 }
696
697 static void mgaViewport( GLcontext *ctx,
698 GLint x, GLint y,
699 GLsizei width, GLsizei height )
700 {
701 mgaCalcViewport( ctx );
702 }
703
704 static void mgaDepthRange( GLcontext *ctx,
705 GLclampd nearval, GLclampd farval )
706 {
707 mgaCalcViewport( ctx );
708 }
709
710
711 /* =============================================================
712 * Miscellaneous
713 */
714
715 static void mgaDDClearColor(GLcontext *ctx,
716 const GLfloat color[4] )
717 {
718 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
719 GLubyte c[4];
720 CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]);
721 CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]);
722 CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]);
723 CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]);
724
725 mmesa->ClearColor = mgaPackColor( mmesa->mgaScreen->cpp,
726 c[0], c[1], c[2], c[3]);
727 }
728
729
730 /* Fallback to swrast for select and feedback.
731 */
732 static void mgaRenderMode( GLcontext *ctx, GLenum mode )
733 {
734 FALLBACK( ctx, MGA_FALLBACK_RENDERMODE, (mode != GL_RENDER) );
735 }
736
737
738 static void mgaDDLogicOp( GLcontext *ctx, GLenum opcode )
739 {
740 mgaContextPtr mmesa = MGA_CONTEXT( ctx );
741
742 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
743 mmesa->hw.rop = mgarop_NoBLK[ opcode & 0x0f ];
744 }
745
746
747 static void mgaXMesaSetFrontClipRects( mgaContextPtr mmesa )
748 {
749 __DRIdrawablePrivate *driDrawable = mmesa->driDrawable;
750
751 if (driDrawable->numClipRects == 0) {
752 static drm_clip_rect_t zeroareacliprect = {0,0,0,0};
753 mmesa->numClipRects = 1;
754 mmesa->pClipRects = &zeroareacliprect;
755 } else {
756 mmesa->numClipRects = driDrawable->numClipRects;
757 mmesa->pClipRects = driDrawable->pClipRects;
758 }
759 mmesa->drawX = driDrawable->x;
760 mmesa->drawY = driDrawable->y;
761
762 mmesa->setup.dstorg = mmesa->drawOffset;
763 mmesa->dirty |= MGA_UPLOAD_CONTEXT | MGA_UPLOAD_CLIPRECTS;
764 }
765
766
767 static void mgaXMesaSetBackClipRects( mgaContextPtr mmesa )
768 {
769 __DRIdrawablePrivate *driDrawable = mmesa->driDrawable;
770
771 if (driDrawable->numBackClipRects == 0)
772 {
773 if (driDrawable->numClipRects == 0) {
774 static drm_clip_rect_t zeroareacliprect = {0,0,0,0};
775 mmesa->numClipRects = 1;
776 mmesa->pClipRects = &zeroareacliprect;
777 } else {
778 mmesa->numClipRects = driDrawable->numClipRects;
779 mmesa->pClipRects = driDrawable->pClipRects;
780 }
781 mmesa->drawX = driDrawable->x;
782 mmesa->drawY = driDrawable->y;
783 } else {
784 mmesa->numClipRects = driDrawable->numBackClipRects;
785 mmesa->pClipRects = driDrawable->pBackClipRects;
786 mmesa->drawX = driDrawable->backX;
787 mmesa->drawY = driDrawable->backY;
788 }
789
790 mmesa->setup.dstorg = mmesa->drawOffset;
791 mmesa->dirty |= MGA_UPLOAD_CONTEXT | MGA_UPLOAD_CLIPRECTS;
792 }
793
794
795 void mgaUpdateRects( mgaContextPtr mmesa, GLuint buffers )
796 {
797 __DRIdrawablePrivate *driDrawable = mmesa->driDrawable;
798 drm_mga_sarea_t *sarea = mmesa->sarea;
799
800
801 DRI_VALIDATE_DRAWABLE_INFO(mmesa->driScreen, driDrawable);
802 mmesa->dirty_cliprects = 0;
803
804 if (mmesa->draw_buffer == MGA_FRONT)
805 mgaXMesaSetFrontClipRects( mmesa );
806 else
807 mgaXMesaSetBackClipRects( mmesa );
808
809 sarea->req_drawable = driDrawable->draw;
810 sarea->req_draw_buffer = mmesa->draw_buffer;
811
812 mgaUpdateClipping( mmesa->glCtx );
813 mgaCalcViewport( mmesa->glCtx );
814
815 mmesa->dirty |= MGA_UPLOAD_CLIPRECTS;
816 }
817
818
819 static void mgaDDDrawBuffer(GLcontext *ctx, GLenum mode )
820 {
821 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
822
823 FLUSH_BATCH( mmesa );
824
825 /*
826 * _DrawDestMask is easier to cope with than <mode>.
827 */
828 switch ( ctx->DrawBuffer->_ColorDrawBufferMask[0] ) {
829 case BUFFER_BIT_FRONT_LEFT:
830 mmesa->setup.dstorg = mmesa->mgaScreen->frontOffset;
831 mmesa->dirty |= MGA_UPLOAD_CONTEXT;
832 mmesa->draw_buffer = MGA_FRONT;
833 mgaXMesaSetFrontClipRects( mmesa );
834 FALLBACK( ctx, MGA_FALLBACK_DRAW_BUFFER, GL_FALSE );
835 break;
836 case BUFFER_BIT_BACK_LEFT:
837 mmesa->setup.dstorg = mmesa->mgaScreen->backOffset;
838 mmesa->draw_buffer = MGA_BACK;
839 mmesa->dirty |= MGA_UPLOAD_CONTEXT;
840 mgaXMesaSetBackClipRects( mmesa );
841 FALLBACK( ctx, MGA_FALLBACK_DRAW_BUFFER, GL_FALSE );
842 break;
843 default:
844 /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */
845 FALLBACK( ctx, MGA_FALLBACK_DRAW_BUFFER, GL_TRUE );
846 return;
847 }
848 }
849
850
851 static void mgaDDReadBuffer(GLcontext *ctx, GLenum mode )
852 {
853 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
854 }
855
856
857 /* =============================================================
858 * State enable/disable
859 */
860
861
862 static void mgaDDEnable(GLcontext *ctx, GLenum cap, GLboolean state)
863 {
864 mgaContextPtr mmesa = MGA_CONTEXT( ctx );
865
866 switch(cap) {
867 case GL_DITHER:
868 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
869 if (!ctx->Color.DitherFlag)
870 mmesa->setup.maccess |= MA_nodither_enable;
871 else
872 mmesa->setup.maccess &= ~MA_nodither_enable;
873 break;
874 case GL_LIGHTING:
875 case GL_COLOR_SUM_EXT:
876 FLUSH_BATCH( mmesa );
877 updateSpecularLighting( ctx );
878 break;
879 case GL_ALPHA_TEST:
880 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
881 mmesa->hw.alpha_func_enable = (state) ? ~0 : 0;
882 break;
883 case GL_DEPTH_TEST:
884 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
885 FALLBACK (ctx, MGA_FALLBACK_DEPTH,
886 ctx->Depth.Func == GL_NEVER && ctx->Depth.Test);
887 break;
888
889 case GL_SCISSOR_TEST:
890 FLUSH_BATCH( mmesa );
891 mmesa->scissor = state;
892 mgaUpdateClipping( ctx );
893 break;
894
895 case GL_FOG:
896 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
897 if (ctx->Fog.Enabled)
898 mmesa->setup.maccess |= MA_fogen_enable;
899 else
900 mmesa->setup.maccess &= ~MA_fogen_enable;
901 break;
902 case GL_CULL_FACE:
903 mgaDDCullFaceFrontFace( ctx, 0 );
904 break;
905 case GL_TEXTURE_1D:
906 case GL_TEXTURE_2D:
907 case GL_TEXTURE_3D:
908 break;
909 case GL_POLYGON_STIPPLE:
910 if (mmesa->haveHwStipple && mmesa->raster_primitive == GL_TRIANGLES) {
911 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
912 mmesa->setup.dwgctl &= ~(0xf<<20);
913 if (state)
914 mmesa->setup.dwgctl |= mmesa->poly_stipple;
915 }
916 break;
917
918 case GL_BLEND:
919 case GL_COLOR_LOGIC_OP:
920 updateBlendLogicOp( ctx );
921 break;
922
923 case GL_STENCIL_TEST:
924 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
925 if (mmesa->hw_stencil) {
926 mmesa->hw.stencil_enable = ( state ) ? ~0 : 0;
927 }
928 else {
929 FALLBACK( ctx, MGA_FALLBACK_STENCIL, state );
930 }
931 default:
932 break;
933 }
934 }
935
936
937 /* =============================================================
938 */
939
940 static void mgaDDPrintDirty( const char *msg, GLuint state )
941 {
942 fprintf(stderr, "%s (0x%03x): %s%s%s%s%s%s%s\n",
943 msg,
944 (unsigned int) state,
945 (state & MGA_WAIT_AGE) ? "wait-age " : "",
946 (state & MGA_UPLOAD_TEX0IMAGE) ? "upload-tex0-img " : "",
947 (state & MGA_UPLOAD_TEX1IMAGE) ? "upload-tex1-img " : "",
948 (state & MGA_UPLOAD_CONTEXT) ? "upload-ctx " : "",
949 (state & MGA_UPLOAD_TEX0) ? "upload-tex0 " : "",
950 (state & MGA_UPLOAD_TEX1) ? "upload-tex1 " : "",
951 (state & MGA_UPLOAD_PIPE) ? "upload-pipe " : ""
952 );
953 }
954
955 /* Push the state into the sarea and/or texture memory.
956 */
957 void mgaEmitHwStateLocked( mgaContextPtr mmesa )
958 {
959 drm_mga_sarea_t *sarea = mmesa->sarea;
960 GLcontext * ctx = mmesa->glCtx;
961
962 if (MGA_DEBUG & DEBUG_VERBOSE_MSG)
963 mgaDDPrintDirty( __FUNCTION__, mmesa->dirty );
964
965 if (mmesa->dirty & MGA_UPLOAD_CONTEXT) {
966 mmesa->setup.wflag = _CULL_DISABLE;
967 if (mmesa->raster_primitive == GL_TRIANGLES) {
968 if ((ctx->Texture.Unit[0]._ReallyEnabled == TEXTURE_2D_BIT &&
969 ctx->Texture.Unit[1]._ReallyEnabled == TEXTURE_2D_BIT)) {
970 mmesa->setup.wflag = mmesa->hw.cull_dualtex;
971 }
972 else {
973 mmesa->setup.wflag = mmesa->hw.cull;
974 }
975 }
976
977 mmesa->setup.stencil = mmesa->hw.stencil
978 & mmesa->hw.stencil_enable;
979 mmesa->setup.stencilctl = mmesa->hw.stencilctl
980 & mmesa->hw.stencil_enable;
981
982 /* If depth testing is not enabled, then use the no Z-compare / no
983 * Z-write mode. Otherwise, use whatever is set in hw.zmode.
984 */
985 mmesa->setup.dwgctl &= (DC_zmode_MASK & DC_atype_MASK);
986 mmesa->setup.dwgctl |= (ctx->Depth.Test)
987 ? mmesa->hw.zmode : (DC_zmode_nozcmp | DC_atype_i);
988
989 mmesa->setup.dwgctl &= DC_bop_MASK;
990 mmesa->setup.dwgctl |= (ctx->Color._LogicOpEnabled)
991 ? mmesa->hw.rop : mgarop_NoBLK[ GL_COPY & 0x0f ];
992
993 mmesa->setup.alphactrl &= AC_src_MASK & AC_dst_MASK & AC_atmode_MASK
994 & AC_atref_MASK & AC_alphasel_MASK;
995 mmesa->setup.alphactrl |=
996 (mmesa->hw.alpha_func & mmesa->hw.alpha_func_enable) |
997 (mmesa->hw.blend_func & mmesa->hw.blend_func_enable) |
998 ((AC_src_one | AC_dst_zero) & ~mmesa->hw.blend_func_enable) |
999 mmesa->hw.alpha_sel;
1000
1001 memcpy( &sarea->context_state, &mmesa->setup, sizeof(mmesa->setup));
1002 }
1003
1004 if ((mmesa->dirty & MGA_UPLOAD_TEX0) && mmesa->CurrentTexObj[0]) {
1005 memcpy(&sarea->tex_state[0],
1006 &mmesa->CurrentTexObj[0]->setup,
1007 sizeof(sarea->tex_state[0]));
1008 }
1009
1010 if ((mmesa->dirty & MGA_UPLOAD_TEX1) && mmesa->CurrentTexObj[1]) {
1011 memcpy(&sarea->tex_state[1],
1012 &mmesa->CurrentTexObj[1]->setup,
1013 sizeof(sarea->tex_state[1]));
1014 }
1015
1016 if (mmesa->dirty & (MGA_UPLOAD_TEX0 | MGA_UPLOAD_TEX1)) {
1017 sarea->tex_state[0].texctl2 &= ~TMC_specen_enable;
1018 sarea->tex_state[1].texctl2 &= ~TMC_specen_enable;
1019 sarea->tex_state[0].texctl2 |= mmesa->hw.specen;
1020 sarea->tex_state[1].texctl2 |= mmesa->hw.specen;
1021 }
1022
1023 if (mmesa->dirty & MGA_UPLOAD_PIPE) {
1024 /* mmesa->sarea->wacceptseq = mmesa->hw_primitive; */
1025 mmesa->sarea->warp_pipe = mmesa->vertex_format;
1026 mmesa->sarea->vertsize = mmesa->vertex_size;
1027 }
1028
1029 mmesa->sarea->dirty |= mmesa->dirty;
1030 mmesa->dirty &= MGA_UPLOAD_CLIPRECTS;
1031 }
1032
1033 /* =============================================================
1034 */
1035
1036
1037 static void mgaDDValidateState( GLcontext *ctx )
1038 {
1039 mgaContextPtr mmesa = MGA_CONTEXT( ctx );
1040
1041 FLUSH_BATCH( mmesa );
1042
1043 if (mmesa->NewGLState & _NEW_TEXTURE) {
1044 mgaUpdateTextureState(ctx);
1045 }
1046
1047 if (!mmesa->Fallback) {
1048 if (mmesa->NewGLState & _MGA_NEW_RASTERSETUP) {
1049 mgaChooseVertexState( ctx );
1050 }
1051
1052 if (mmesa->NewGLState & _MGA_NEW_RENDERSTATE) {
1053 mgaChooseRenderState( ctx );
1054 }
1055 }
1056
1057 mmesa->NewGLState = 0;
1058 }
1059
1060
1061 static void mgaDDInvalidateState( GLcontext *ctx, GLuint new_state )
1062 {
1063 _swrast_InvalidateState( ctx, new_state );
1064 _swsetup_InvalidateState( ctx, new_state );
1065 _ac_InvalidateState( ctx, new_state );
1066 _tnl_InvalidateState( ctx, new_state );
1067 MGA_CONTEXT(ctx)->NewGLState |= new_state;
1068 }
1069
1070
1071 static void mgaRunPipeline( GLcontext *ctx )
1072 {
1073 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
1074
1075 if (mmesa->NewGLState) {
1076 mgaDDValidateState( ctx );
1077 }
1078
1079 if (mmesa->dirty) {
1080 mgaEmitHwStateLocked( mmesa );
1081 }
1082
1083 _tnl_run_pipeline( ctx );
1084 }
1085
1086
1087 void mgaInitState( mgaContextPtr mmesa )
1088 {
1089 mgaScreenPrivate *mgaScreen = mmesa->mgaScreen;
1090 GLcontext *ctx = mmesa->glCtx;
1091
1092 if (ctx->Visual.doubleBufferMode) {
1093 /* use back buffer by default */
1094 mmesa->draw_buffer = MGA_BACK;
1095 mmesa->drawOffset = mmesa->mgaScreen->backOffset;
1096 mmesa->readOffset = mmesa->mgaScreen->backOffset;
1097 mmesa->setup.dstorg = mgaScreen->backOffset;
1098 } else {
1099 /* use front buffer by default */
1100 mmesa->draw_buffer = MGA_FRONT;
1101 mmesa->drawOffset = mmesa->mgaScreen->frontOffset;
1102 mmesa->readOffset = mmesa->mgaScreen->frontOffset;
1103 mmesa->setup.dstorg = mgaScreen->frontOffset;
1104 }
1105
1106 mmesa->setup.maccess = (MA_memreset_disable |
1107 MA_fogen_disable |
1108 MA_tlutload_disable |
1109 MA_nodither_disable |
1110 MA_dit555_disable);
1111 if (driQueryOptioni (&mmesa->optionCache, "color_reduction") !=
1112 DRI_CONF_COLOR_REDUCTION_DITHER)
1113 mmesa->setup.maccess |= MA_nodither_enable;
1114
1115 switch (mmesa->mgaScreen->cpp) {
1116 case 2:
1117 mmesa->setup.maccess |= MA_pwidth_16;
1118 break;
1119 case 4:
1120 mmesa->setup.maccess |= MA_pwidth_32;
1121 break;
1122 default:
1123 fprintf( stderr, "Error: unknown cpp %d, exiting...\n",
1124 mmesa->mgaScreen->cpp );
1125 exit( 1 );
1126 }
1127
1128 switch (mmesa->glCtx->Visual.depthBits) {
1129 case 16:
1130 mmesa->setup.maccess |= MA_zwidth_16;
1131 break;
1132 case 24:
1133 mmesa->setup.maccess |= MA_zwidth_24;
1134 break;
1135 case 32:
1136 mmesa->setup.maccess |= MA_zwidth_32;
1137 break;
1138 }
1139
1140 mmesa->hw.blend_func = AC_src_one | AC_dst_zero;
1141 mmesa->hw.blend_func_enable = 0;
1142 mmesa->hw.alpha_func = AC_atmode_noacmp | MGA_FIELD( AC_atref, 0x00 );
1143 mmesa->hw.alpha_func_enable = 0;
1144 mmesa->hw.rop = mgarop_NoBLK[ GL_COPY & 0x0f ];
1145 mmesa->hw.zmode = DC_zmode_zlt | DC_atype_zi;
1146 mmesa->hw.stencil = MGA_FIELD( S_sref, 0x00) | MGA_FIELD( S_smsk, 0xff ) |
1147 MGA_FIELD( S_swtmsk, 0xff );
1148 mmesa->hw.stencilctl = SC_smode_salways | SC_sfailop_keep
1149 | SC_szfailop_keep | SC_szpassop_keep;
1150 mmesa->hw.stencil_enable = 0;
1151 mmesa->hw.cull = _CULL_DISABLE;
1152 mmesa->hw.cull_dualtex = _CULL_DISABLE;
1153 mmesa->hw.specen = 0;
1154 mmesa->hw.alpha_sel = AC_alphasel_diffused;
1155
1156 mmesa->setup.dwgctl = (DC_opcod_trap |
1157 DC_linear_xy |
1158 DC_solid_disable |
1159 DC_arzero_disable |
1160 DC_sgnzero_disable |
1161 DC_shftzero_enable |
1162 MGA_FIELD( DC_bop, 0xC ) |
1163 MGA_FIELD( DC_trans, 0x0 ) |
1164 DC_bltmod_bmonolef |
1165 DC_pattern_disable |
1166 DC_transc_disable |
1167 DC_clipdis_disable);
1168
1169 mmesa->setup.plnwt = ~0;
1170 mmesa->setup.alphactrl = (AC_amode_alpha_channel |
1171 AC_astipple_disable |
1172 AC_aten_disable);
1173
1174 mmesa->setup.fogcolor = PACK_COLOR_888((GLubyte)(ctx->Fog.Color[0]*255.0F),
1175 (GLubyte)(ctx->Fog.Color[1]*255.0F),
1176 (GLubyte)(ctx->Fog.Color[2]*255.0F));
1177
1178 mmesa->setup.wflag = 0;
1179 mmesa->setup.tdualstage0 = 0;
1180 mmesa->setup.tdualstage1 = 0;
1181 mmesa->setup.fcol = 0;
1182 mmesa->dirty |= MGA_UPLOAD_CONTEXT;
1183
1184 mmesa->envcolor[0] = 0;
1185 mmesa->envcolor[1] = 0;
1186 }
1187
1188
1189 void mgaDDInitStateFuncs( GLcontext *ctx )
1190 {
1191 ctx->Driver.UpdateState = mgaDDInvalidateState;
1192 ctx->Driver.Enable = mgaDDEnable;
1193 ctx->Driver.LightModelfv = mgaDDLightModelfv;
1194 ctx->Driver.AlphaFunc = mgaDDAlphaFunc;
1195 ctx->Driver.BlendEquationSeparate = mgaDDBlendEquationSeparate;
1196 ctx->Driver.BlendFuncSeparate = mgaDDBlendFuncSeparate;
1197 ctx->Driver.DepthFunc = mgaDDDepthFunc;
1198 ctx->Driver.DepthMask = mgaDDDepthMask;
1199 ctx->Driver.Fogfv = mgaDDFogfv;
1200 ctx->Driver.Scissor = mgaDDScissor;
1201 ctx->Driver.CullFace = mgaDDCullFaceFrontFace;
1202 ctx->Driver.FrontFace = mgaDDCullFaceFrontFace;
1203 ctx->Driver.ColorMask = mgaDDColorMask;
1204
1205 ctx->Driver.DrawBuffer = mgaDDDrawBuffer;
1206 ctx->Driver.ReadBuffer = mgaDDReadBuffer;
1207 ctx->Driver.ClearColor = mgaDDClearColor;
1208 ctx->Driver.ClearDepth = mgaDDClearDepth;
1209 ctx->Driver.LogicOpcode = mgaDDLogicOp;
1210
1211 ctx->Driver.PolygonStipple = mgaDDPolygonStipple;
1212
1213 ctx->Driver.StencilFuncSeparate = mgaDDStencilFuncSeparate;
1214 ctx->Driver.StencilMaskSeparate = mgaDDStencilMaskSeparate;
1215 ctx->Driver.StencilOpSeparate = mgaDDStencilOpSeparate;
1216
1217 ctx->Driver.DepthRange = mgaDepthRange;
1218 ctx->Driver.Viewport = mgaViewport;
1219 ctx->Driver.RenderMode = mgaRenderMode;
1220
1221 ctx->Driver.ClearIndex = 0;
1222 ctx->Driver.IndexMask = 0;
1223
1224 /* Swrast hooks for imaging extensions:
1225 */
1226 ctx->Driver.CopyColorTable = _swrast_CopyColorTable;
1227 ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable;
1228 ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
1229 ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
1230
1231 TNL_CONTEXT(ctx)->Driver.RunPipeline = mgaRunPipeline;
1232 }