Fix PPC DFS/UTS by using PCIgart.
[nouveau] / src / nv10_exa.c
1 /*
2  * Copyright 2007 Stephane Marchesin
3  * Copyright 2007 Arthur Huillet
4  * Copyright 2007 Peter Winters
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the 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 NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
21  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include "nv_include.h"
30
31 typedef struct nv10_exa_state {
32         Bool have_mask;
33         Bool is_a8_plus_a8; /*as known as is_extremely_dirty :)*/
34         struct {
35                 PictTransformPtr transform;
36                 float width;
37                 float height;
38         } unit[2];
39 } nv10_exa_state_t;
40 static nv10_exa_state_t state;
41
42 static int NV10TexFormat(int ExaFormat)
43 {
44         struct {int exa;int hw;} tex_format[] =
45         {
46                 {PICT_a8r8g8b8, 0x900},
47                 {PICT_x8r8g8b8, 0x900},
48                 {PICT_r5g6b5, 0x880}, /*this one was only tested with rendercheck*/
49                 /*{PICT_a1r5g5b5,       NV10TCL_TX_FORMAT_FORMAT_R5G5B5A1},
50                 {PICT_a4r4g4b4, NV10TCL_TX_FORMAT_FORMAT_R4G4B4A4},*/
51                 {PICT_a8,       0x980}, /*this is a NV1x only format, corresponding NV2x is 0xD80, we hack it in below*/
52         };
53
54         int i;
55         for(i=0;i<sizeof(tex_format)/sizeof(tex_format[0]);i++)
56         {
57                 if(tex_format[i].exa==ExaFormat)
58                         return tex_format[i].hw;
59         }
60
61         return 0;
62 }
63
64 static int NV10DstFormat(int ExaFormat)
65 {
66         struct {int exa;int hw;} dst_format[] =
67         {
68                 {PICT_a8r8g8b8, 0x108},
69                 {PICT_x8r8g8b8, 0x108},
70                 {PICT_r5g6b5,   0x103}
71         };
72
73         int i;
74         for(i=0;i<sizeof(dst_format)/sizeof(dst_format[0]);i++)
75         {
76                 if(dst_format[i].exa==ExaFormat)
77                         return dst_format[i].hw;
78         }
79
80         return 0;
81 }
82
83 static Bool NV10CheckTexture(PicturePtr Picture)
84 {
85         int w = Picture->pDrawable->width;
86         int h = Picture->pDrawable->height;
87
88         if ((w > 2046) || (h>2046))
89                 return FALSE;
90         if (!NV10TexFormat(Picture->format))
91                 return FALSE;
92         if (Picture->filter != PictFilterNearest && Picture->filter != PictFilterBilinear)
93                 return FALSE;
94         if (Picture->componentAlpha)
95                 return FALSE;
96         /* we cannot repeat on NV10 because NPOT textures do not support this. unfortunately. */
97         if (Picture->repeat != RepeatNone)
98                 /* we can repeat 1x1 textures */
99                 if (!(w == 1 && h == 1))
100                         return FALSE;
101         return TRUE;
102 }
103
104 static Bool NV10CheckBuffer(PicturePtr Picture)
105 {
106         int w = Picture->pDrawable->width;
107         int h = Picture->pDrawable->height;
108
109         if ((w > 4096) || (h>4096))
110                 return FALSE;
111         if (Picture->componentAlpha)
112                 return FALSE;
113         if (!NV10DstFormat(Picture->format))
114                 return FALSE;
115         return TRUE;
116 }
117
118 static Bool NV10CheckPictOp(int op)
119 {
120         if ( op == PictOpAtopReverse ) /*this op doesn't work*/
121                 {
122                 return FALSE;
123                 }
124         if ( op >= PictOpSaturate )
125                 { /*we do no saturate, disjoint, conjoint, though we could do e.g. DisjointClear which really is Clear*/
126                 return FALSE;
127                 }
128         return TRUE;
129 }       
130
131 /* Check if the current operation is a doable A8 + A8 */
132 /* A8 destination is a special case, because we do it by having the card think 
133 it's ARGB. For now we support PictOpAdd which is the only important op for this dst format, 
134 and without transformation or funny things.*/
135 static Bool NV10Check_A8plusA8_Feasability(PicturePtr src, PicturePtr msk, PicturePtr dst, int op)  
136 {
137 #if X_BYTE_ORDER == X_BIG_ENDIAN
138     return FALSE;
139 #endif
140     if ((!msk) &&       (src->format == PICT_a8) && (dst->format == PICT_a8) && (!src->transform) && 
141             (op == PictOpAdd) && (src->repeat == RepeatNone))
142         {
143         return TRUE;
144         }
145     return FALSE;
146 }
147
148 #if 0
149 #define NV10EXAFallbackInfo(X,Y,Z,S,T) NV10EXAFallbackInfo_real(X,Y,Z,S,T)
150 #else
151 #define NV10EXAFallbackInfo(X,Y,Z,S,T) do { ; } while (0)
152 #endif
153
154 static void NV10EXAFallbackInfo_real(char * reason, int op, PicturePtr pSrcPicture,
155                              PicturePtr pMaskPicture,
156                              PicturePtr pDstPicture)
157 {
158         char out2[4096];
159         char * out = out2;
160         sprintf(out, "%s  ", reason);
161         out = out + strlen(out);
162         switch ( op )
163                 {
164                 case PictOpClear:
165                         sprintf(out, "PictOpClear ");
166                         break;
167                 case PictOpSrc:
168                         sprintf(out, "PictOpSrc ");
169                         break;
170                 case PictOpDst:
171                         sprintf(out, "PictOpDst ");
172                         break;
173                 case PictOpOver:
174                         sprintf(out, "PictOpOver ");
175                         break;
176                 case PictOpOutReverse:
177                         sprintf(out, "PictOpOutReverse ");
178                         break;
179                 case PictOpAdd:
180                         sprintf(out, "PictOpAdd ");
181                         break;
182                 default :
183                         sprintf(out, "PictOp%d ", op);
184                 }
185         out = out + strlen(out);
186         switch ( pSrcPicture->format )
187                 {
188                 case PICT_a8r8g8b8:
189                         sprintf(out, "A8R8G8B8 ");
190                         break;
191                 case PICT_x8r8g8b8:
192                         sprintf(out, "X8R8G8B8 ");
193                         break;
194                 case PICT_x8b8g8r8:
195                         sprintf(out, "X8B8G8R8 ");
196                         break;
197                 case PICT_r5g6b5:
198                         sprintf(out, "R5G6B5 ");
199                         break;
200                 case PICT_a8:
201                         sprintf(out, "A8 ");
202                         break;
203                 case PICT_a1:
204                         sprintf(out, "A1 ");
205                         break;
206                 default:
207                         sprintf(out, "%x ", pSrcPicture->format);
208                 }
209         out+=strlen(out);
210         sprintf(out, "(%dx%d) ", pSrcPicture->pDrawable->width, pSrcPicture->pDrawable->height);
211         if ( pSrcPicture->repeat != RepeatNone )
212                 strcat(out, "R ");
213         strcat(out, "-> ");
214         out+=strlen(out);
215         
216         switch ( pDstPicture->format )
217                 {
218                 case PICT_a8r8g8b8:
219                         sprintf(out, "A8R8G8B8 ");
220                         break;
221                 case PICT_x8r8g8b8:
222                         sprintf(out, "X8R8G8B8  ");
223                         break;
224                 case PICT_x8b8g8r8:
225                         sprintf(out, "X8B8G8R8  ");
226                         break;
227                 case PICT_r5g6b5:
228                         sprintf(out, "R5G6B5 ");
229                         break;
230                 case PICT_a8:
231                         sprintf(out, "A8  ");
232                         break;
233                 case PICT_a1:
234                         sprintf(out, "A1  ");
235                         break;
236                 default:
237                         sprintf(out, "%x  ", pDstPicture->format);
238                 }
239         out+=strlen(out);
240         sprintf(out, "(%dx%d) ", pDstPicture->pDrawable->width, pDstPicture->pDrawable->height);
241         if ( pDstPicture->repeat != RepeatNone )
242                 strcat(out, "R ");
243         out+=strlen(out);
244         if ( !pMaskPicture ) 
245                 sprintf(out, "& NONE");
246         else {
247         switch ( pMaskPicture->format )
248                 {
249                 case PICT_a8r8g8b8:
250                         sprintf(out, "& A8R8G8B8 ");
251                         break;
252                 case PICT_x8r8g8b8:
253                         sprintf(out, "& X8R8G8B8  ");
254                         break;
255                 case PICT_x8b8g8r8:
256                         sprintf(out, "& X8B8G8R8  ");
257                         break;
258                 case PICT_a8:
259                         sprintf(out, "& A8  ");
260                         break;
261                 case PICT_a1:
262                         sprintf(out, "& A1  ");
263                         break;
264                 default:
265                         sprintf(out, "& %x  ", pMaskPicture->format);
266                 }
267                 out+=strlen(out);
268                 sprintf(out, "(%dx%d) ", pMaskPicture->pDrawable->width, pMaskPicture->pDrawable->height);
269                 if ( pMaskPicture->repeat != RepeatNone )
270                         strcat(out, "R ");
271                 out+=strlen(out);
272         }
273         strcat(out, "\n");
274         xf86DrvMsg(0, X_INFO, out2);
275 }
276
277
278 Bool NV10CheckComposite(int     op,
279                              PicturePtr pSrcPicture,
280                              PicturePtr pMaskPicture,
281                              PicturePtr pDstPicture)
282 {
283         
284         if (NV10Check_A8plusA8_Feasability(pSrcPicture,pMaskPicture,pDstPicture,op))
285                 {
286                 NV10EXAFallbackInfo("Hackelerating", op, pSrcPicture, pMaskPicture, pDstPicture);
287                 return TRUE;
288                 }
289
290         if (!NV10CheckPictOp(op))
291                 {
292                 NV10EXAFallbackInfo("pictop", op, pSrcPicture, pMaskPicture, pDstPicture);
293                 return FALSE;
294                 }
295         if (!NV10CheckBuffer(pDstPicture)) 
296                 {
297                 NV10EXAFallbackInfo("dst", op, pSrcPicture, pMaskPicture, pDstPicture);
298                 return FALSE;
299                 }
300                 
301         if (!NV10CheckTexture(pSrcPicture))
302                 {
303                 NV10EXAFallbackInfo("src", op, pSrcPicture, pMaskPicture, pDstPicture);
304                 return FALSE;
305                 }
306                 
307         if ((pMaskPicture) &&(!NV10CheckTexture(pMaskPicture)))
308                 {
309                 NV10EXAFallbackInfo("mask", op, pSrcPicture, pMaskPicture, pDstPicture);
310                 return FALSE;
311                 }
312                 
313         NV10EXAFallbackInfo("Accelerating", op, pSrcPicture, pMaskPicture, pDstPicture);
314         return TRUE;
315 }
316
317 static void NV10SetTexture(NVPtr pNv,int unit,PicturePtr Pict,PixmapPtr pixmap)
318 {
319         BEGIN_RING(Nv3D, NV10TCL_TX_OFFSET(unit), 1 );
320         OUT_PIXMAPl(pixmap, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
321         int log2w = log2i(Pict->pDrawable->width);
322         int log2h = log2i(Pict->pDrawable->height);
323         int w;
324         unsigned int txfmt =
325                         (NV10TCL_TX_FORMAT_WRAP_T_CLAMP_TO_EDGE) |
326                         (NV10TCL_TX_FORMAT_WRAP_S_CLAMP_TO_EDGE) |
327                         (log2w<<20) |
328                         (log2h<<16) |
329                         (1<<12) | /* lod == 1 */
330                         0x51 /* UNK */;
331
332         /* if repeat is set we're always handling a 1x1 texture with ARGB/XRGB destination, 
333         in that case we change the format       to use the POT (swizzled) matching format */
334         if (Pict->repeat != RepeatNone)
335         {
336                 if (Pict->format == PICT_a8)
337                         txfmt |= 0x80; /* A8 */
338                 else if (Pict->format == PICT_r5g6b5 )
339                         txfmt |= 0x280; /* R5G6B5 */
340                 else
341                         txfmt |= 0x300; /* ARGB format */
342         }
343         else
344         {
345                 if (pNv->Architecture == NV_ARCH_20 && Pict->format == PICT_a8 )
346                         txfmt |= 0xd80;
347                 else txfmt |= NV10TexFormat(Pict->format);
348                 w = Pict->pDrawable->width;
349                 /* NPOT_SIZE expects an even number for width, we can round up uneven
350                 * numbers here because EXA always gives 64 byte aligned pixmaps
351                 * and for all formats we support 64 bytes represents an even number
352                 * of pixels
353                 */
354                 w = (w + 1) &~ 1;
355
356                 BEGIN_RING(Nv3D, NV10TCL_TX_NPOT_PITCH(unit), 1);
357                 OUT_RING  (exaGetPixmapPitch(pixmap) << 16);
358
359                 BEGIN_RING(Nv3D, NV10TCL_TX_NPOT_SIZE(unit), 1);
360                 OUT_RING  ((w<<16) | Pict->pDrawable->height);
361         }
362
363         BEGIN_RING(Nv3D, NV10TCL_TX_FORMAT(unit), 1 );
364         OUT_RING  (txfmt);
365
366         BEGIN_RING(Nv3D, NV10TCL_TX_ENABLE(unit), 1 );
367         OUT_RING  (NV10TCL_TX_ENABLE_ENABLE);
368
369         BEGIN_RING(Nv3D, NV10TCL_TX_FILTER(unit), 1);
370         if (Pict->filter == PictFilterNearest)
371                 OUT_RING  ((NV10TCL_TX_FILTER_MAGNIFY_NEAREST) |
372                                 (NV10TCL_TX_FILTER_MINIFY_NEAREST));
373         else
374                 OUT_RING  ((NV10TCL_TX_FILTER_MAGNIFY_LINEAR) |
375                                 (NV10TCL_TX_FILTER_MINIFY_LINEAR));
376
377         state.unit[unit].width          = (float)pixmap->drawable.width;
378         state.unit[unit].height         = (float)pixmap->drawable.height;
379         state.unit[unit].transform      = Pict->transform;
380 }
381
382 static void NV10SetBuffer(NVPtr pNv,PicturePtr Pict,PixmapPtr pixmap)
383 {
384         int i;
385         int x = 0;
386         int y = 0;
387         int w = 2048;
388         int h = 2048;
389
390         BEGIN_RING(Nv3D, NV10TCL_BUFFER_FORMAT, 4);
391         if ( state.is_a8_plus_a8 )
392                 { /*A8 + A8 hack*/
393                 OUT_RING  (NV10DstFormat(PICT_a8r8g8b8));
394                 }
395         else {
396                 OUT_RING  (NV10DstFormat(Pict->format));
397                 }
398         
399         OUT_RING  (((uint32_t)exaGetPixmapPitch(pixmap) << 16) |(uint32_t)exaGetPixmapPitch(pixmap));
400         OUT_PIXMAPl(pixmap, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
401         OUT_RING  (0);
402                 
403         BEGIN_RING(Nv3D, NV10TCL_VIEWPORT_HORIZ, 2);
404         OUT_RING  ((w<<16)|x);
405         OUT_RING  ((h<<16)|y);
406         BEGIN_RING(Nv3D, NV10TCL_VIEWPORT_CLIP_MODE, 1); /* clip_mode */
407         OUT_RING  (0);
408         BEGIN_RING(Nv3D, NV10TCL_VIEWPORT_CLIP_HORIZ(0), 1);
409         OUT_RING  (((w-1+x)<<16)|x|0x08000800);
410         BEGIN_RING(Nv3D, NV10TCL_VIEWPORT_CLIP_VERT(0), 1);
411         OUT_RING  (((h-1+y)<<16)|y|0x08000800);
412
413         BEGIN_RING(Nv3D, NV10TCL_PROJECTION_MATRIX(0), 16);
414         for(i=0;i<16;i++)
415                 if (i/4==i%4)
416                         OUT_RINGf (1.0f);
417                 else
418                         OUT_RINGf (0.0f);
419
420         BEGIN_RING(Nv3D, NV10TCL_DEPTH_RANGE_NEAR, 2);
421         OUT_RING  (0);
422 #if SCREEN_BPP == 32
423         OUT_RINGf (16777216.0);
424 #else
425         OUT_RINGf (65536.0);
426 #endif
427         BEGIN_RING(Nv3D, NV10TCL_VIEWPORT_SCALE_X, 4);
428         OUT_RINGf (-2048.0);
429         OUT_RINGf (-2048.0);
430         OUT_RINGf (0);
431         OUT_RING  (0);
432 }
433
434 static void NV10SetRegCombs(NVPtr pNv, PicturePtr src, PicturePtr mask)
435 {
436 /*This can be a bit difficult to understand at first glance.
437 Reg combiners are described here:
438 http://icps.u-strasbg.fr/~marchesin/perso/extensions/NV/register_combiners.html
439         
440 Single texturing setup, without honoring vertex colors (non default setup) is:
441 Alpha RC 0 : a_0  * 1 + 0 * 0
442 RGB RC 0 : rgb_0 * 1 + 0 * 0
443 RC 1s are unused
444 Final combiner uses default setup
445         
446 Default setup uses vertex rgb/alpha in place of 1s above, but we don't need that in 2D.
447         
448 Multi texturing setup, where we do TEX0 in TEX1 (masking) is:
449 Alpha RC 0 : a_0 * a_1 + 0 * 0
450 RGB RC0 : rgb_0 * a_1 + 0 * 0
451 RC 1s are unused
452 Final combiner uses default setup
453         
454 */
455
456 unsigned int rc0_in_alpha = 0, rc0_in_rgb = 0;
457 unsigned int rc1_in_alpha = 0, rc1_in_rgb = 0;
458 unsigned int color0 = 0, color1 = 0;
459 #define A_ALPHA_ZERO (NV10TCL_RC_IN_ALPHA_A_INPUT_ZERO | NV10TCL_RC_IN_ALPHA_A_COMPONENT_USAGE_ALPHA)
460 #define B_ALPHA_ZERO (NV10TCL_RC_IN_ALPHA_B_INPUT_ZERO | NV10TCL_RC_IN_ALPHA_B_COMPONENT_USAGE_ALPHA)
461 #define C_ALPHA_ZERO (NV10TCL_RC_IN_ALPHA_C_INPUT_ZERO | NV10TCL_RC_IN_ALPHA_C_COMPONENT_USAGE_ALPHA)
462 #define D_ALPHA_ZERO (NV10TCL_RC_IN_ALPHA_D_INPUT_ZERO | NV10TCL_RC_IN_ALPHA_D_COMPONENT_USAGE_ALPHA)
463         
464 #define A_ALPHA_ONE (A_ALPHA_ZERO | (NV10TCL_RC_IN_ALPHA_A_MAPPING_UNSIGNED_INVERT_NV))
465 #define B_ALPHA_ONE (B_ALPHA_ZERO | (NV10TCL_RC_IN_ALPHA_B_MAPPING_UNSIGNED_INVERT_NV))
466 #define C_ALPHA_ONE (C_ALPHA_ZERO | (NV10TCL_RC_IN_ALPHA_C_MAPPING_UNSIGNED_INVERT_NV))
467 #define D_ALPHA_ONE (D_ALPHA_ZERO | (NV10TCL_RC_IN_ALPHA_D_MAPPING_UNSIGNED_INVERT_NV))
468
469 #define A_RGB_ZERO (NV10TCL_RC_IN_RGB_A_INPUT_ZERO | NV10TCL_RC_IN_RGB_A_COMPONENT_USAGE_RGB)
470 #define B_RGB_ZERO (NV10TCL_RC_IN_RGB_B_INPUT_ZERO | NV10TCL_RC_IN_RGB_B_COMPONENT_USAGE_RGB)
471 #define C_RGB_ZERO (NV10TCL_RC_IN_RGB_C_INPUT_ZERO | NV10TCL_RC_IN_RGB_C_COMPONENT_USAGE_RGB)
472 #define D_RGB_ZERO (NV10TCL_RC_IN_RGB_D_INPUT_ZERO | NV10TCL_RC_IN_RGB_D_COMPONENT_USAGE_RGB)
473
474 #define A_RGB_ONE (A_RGB_ZERO | NV10TCL_RC_IN_RGB_A_MAPPING_UNSIGNED_INVERT_NV)
475 #define B_RGB_ONE (B_RGB_ZERO | NV10TCL_RC_IN_RGB_B_MAPPING_UNSIGNED_INVERT_NV)
476 #define C_RGB_ONE (C_RGB_ZERO | NV10TCL_RC_IN_RGB_C_MAPPING_UNSIGNED_INVERT_NV)
477 #define D_RGB_ONE (D_RGB_ZERO | NV10TCL_RC_IN_RGB_D_MAPPING_UNSIGNED_INVERT_NV)
478
479         rc0_in_alpha |= C_ALPHA_ZERO | D_ALPHA_ZERO;
480         if (src->format == PICT_x8r8g8b8)
481                 rc0_in_alpha |= A_ALPHA_ONE;
482         else
483                 rc0_in_alpha |= 0x18000000;
484
485         if ( ! mask ) 
486                 rc0_in_alpha |= B_ALPHA_ONE;
487         else 
488                 if ( mask->format == PICT_x8r8g8b8 )  /*no alpha? ignore it*/
489                         rc0_in_alpha |= B_ALPHA_ONE;
490                 else
491                         rc0_in_alpha |= 0x00190000; /*B = a_1*/
492
493         rc0_in_rgb |=  C_RGB_ZERO | D_RGB_ZERO;
494         if (src->format == PICT_a8 )
495                 rc0_in_rgb |= A_RGB_ZERO;
496         else 
497                 rc0_in_rgb |= 0x08000000; /*A = rgb_0*/
498
499         if ( ! mask )
500                 rc0_in_rgb |= B_RGB_ONE;
501         else 
502                 if (  mask->format == PICT_x8r8g8b8 )  /*no alpha? ignore it*/
503                         rc0_in_rgb |= B_RGB_ONE;
504                 else
505                         rc0_in_rgb |= 0x00190000; /*B = a_1*/
506                 
507         BEGIN_RING(Nv3D, NV10TCL_RC_IN_ALPHA(0), 6);
508         OUT_RING(rc0_in_alpha);
509         OUT_RING  (rc1_in_alpha);
510         OUT_RING (rc0_in_rgb);
511         OUT_RING  (rc1_in_rgb);
512         OUT_RING  (color0); /*COLOR 0*/
513         OUT_RING  (color1); /*COLOR 1*/
514 }
515
516 static void NV10SetRegCombs_A8plusA8(NVPtr pNv, int pass, int mask_out_bytes)
517 {
518         unsigned int rc0_in_alpha = 0, rc0_in_rgb = 0;
519         unsigned int rc1_in_alpha = 0, rc1_in_rgb = 0;
520         unsigned int color0 = 0, color1 = 0;
521
522         if ( pass == 1)
523                 {
524                 if ( mask_out_bytes & 1 )
525                         rc0_in_alpha = A_ALPHA_ZERO | B_ALPHA_ZERO | C_ALPHA_ZERO | D_ALPHA_ZERO;
526                 else rc0_in_alpha = 0x19000000 | B_ALPHA_ONE | C_ALPHA_ZERO | D_ALPHA_ZERO;
527                 
528                 rc0_in_rgb = C_RGB_ZERO | D_RGB_ZERO;
529                 
530                 if ( mask_out_bytes & 2 )
531                         rc0_in_rgb |= A_RGB_ZERO | B_RGB_ZERO;
532                 else rc0_in_rgb |= 0x18000000 | 0x00010000;
533                 
534                 color0 = 0x00ff0000; /*R = 1 G = 0 B = 0*/
535                 }
536         else {
537                 rc0_in_alpha = A_ALPHA_ZERO | B_ALPHA_ZERO | C_ALPHA_ZERO | D_ALPHA_ZERO;
538                 
539                 rc0_in_rgb = 0;
540                 
541                 
542                 
543                 if ( mask_out_bytes & 8 )
544                         rc0_in_rgb |= A_RGB_ZERO | B_RGB_ZERO;
545                 else  rc0_in_rgb |= 0x18000000 | 0x00010000; /*A = a_0, B= cst color 0*/
546                 
547                 color0 = 0x000000ff; 
548                 
549                 if ( mask_out_bytes & 4)
550                         rc0_in_rgb |= C_RGB_ZERO | D_RGB_ZERO;
551                 else rc0_in_rgb |= 0x1900 | 0x02; /*C = a_1, D = cst color 1*/
552                         
553                 color1 = 0x0000ff00; /*R = 0, G = 1, B = 0*/
554                 }
555
556         BEGIN_RING(Nv3D, NV10TCL_RC_IN_ALPHA(0), 6);
557         OUT_RING(rc0_in_alpha);
558         OUT_RING  (rc1_in_alpha);
559         OUT_RING (rc0_in_rgb);
560         OUT_RING  (rc1_in_rgb);
561         OUT_RING  (color0); /*COLOR 0*/
562         OUT_RING  (color1); /*COLOR 1*/
563 }
564
565 static void NV10SetPictOp(NVPtr pNv,int op)
566 {
567         struct {int src;int dst;} pictops[] =
568         {
569                 {0x0000,0x0000}, /* PictOpClear */
570                 {0x0001,0x0000}, /* PictOpSrc */
571                 {0x0000,0x0001}, /* PictOpDst */
572                 {0x0001,0x0303}, /* PictOpOver */
573                 {0x0305,0x0001}, /* PictOpOverReverse */
574                 {0x0304,0x0000}, /* PictOpIn */
575                 {0x0000,0x0302}, /* PictOpInReverse */
576                 {0x0305,0x0000}, /* PictOpOut */
577                 {0x0000,0x0303}, /* PictOpOutReverse */
578                 {0x0304,0x0303}, /* PictOpAtop */
579                 {0x0305,0x0302}, /* PictOpAtopReverse - DOES NOT WORK*/
580                 {0x0305,0x0303}, /* PictOpXor */
581                 {0x0001,0x0001}, /* PictOpAdd */
582         };
583         
584         BEGIN_RING(Nv3D, NV10TCL_BLEND_FUNC_SRC, 2);
585         OUT_RING  (pictops[op].src);
586         OUT_RING  (pictops[op].dst);
587         BEGIN_RING(Nv3D, NV10TCL_BLEND_FUNC_ENABLE, 1);
588         OUT_RING  (1);
589 }
590
591 Bool NV10PrepareComposite(int     op,
592                                PicturePtr pSrcPicture,
593                                PicturePtr pMaskPicture,
594                                PicturePtr pDstPicture,
595                                PixmapPtr  pSrc,
596                                PixmapPtr  pMask,
597                                PixmapPtr  pDst)
598 {
599         ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
600         NVPtr pNv = NVPTR(pScrn);
601
602         if (NV10Check_A8plusA8_Feasability(pSrcPicture,pMaskPicture,pDstPicture,op))
603                 {
604                 state.have_mask = FALSE;
605                 state.is_a8_plus_a8 = TRUE;
606                 NV10SetBuffer(pNv,pDstPicture,pDst);
607                 NV10SetPictOp(pNv, op);
608                 NV10SetTexture(pNv, 0, pSrcPicture, pSrc);
609                 NV10SetTexture(pNv, 1, pSrcPicture, pSrc);
610                 return TRUE;
611                 }
612         
613         state.is_a8_plus_a8 = FALSE;
614                 
615         /* Set dst format */
616         NV10SetBuffer(pNv,pDstPicture,pDst);
617
618         /* Set src format */
619         NV10SetTexture(pNv,0,pSrcPicture,pSrc);
620
621         /* Set mask format */
622         if (pMaskPicture)
623                 NV10SetTexture(pNv,1,pMaskPicture,pMask);
624
625         NV10SetRegCombs(pNv, pSrcPicture, pMaskPicture);
626
627         /* Set PictOp */
628         NV10SetPictOp(pNv, op);
629
630         BEGIN_RING(Nv3D, NV10TCL_VERTEX_BEGIN_END, 1);
631         OUT_RING  (NV10TCL_VERTEX_BEGIN_END_QUADS);
632
633         state.have_mask=(pMaskPicture!=NULL);
634         return TRUE;
635 }
636
637 static inline void NV10Vertex(NVPtr pNv,float vx,float vy,float tx,float ty)
638 {
639         BEGIN_RING(Nv3D, NV10TCL_VERTEX_TX0_2F_S, 2);
640         OUT_RINGf (tx);
641         OUT_RINGf (ty);
642         BEGIN_RING(Nv3D, NV10TCL_VERTEX_POS_3F_X, 3);
643         OUT_RINGf (vx);
644         OUT_RINGf (vy);
645         OUT_RINGf (0.f);
646 }
647
648 static inline void NV10MVertex(NVPtr pNv,float vx,float vy,float t0x,float t0y,float t1x,float t1y)
649 {
650         BEGIN_RING(Nv3D, NV10TCL_VERTEX_TX0_2F_S, 2);
651         OUT_RINGf (t0x);
652         OUT_RINGf (t0y);
653         BEGIN_RING(Nv3D, NV10TCL_VERTEX_TX1_2F_S, 2);
654         OUT_RINGf (t1x);
655         OUT_RINGf (t1y);
656         BEGIN_RING(Nv3D, NV10TCL_VERTEX_POS_3F_X, 3);
657         OUT_RINGf (vx);
658         OUT_RINGf (vy);
659         OUT_RINGf (0.f);
660 }
661
662 #define xFixedToFloat(v) \
663         ((float)xFixedToInt((v)) + ((float)xFixedFrac(v) / 65536.0))
664
665 static void
666 NV10EXATransformCoord(PictTransformPtr t, int x, int y, float sx, float sy,
667                                           float *x_ret, float *y_ret)
668 {
669         PictVector v;
670
671         if (t) {
672                 v.vector[0] = IntToxFixed(x);
673                 v.vector[1] = IntToxFixed(y);
674                 v.vector[2] = xFixed1;
675                 PictureTransformPoint(t, &v);
676                 *x_ret = xFixedToFloat(v.vector[0]);
677                 *y_ret = xFixedToFloat(v.vector[1]);
678         } else {
679                 *x_ret = (float)x;
680                 *y_ret = (float)y;
681         }
682 }
683
684
685 void NV10Composite(PixmapPtr pDst,
686                         int       srcX,
687                         int       srcY,
688                         int       maskX,
689                         int       maskY,
690                         int       dstX,
691                         int       dstY,
692                         int       width,
693                         int       height)
694 {
695         ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
696         NVPtr pNv = NVPTR(pScrn);
697         float sX0, sX1, sX2, sY0, sY1, sY2, sX3, sY3;
698         float mX0, mX1, mX2, mY0, mY1, mY2, mX3, mY3;
699
700         NV10EXATransformCoord(state.unit[0].transform, srcX, srcY,
701                               state.unit[0].width,
702                               state.unit[0].height, &sX0, &sY0);
703         NV10EXATransformCoord(state.unit[0].transform,
704                               srcX + width, srcY,
705                               state.unit[0].width,
706                               state.unit[0].height, &sX1, &sY1);
707         NV10EXATransformCoord(state.unit[0].transform,
708                               srcX + width, srcY + height,
709                               state.unit[0].width,
710                               state.unit[0].height, &sX2, &sY2);
711         NV10EXATransformCoord(state.unit[0].transform,
712                               srcX, srcY + height,
713                               state.unit[0].width,
714                               state.unit[0].height, &sX3, &sY3);
715
716         if ( state.is_a8_plus_a8 )
717                 {
718                 /*We do A8 + A8 in 2-pass : setup the source texture as A8 twice, 
719                         with different tex coords, do B and G on first pass
720                 Then setup again and do R and A on second pass
721                 */
722                 int part_pos_dX = 0;
723                 int part_pos_sX = 0;
724                 int mask_out_bytes = 0;
725                 
726                 part_pos_dX = (dstX &~ 3) >> 2; /*we start at the 4byte boundary to the left of the image*/
727                 part_pos_sX = sX0 + (dstX &~ 3) - dstX; 
728
729                 /*xf86DrvMsg(0, X_INFO, "drawing - srcX %f dstX %d w %d\n", sX0, dstX, width);*/
730                 for ( ; part_pos_dX <= (((dstX + width) &~ 3) >> 2); part_pos_sX += 4, part_pos_dX ++ )
731                         {
732                         mask_out_bytes = 0;
733                         if ( part_pos_dX == (dstX &~ 3) >> 2  ) /*then we're slightly on the left of the image, bytes to mask out*/
734                                 {
735                                 /*xf86DrvMsg(0, X_INFO, "on left border...\n");*/
736                                 switch ( dstX - (dstX &~ 3) ) /*mask out the extra pixels on the left*/
737                                         {
738                                         case 4: 
739                                                 mask_out_bytes |= 1 << 0;
740                                         case 3: 
741                                                 mask_out_bytes |= 1 << 1;
742                                         case 2:
743                                                 mask_out_bytes |= 1 << 2;
744                                         case 1: 
745                                                 mask_out_bytes |= 1 << 3;
746                                         case 0:
747                                                 break;
748                                         }
749                                         
750                                 /*mask out extra pixels on the right, in case the picture never touches an alignment marker*/
751                                 switch ( width + (dstX & 3) )
752                                         {
753                                         case 0:
754                                                 mask_out_bytes |= 1 << 3;
755                                         case 1:
756                                                 mask_out_bytes |= 1 << 2;
757                                         case 2:
758                                                 mask_out_bytes |= 1 << 1;
759                                         case 3:
760                                                 mask_out_bytes |= 1 << 0;
761                                         default : break;
762                                         }
763                                 }
764                         else if ( part_pos_dX == (((dstX + width) &~ 3) >> 2) ) 
765                                 {
766                                 /*xf86DrvMsg(0, X_INFO, "on right border...\n");*/
767                                 switch (4 - ((dstX + width) & 3))
768                                         {
769                                         case 4:
770                                                 mask_out_bytes |= 1 << 3;
771                                         case 3: 
772                                                 mask_out_bytes |= 1 << 2;
773                                         case 2: 
774                                                 mask_out_bytes |= 1 << 1;
775                                         case 1:
776                                                 mask_out_bytes |= 1 << 0;
777                                         case 0:
778                                                 break;
779                                         }
780                                 }
781                                 
782                         /*Pass number 0*/
783                         
784                         NV10SetRegCombs_A8plusA8(pNv, 0, mask_out_bytes);
785                         BEGIN_RING(Nv3D, NV10TCL_VERTEX_BEGIN_END, 1);
786                         OUT_RING  (NV10TCL_VERTEX_BEGIN_END_QUADS);             
787                                         
788                         NV10MVertex(pNv , part_pos_dX   , dstY              , part_pos_sX, sY0, part_pos_sX + 1, sY0);
789                         NV10MVertex(pNv , part_pos_dX + 1, dstY              , part_pos_sX, sY0, part_pos_sX + 1, sY0);
790                         NV10MVertex(pNv , part_pos_dX + 1, dstY + height, part_pos_sX,  sY2, part_pos_sX + 1, sY2);
791                         NV10MVertex(pNv , part_pos_dX   , dstY + height, part_pos_sX, sY2, part_pos_sX + 1, sY2);
792                         
793                         BEGIN_RING(Nv3D, NV10TCL_VERTEX_BEGIN_END, 1);
794                         OUT_RING  (NV10TCL_VERTEX_BEGIN_END_STOP);
795                         
796                         /*Pass number 1*/
797                         
798                         NV10SetRegCombs_A8plusA8(pNv, 1, mask_out_bytes);
799                         BEGIN_RING(Nv3D, NV10TCL_VERTEX_BEGIN_END, 1);
800                         OUT_RING  (NV10TCL_VERTEX_BEGIN_END_QUADS);             
801                                         
802                         NV10MVertex(pNv , part_pos_dX, dstY              , part_pos_sX + 2, sY0, part_pos_sX + 3, sY0);
803                         NV10MVertex(pNv , part_pos_dX + 1 , dstY              , part_pos_sX + 2, sY0, part_pos_sX + 3, sY0);
804                         NV10MVertex(pNv , part_pos_dX + 1 , dstY + height, part_pos_sX + 2, sY2, part_pos_sX + 3, sY2);
805                         NV10MVertex(pNv , part_pos_dX, dstY + height, part_pos_sX + 2, sY2, part_pos_sX + 3, sY2);
806
807                         BEGIN_RING(Nv3D, NV10TCL_VERTEX_BEGIN_END, 1);
808                         OUT_RING  (NV10TCL_VERTEX_BEGIN_END_STOP);
809                         
810                         }
811                 }
812         else if (state.have_mask) {
813                 NV10EXATransformCoord(state.unit[1].transform, maskX, maskY,
814                                       state.unit[1].width,
815                                       state.unit[1].height, &mX0, &mY0);
816                 NV10EXATransformCoord(state.unit[1].transform,
817                                       maskX + width, maskY,
818                                       state.unit[1].width,
819                                       state.unit[1].height, &mX1, &mY1);
820                 NV10EXATransformCoord(state.unit[1].transform,
821                                       maskX + width, maskY + height,
822                                       state.unit[1].width,
823                                       state.unit[1].height, &mX2, &mY2);
824                 NV10EXATransformCoord(state.unit[1].transform,
825                                       maskX, maskY + height,
826                                       state.unit[1].width,
827                                       state.unit[1].height, &mX3, &mY3);
828                 NV10MVertex(pNv , dstX         ,          dstY,sX0 , sY0 , mX0 , mY0);
829                 NV10MVertex(pNv , dstX + width ,          dstY,sX1 , sY1 , mX1 , mY1);
830                 NV10MVertex(pNv , dstX + width , dstY + height,sX2 , sY2 , mX2 , mY2);
831                 NV10MVertex(pNv , dstX         , dstY + height,sX3 , sY3 , mX3 , mY3);
832         } else {
833                 NV10Vertex(pNv , dstX         ,          dstY , sX0 , sY0);
834                 NV10Vertex(pNv , dstX + width ,          dstY , sX1 , sY1);
835                 NV10Vertex(pNv , dstX + width , dstY + height , sX2 , sY2);
836                 NV10Vertex(pNv , dstX         , dstY + height , sX3 , sY3);
837         }
838
839         FIRE_RING();
840 }
841
842 void NV10DoneComposite (PixmapPtr pDst)
843 {
844         ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
845         NVPtr pNv = NVPTR(pScrn);
846
847         BEGIN_RING(Nv3D, NV10TCL_VERTEX_BEGIN_END, 1);
848         OUT_RING  (NV10TCL_VERTEX_BEGIN_END_STOP);
849
850         exaMarkSync(pDst->drawable.pScreen);
851 }
852
853
854 Bool
855 NVAccelInitNV10TCL(ScrnInfoPtr pScrn)
856 {
857         NVPtr pNv = NVPTR(pScrn);
858         uint32_t class = 0, chipset;
859         int i;
860
861         chipset = (nvReadMC(pNv, 0) >> 20) & 0xff;
862         if (    ((chipset & 0xf0) != NV_ARCH_10) &&
863                 ((chipset & 0xf0) != NV_ARCH_20) )
864                 return FALSE;
865
866         if (chipset>=0x20)
867                 class = NV11TCL;
868         else if (chipset>=0x17)
869                 class = NV17TCL;
870         else if (chipset>=0x11)
871                 class = NV11TCL;
872         else
873                 class = NV10TCL;
874
875         if (!pNv->Nv3D) {
876                 if (nouveau_grobj_alloc(pNv->chan, Nv3D, class, &pNv->Nv3D))
877                         return FALSE;
878         }
879
880         BEGIN_RING(Nv3D, NV10TCL_DMA_NOTIFY, 1);
881         OUT_RING  (pNv->NvNull->handle);
882
883         BEGIN_RING(Nv3D, NV10TCL_DMA_IN_MEMORY0, 2);
884         OUT_RING  (pNv->chan->vram->handle);
885         OUT_RING  (pNv->chan->gart->handle);
886
887         BEGIN_RING(Nv3D, NV10TCL_DMA_IN_MEMORY2, 2);
888         OUT_RING  (pNv->chan->vram->handle);
889         OUT_RING  (pNv->chan->vram->handle);
890
891         BEGIN_RING(Nv3D, NV10TCL_NOP, 1);
892         OUT_RING  (0);
893
894         BEGIN_RING(Nv3D, NV10TCL_VIEWPORT_HORIZ, 2);
895         OUT_RING  (0);
896         OUT_RING  (0);
897
898         BEGIN_RING(Nv3D, NV10TCL_VIEWPORT_CLIP_HORIZ(0), 1);
899         OUT_RING  ((0x7ff<<16)|0x800);
900         BEGIN_RING(Nv3D, NV10TCL_VIEWPORT_CLIP_VERT(0), 1);
901         OUT_RING  ((0x7ff<<16)|0x800);
902
903         for (i=1;i<8;i++) {
904                 BEGIN_RING(Nv3D, NV10TCL_VIEWPORT_CLIP_HORIZ(i), 1);
905                 OUT_RING  (0);
906                 BEGIN_RING(Nv3D, NV10TCL_VIEWPORT_CLIP_VERT(i), 1);
907                 OUT_RING  (0);
908         }
909
910         BEGIN_RING(Nv3D, 0x290, 1);
911         OUT_RING  ((0x10<<16)|1);
912         BEGIN_RING(Nv3D, 0x3f4, 1);
913         OUT_RING  (0);
914
915         BEGIN_RING(Nv3D, NV10TCL_NOP, 1);
916         OUT_RING  (0);
917
918         if (class != NV10TCL) {
919                 /* For nv11, nv17 */
920                 BEGIN_RING(Nv3D, 0x120, 3);
921                 OUT_RING  (0);
922                 OUT_RING  (1);
923                 OUT_RING  (2);
924
925                 BEGIN_RING(NvImageBlit, 0x120, 3);
926                 OUT_RING  (0);
927                 OUT_RING  (1);
928                 OUT_RING  (2);
929
930                 BEGIN_RING(Nv3D, NV10TCL_NOP, 1);
931                 OUT_RING  (0);
932         }
933
934         BEGIN_RING(Nv3D, NV10TCL_NOP, 1);
935         OUT_RING  (0);
936
937         /* Set state */
938         BEGIN_RING(Nv3D, NV10TCL_FOG_ENABLE, 1);
939         OUT_RING  (0);
940         BEGIN_RING(Nv3D, NV10TCL_ALPHA_FUNC_ENABLE, 1);
941         OUT_RING  (0);
942         BEGIN_RING(Nv3D, NV10TCL_ALPHA_FUNC_FUNC, 2);
943         OUT_RING  (0x207);
944         OUT_RING  (0);
945         BEGIN_RING(Nv3D, NV10TCL_TX_ENABLE(0), 2);
946         OUT_RING  (0);
947         OUT_RING  (0);
948         BEGIN_RING(Nv3D, NV10TCL_RC_OUT_ALPHA(0), 6);
949         OUT_RING  (0x00000c00);
950         OUT_RING  (0);
951         OUT_RING  (0x00000c00);
952         OUT_RING  (0x18000000);
953         OUT_RING  (0x300c0000);
954         OUT_RING  (0x00001c80);
955         BEGIN_RING(Nv3D, NV10TCL_BLEND_FUNC_ENABLE, 1);
956         OUT_RING  (0);
957         BEGIN_RING(Nv3D, NV10TCL_DITHER_ENABLE, 2);
958         OUT_RING  (1);
959         OUT_RING  (0);
960         BEGIN_RING(Nv3D, NV10TCL_LINE_SMOOTH_ENABLE, 1);
961         OUT_RING  (0);
962         BEGIN_RING(Nv3D, NV10TCL_VERTEX_WEIGHT_ENABLE, 2);
963         OUT_RING  (0);
964         OUT_RING  (0);
965         BEGIN_RING(Nv3D, NV10TCL_BLEND_FUNC_SRC, 4);
966         OUT_RING  (1);
967         OUT_RING  (0);
968         OUT_RING  (0);
969         OUT_RING  (0x8006);
970         BEGIN_RING(Nv3D, NV10TCL_STENCIL_MASK, 8);
971         OUT_RING  (0xff);
972         OUT_RING  (0x207);
973         OUT_RING  (0);
974         OUT_RING  (0xff);
975         OUT_RING  (0x1e00);
976         OUT_RING  (0x1e00);
977         OUT_RING  (0x1e00);
978         OUT_RING  (0x1d01);
979         BEGIN_RING(Nv3D, NV10TCL_NORMALIZE_ENABLE, 1);
980         OUT_RING  (0);
981         BEGIN_RING(Nv3D, NV10TCL_FOG_ENABLE, 2);
982         OUT_RING  (0);
983         OUT_RING  (0);
984         BEGIN_RING(Nv3D, NV10TCL_LIGHT_MODEL, 1);
985         OUT_RING  (0);
986         BEGIN_RING(Nv3D, NV10TCL_COLOR_CONTROL, 1);
987         OUT_RING  (0);
988         BEGIN_RING(Nv3D, NV10TCL_ENABLED_LIGHTS, 1);
989         OUT_RING  (0);
990         BEGIN_RING(Nv3D, NV10TCL_POLYGON_OFFSET_POINT_ENABLE, 3);
991         OUT_RING  (0);
992         OUT_RING  (0);
993         OUT_RING  (0);
994         BEGIN_RING(Nv3D, NV10TCL_DEPTH_FUNC, 1);
995         OUT_RING  (0x201);
996         BEGIN_RING(Nv3D, NV10TCL_DEPTH_WRITE_ENABLE, 1);
997         OUT_RING  (0);
998         BEGIN_RING(Nv3D, NV10TCL_DEPTH_TEST_ENABLE, 1);
999         OUT_RING  (0);
1000         BEGIN_RING(Nv3D, NV10TCL_POLYGON_OFFSET_FACTOR, 2);
1001         OUT_RING  (0);
1002         OUT_RING  (0);
1003         BEGIN_RING(Nv3D, NV10TCL_POINT_SIZE, 1);
1004         OUT_RING  (8);
1005         BEGIN_RING(Nv3D, NV10TCL_POINT_PARAMETERS_ENABLE, 2);
1006         OUT_RING  (0);
1007         OUT_RING  (0);
1008         BEGIN_RING(Nv3D, NV10TCL_LINE_WIDTH, 1);
1009         OUT_RING  (8);
1010         BEGIN_RING(Nv3D, NV10TCL_LINE_SMOOTH_ENABLE, 1);
1011         OUT_RING  (0);
1012         BEGIN_RING(Nv3D, NV10TCL_POLYGON_MODE_FRONT, 2);
1013         OUT_RING  (0x1b02);
1014         OUT_RING  (0x1b02);
1015         BEGIN_RING(Nv3D, NV10TCL_CULL_FACE, 2);
1016         OUT_RING  (0x405);
1017         OUT_RING  (0x901);
1018         BEGIN_RING(Nv3D, NV10TCL_POLYGON_SMOOTH_ENABLE, 1);
1019         OUT_RING  (0);
1020         BEGIN_RING(Nv3D, NV10TCL_CULL_FACE_ENABLE, 1);
1021         OUT_RING  (0);
1022         BEGIN_RING(Nv3D, NV10TCL_CLIP_PLANE_ENABLE(0), 8);
1023         for (i=0;i<8;i++) {
1024                 OUT_RING  (0);
1025         }
1026         BEGIN_RING(Nv3D, NV10TCL_FOG_EQUATION_CONSTANT, 3);
1027         OUT_RING  (0x3fc00000); /* -1.50 */
1028         OUT_RING  (0xbdb8aa0a); /* -0.09 */
1029         OUT_RING  (0);          /*  0.00 */
1030
1031         BEGIN_RING(Nv3D, NV10TCL_NOP, 1);
1032         OUT_RING  (0);
1033
1034         BEGIN_RING(Nv3D, NV10TCL_FOG_MODE, 2);
1035         OUT_RING  (0x802);
1036         OUT_RING  (2);
1037         /* for some reason VIEW_MATRIX_ENABLE need to be 6 instead of 4 when
1038          * using texturing, except when using the texture matrix
1039          */
1040         BEGIN_RING(Nv3D, NV10TCL_VIEW_MATRIX_ENABLE, 1);
1041         OUT_RING  (6);
1042         BEGIN_RING(Nv3D, NV10TCL_COLOR_MASK, 1);
1043         OUT_RING  (0x01010101);
1044
1045         /* Set vertex component */
1046         BEGIN_RING(Nv3D, NV10TCL_VERTEX_COL_4F_R, 4);
1047         OUT_RINGf (1.0);
1048         OUT_RINGf (1.0);
1049         OUT_RINGf (1.0);
1050         OUT_RINGf (1.0);
1051         BEGIN_RING(Nv3D, NV10TCL_VERTEX_COL2_3F_R, 3);
1052         OUT_RING  (0);
1053         OUT_RING  (0);
1054         OUT_RING  (0);
1055         BEGIN_RING(Nv3D, NV10TCL_VERTEX_NOR_3F_X, 3);
1056         OUT_RING  (0);
1057         OUT_RING  (0);
1058         OUT_RINGf (1.0);
1059         BEGIN_RING(Nv3D, NV10TCL_VERTEX_TX0_4F_S, 4);
1060         OUT_RINGf (0.0);
1061         OUT_RINGf (0.0);
1062         OUT_RINGf (0.0);
1063         OUT_RINGf (1.0);
1064         BEGIN_RING(Nv3D, NV10TCL_VERTEX_TX1_4F_S, 4);
1065         OUT_RINGf (0.0);
1066         OUT_RINGf (0.0);
1067         OUT_RINGf (0.0);
1068         OUT_RINGf (1.0);
1069         BEGIN_RING(Nv3D, NV10TCL_VERTEX_FOG_1F, 1);
1070         OUT_RINGf (0.0);
1071         BEGIN_RING(Nv3D, NV10TCL_EDGEFLAG_ENABLE, 1);
1072         OUT_RING  (1);
1073
1074         return TRUE;
1075 }
1076
1077
1078
1079