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