NV10 EXA: use the proper variable
[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,       NV10_TCL_PRIMITIVE_3D_TX_FORMAT_FORMAT_R5G5B5A1},
50                 {PICT_a4r4g4b4, NV10_TCL_PRIMITIVE_3D_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 ((!msk) &&   (src->format == PICT_a8) && (dst->format == PICT_a8) && (!src->transform) && 
138                                                                         (op == PictOpAdd) && (src->repeat == RepeatNone))
139                 {
140                 return TRUE;
141                 }
142         return FALSE;
143 }
144
145 #if 0
146 #define NV10EXAFallbackInfo(X,Y,Z,S,T) NV10EXAFallbackInfo_real(X,Y,Z,S,T)
147 #else
148 #define NV10EXAFallbackInfo(X,Y,Z,S,T) do { ; } while (0)
149 #endif
150
151 static void NV10EXAFallbackInfo_real(char * reason, int op, PicturePtr pSrcPicture,
152                              PicturePtr pMaskPicture,
153                              PicturePtr pDstPicture)
154 {
155         char out2[4096];
156         char * out = out2;
157         sprintf(out, "%s  ", reason);
158         out = out + strlen(out);
159         switch ( op )
160                 {
161                 case PictOpClear:
162                         sprintf(out, "PictOpClear ");
163                         break;
164                 case PictOpSrc:
165                         sprintf(out, "PictOpSrc ");
166                         break;
167                 case PictOpDst:
168                         sprintf(out, "PictOpDst ");
169                         break;
170                 case PictOpOver:
171                         sprintf(out, "PictOpOver ");
172                         break;
173                 case PictOpOutReverse:
174                         sprintf(out, "PictOpOutReverse ");
175                         break;
176                 case PictOpAdd:
177                         sprintf(out, "PictOpAdd ");
178                         break;
179                 default :
180                         sprintf(out, "PictOp%d ", op);
181                 }
182         out = out + strlen(out);
183         switch ( pSrcPicture->format )
184                 {
185                 case PICT_a8r8g8b8:
186                         sprintf(out, "A8R8G8B8 ");
187                         break;
188                 case PICT_x8r8g8b8:
189                         sprintf(out, "X8R8G8B8 ");
190                         break;
191                 case PICT_x8b8g8r8:
192                         sprintf(out, "X8B8G8R8 ");
193                         break;
194                 case PICT_r5g6b5:
195                         sprintf(out, "R5G6B5 ");
196                         break;
197                 case PICT_a8:
198                         sprintf(out, "A8 ");
199                         break;
200                 case PICT_a1:
201                         sprintf(out, "A1 ");
202                         break;
203                 default:
204                         sprintf(out, "%x ", pSrcPicture->format);
205                 }
206         out+=strlen(out);
207         sprintf(out, "(%dx%d) ", pSrcPicture->pDrawable->width, pSrcPicture->pDrawable->height);
208         if ( pSrcPicture->repeat != RepeatNone )
209                 strcat(out, "R ");
210         strcat(out, "-> ");
211         out+=strlen(out);
212         
213         switch ( pDstPicture->format )
214                 {
215                 case PICT_a8r8g8b8:
216                         sprintf(out, "A8R8G8B8 ");
217                         break;
218                 case PICT_x8r8g8b8:
219                         sprintf(out, "X8R8G8B8  ");
220                         break;
221                 case PICT_x8b8g8r8:
222                         sprintf(out, "X8B8G8R8  ");
223                         break;
224                 case PICT_r5g6b5:
225                         sprintf(out, "R5G6B5 ");
226                         break;
227                 case PICT_a8:
228                         sprintf(out, "A8  ");
229                         break;
230                 case PICT_a1:
231                         sprintf(out, "A1  ");
232                         break;
233                 default:
234                         sprintf(out, "%x  ", pDstPicture->format);
235                 }
236         out+=strlen(out);
237         sprintf(out, "(%dx%d) ", pDstPicture->pDrawable->width, pDstPicture->pDrawable->height);
238         if ( pDstPicture->repeat != RepeatNone )
239                 strcat(out, "R ");
240         out+=strlen(out);
241         if ( !pMaskPicture ) 
242                 sprintf(out, "& NONE");
243         else {
244         switch ( pMaskPicture->format )
245                 {
246                 case PICT_a8r8g8b8:
247                         sprintf(out, "& A8R8G8B8 ");
248                         break;
249                 case PICT_x8r8g8b8:
250                         sprintf(out, "& X8R8G8B8  ");
251                         break;
252                 case PICT_x8b8g8r8:
253                         sprintf(out, "& X8B8G8R8  ");
254                         break;
255                 case PICT_a8:
256                         sprintf(out, "& A8  ");
257                         break;
258                 case PICT_a1:
259                         sprintf(out, "& A1  ");
260                         break;
261                 default:
262                         sprintf(out, "& %x  ", pMaskPicture->format);
263                 }
264                 out+=strlen(out);
265                 sprintf(out, "(%dx%d) ", pMaskPicture->pDrawable->width, pMaskPicture->pDrawable->height);
266                 if ( pMaskPicture->repeat != RepeatNone )
267                         strcat(out, "R ");
268                 out+=strlen(out);
269         }
270         strcat(out, "\n");
271         xf86DrvMsg(0, X_INFO, out2);
272 }
273
274
275 Bool NV10CheckComposite(int     op,
276                              PicturePtr pSrcPicture,
277                              PicturePtr pMaskPicture,
278                              PicturePtr pDstPicture)
279 {
280         
281         if (NV10Check_A8plusA8_Feasability(pSrcPicture,pMaskPicture,pDstPicture,op))
282                 {
283                 NV10EXAFallbackInfo("Hackelerating", op, pSrcPicture, pMaskPicture, pDstPicture);
284                 return TRUE;
285                 }
286
287         if (!NV10CheckPictOp(op))
288                 {
289                 NV10EXAFallbackInfo("pictop", op, pSrcPicture, pMaskPicture, pDstPicture);
290                 return FALSE;
291                 }
292         if (!NV10CheckBuffer(pDstPicture)) 
293                 {
294                 NV10EXAFallbackInfo("dst", op, pSrcPicture, pMaskPicture, pDstPicture);
295                 return FALSE;
296                 }
297                 
298         if (!NV10CheckTexture(pSrcPicture))
299                 {
300                 NV10EXAFallbackInfo("src", op, pSrcPicture, pMaskPicture, pDstPicture);
301                 return FALSE;
302                 }
303                 
304         if ((pMaskPicture) &&(!NV10CheckTexture(pMaskPicture)))
305                 {
306                 NV10EXAFallbackInfo("mask", op, pSrcPicture, pMaskPicture, pDstPicture);
307                 return FALSE;
308                 }
309                 
310         NV10EXAFallbackInfo("Accelerating", op, pSrcPicture, pMaskPicture, pDstPicture);
311         return TRUE;
312 }
313
314 static void NV10SetTexture(NVPtr pNv,int unit,PicturePtr Pict,PixmapPtr pixmap)
315 {
316         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_TX_OFFSET(unit), 1 );
317         OUT_PIXMAPl(pixmap, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
318         int log2w = log2i(Pict->pDrawable->width);
319         int log2h = log2i(Pict->pDrawable->height);
320         int w;
321         unsigned int txfmt =
322                         (NV10_TCL_PRIMITIVE_3D_TX_FORMAT_WRAP_T_CLAMP_TO_EDGE) |
323                         (NV10_TCL_PRIMITIVE_3D_TX_FORMAT_WRAP_S_CLAMP_TO_EDGE) |
324                         (log2w<<20) |
325                         (log2h<<16) |
326                         (1<<12) | /* lod == 1 */
327                         0x51 /* UNK */;
328
329         /* if repeat is set we're always handling a 1x1 texture with ARGB/XRGB destination, 
330         in that case we change the format       to use the POT (swizzled) matching format */
331         if (Pict->repeat != RepeatNone)
332         {
333                 if (Pict->format == PICT_a8)
334                         txfmt |= 0x80; /* A8 */
335                 else if (Pict->format == PICT_r5g6b5 )
336                         txfmt |= 0x280; /* R5G6B5 */
337                 else
338                         txfmt |= 0x300; /* ARGB format */
339         }
340         else
341         {
342                 if (pNv->Architecture == NV_ARCH_20 && Pict->format == PICT_a8 )
343                         txfmt |= 0xd80;
344                 else txfmt |= NV10TexFormat(Pict->format);
345                 w = Pict->pDrawable->width;
346                 /* NPOT_SIZE expects an even number for width, we can round up uneven
347                 * numbers here because EXA always gives 64 byte aligned pixmaps
348                 * and for all formats we support 64 bytes represents an even number
349                 * of pixels
350                 */
351                 w = (w + 1) &~ 1;
352
353                 BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_TX_NPOT_PITCH(unit), 1);
354                 OUT_RING  (exaGetPixmapPitch(pixmap) << 16);
355
356                 BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_TX_NPOT_SIZE(unit), 1);
357                 OUT_RING  ((w<<16) | Pict->pDrawable->height);
358         }
359
360         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_TX_FORMAT(unit), 1 );
361         OUT_RING  (txfmt);
362
363         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_TX_ENABLE(unit), 1 );
364         OUT_RING  (NV10_TCL_PRIMITIVE_3D_TX_ENABLE_ENABLE);
365
366         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_TX_FILTER(unit), 1);
367         if (Pict->filter == PictFilterNearest)
368                 OUT_RING  ((NV10_TCL_PRIMITIVE_3D_TX_FILTER_MAGNIFY_NEAREST) |
369                                 (NV10_TCL_PRIMITIVE_3D_TX_FILTER_MINIFY_NEAREST));
370         else
371                 OUT_RING  ((NV10_TCL_PRIMITIVE_3D_TX_FILTER_MAGNIFY_LINEAR) |
372                                 (NV10_TCL_PRIMITIVE_3D_TX_FILTER_MINIFY_LINEAR));
373
374         state.unit[unit].width          = (float)pixmap->drawable.width;
375         state.unit[unit].height         = (float)pixmap->drawable.height;
376         state.unit[unit].transform      = Pict->transform;
377 }
378
379 static void NV10SetBuffer(NVPtr pNv,PicturePtr Pict,PixmapPtr pixmap)
380 {
381         int i;
382         int x = 0;
383         int y = 0;
384         int w = 2048;
385         int h = 2048;
386
387         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_BUFFER_FORMAT, 4);
388         if ( state.is_a8_plus_a8 )
389                 { /*A8 + A8 hack*/
390                 OUT_RING  (NV10DstFormat(PICT_a8r8g8b8));
391                 }
392         else {
393                 OUT_RING  (NV10DstFormat(Pict->format));
394                 }
395         
396         OUT_RING  (((uint32_t)exaGetPixmapPitch(pixmap) << 16) |(uint32_t)exaGetPixmapPitch(pixmap));
397         OUT_PIXMAPl(pixmap, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
398         OUT_RING  (0);
399                 
400         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VIEWPORT_HORIZ, 2);
401         OUT_RING  ((w<<16)|x);
402         OUT_RING  ((h<<16)|y);
403         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_MODE, 1); /* clip_mode */
404         OUT_RING  (0);
405         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_HORIZ(0), 1);
406         OUT_RING  (((w-1+x)<<16)|x|0x08000800);
407         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_VERT(0), 1);
408         OUT_RING  (((h-1+y)<<16)|y|0x08000800);
409
410         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_PROJECTION_MATRIX(0), 16);
411         for(i=0;i<16;i++)
412                 if (i/4==i%4)
413                         OUT_RINGf (1.0f);
414                 else
415                         OUT_RINGf (0.0f);
416
417         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_DEPTH_RANGE_NEAR, 2);
418         OUT_RING  (0);
419 #if SCREEN_BPP == 32
420         OUT_RINGf (16777216.0);
421 #else
422         OUT_RINGf (65536.0);
423 #endif
424         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VIEWPORT_SCALE_X, 4);
425         OUT_RINGf (-2048.0);
426         OUT_RINGf (-2048.0);
427         OUT_RINGf (0);
428         OUT_RING  (0);
429 }
430
431 static void NV10SetRegCombs(NVPtr pNv, PicturePtr src, PicturePtr mask)
432 {
433 /*This can be a bit difficult to understand at first glance.
434 Reg combiners are described here:
435 http://icps.u-strasbg.fr/~marchesin/perso/extensions/NV/register_combiners.html
436         
437 Single texturing setup, without honoring vertex colors (non default setup) is:
438 Alpha RC 0 : a_0  * 1 + 0 * 0
439 RGB RC 0 : rgb_0 * 1 + 0 * 0
440 RC 1s are unused
441 Final combiner uses default setup
442         
443 Default setup uses vertex rgb/alpha in place of 1s above, but we don't need that in 2D.
444         
445 Multi texturing setup, where we do TEX0 in TEX1 (masking) is:
446 Alpha RC 0 : a_0 * a_1 + 0 * 0
447 RGB RC0 : rgb_0 * a_1 + 0 * 0
448 RC 1s are unused
449 Final combiner uses default setup
450         
451 */
452
453 unsigned int rc0_in_alpha = 0, rc0_in_rgb = 0;
454 unsigned int rc1_in_alpha = 0, rc1_in_rgb = 0;
455 unsigned int color0 = 0, color1 = 0;
456 #define A_ALPHA_ZERO (NV10_TCL_PRIMITIVE_3D_RC_IN_ALPHA_A_INPUT_ZERO | NV10_TCL_PRIMITIVE_3D_RC_IN_ALPHA_A_COMPONENT_USAGE_ALPHA)
457 #define B_ALPHA_ZERO (NV10_TCL_PRIMITIVE_3D_RC_IN_ALPHA_B_INPUT_ZERO | NV10_TCL_PRIMITIVE_3D_RC_IN_ALPHA_B_COMPONENT_USAGE_ALPHA)
458 #define C_ALPHA_ZERO (NV10_TCL_PRIMITIVE_3D_RC_IN_ALPHA_C_INPUT_ZERO | NV10_TCL_PRIMITIVE_3D_RC_IN_ALPHA_C_COMPONENT_USAGE_ALPHA)
459 #define D_ALPHA_ZERO (NV10_TCL_PRIMITIVE_3D_RC_IN_ALPHA_D_INPUT_ZERO | NV10_TCL_PRIMITIVE_3D_RC_IN_ALPHA_D_COMPONENT_USAGE_ALPHA)
460         
461 #define A_ALPHA_ONE (A_ALPHA_ZERO | (NV10_TCL_PRIMITIVE_3D_RC_IN_ALPHA_A_MAPPING_UNSIGNED_INVERT_NV))
462 #define B_ALPHA_ONE (B_ALPHA_ZERO | (NV10_TCL_PRIMITIVE_3D_RC_IN_ALPHA_B_MAPPING_UNSIGNED_INVERT_NV))
463 #define C_ALPHA_ONE (C_ALPHA_ZERO | (NV10_TCL_PRIMITIVE_3D_RC_IN_ALPHA_C_MAPPING_UNSIGNED_INVERT_NV))
464 #define D_ALPHA_ONE (D_ALPHA_ZERO | (NV10_TCL_PRIMITIVE_3D_RC_IN_ALPHA_D_MAPPING_UNSIGNED_INVERT_NV))
465
466 #define A_RGB_ZERO (NV10_TCL_PRIMITIVE_3D_RC_IN_RGB_A_INPUT_ZERO | NV10_TCL_PRIMITIVE_3D_RC_IN_RGB_A_COMPONENT_USAGE_RGB)
467 #define B_RGB_ZERO (NV10_TCL_PRIMITIVE_3D_RC_IN_RGB_B_INPUT_ZERO | NV10_TCL_PRIMITIVE_3D_RC_IN_RGB_B_COMPONENT_USAGE_RGB)
468 #define C_RGB_ZERO (NV10_TCL_PRIMITIVE_3D_RC_IN_RGB_C_INPUT_ZERO | NV10_TCL_PRIMITIVE_3D_RC_IN_RGB_C_COMPONENT_USAGE_RGB)
469 #define D_RGB_ZERO (NV10_TCL_PRIMITIVE_3D_RC_IN_RGB_D_INPUT_ZERO | NV10_TCL_PRIMITIVE_3D_RC_IN_RGB_D_COMPONENT_USAGE_RGB)
470
471 #define A_RGB_ONE (A_RGB_ZERO | NV10_TCL_PRIMITIVE_3D_RC_IN_RGB_A_MAPPING_UNSIGNED_INVERT_NV)
472 #define B_RGB_ONE (B_RGB_ZERO | NV10_TCL_PRIMITIVE_3D_RC_IN_RGB_B_MAPPING_UNSIGNED_INVERT_NV)
473 #define C_RGB_ONE (C_RGB_ZERO | NV10_TCL_PRIMITIVE_3D_RC_IN_RGB_C_MAPPING_UNSIGNED_INVERT_NV)
474 #define D_RGB_ONE (D_RGB_ZERO | NV10_TCL_PRIMITIVE_3D_RC_IN_RGB_D_MAPPING_UNSIGNED_INVERT_NV)
475
476         rc0_in_alpha |= C_ALPHA_ZERO | D_ALPHA_ZERO;
477         if (src->format == PICT_x8r8g8b8)
478                 rc0_in_alpha |= A_ALPHA_ONE;
479         else
480                 rc0_in_alpha |= 0x18000000;
481
482         if ( ! mask ) 
483                 rc0_in_alpha |= B_ALPHA_ONE;
484         else 
485                 if ( mask->format == PICT_x8r8g8b8 )  /*no alpha? ignore it*/
486                         rc0_in_alpha |= B_ALPHA_ONE;
487                 else
488                         rc0_in_alpha |= 0x00190000; /*B = a_1*/
489
490         rc0_in_rgb |=  C_RGB_ZERO | D_RGB_ZERO;
491         if (src->format == PICT_a8 )
492                 rc0_in_rgb |= A_RGB_ZERO;
493         else 
494                 rc0_in_rgb |= 0x08000000; /*A = rgb_0*/
495
496         if ( ! mask )
497                 rc0_in_rgb |= B_RGB_ONE;
498         else 
499                 if (  mask->format == PICT_x8r8g8b8 )  /*no alpha? ignore it*/
500                         rc0_in_rgb |= B_RGB_ONE;
501                 else
502                         rc0_in_rgb |= 0x00190000; /*B = a_1*/
503                 
504         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_RC_IN_ALPHA(0), 12);
505         OUT_RING(rc0_in_alpha);
506         OUT_RING  (rc1_in_alpha);
507         OUT_RING (rc0_in_rgb);
508         OUT_RING  (rc1_in_rgb);
509         OUT_RING  (color0); /*COLOR 0*/
510         OUT_RING  (color1); /*COLOR 1*/
511         OUT_RING  (0x00000c00);
512         OUT_RING  (0);
513         OUT_RING  (0x000010cd);
514         OUT_RING  (0x18000000);
515         OUT_RING  (0x300e0300);
516         OUT_RING  (0x0c091c80);
517 }
518
519 static void NV10SetRegCombs_A8plusA8(NVPtr pNv, int pass, int mask_out_bytes)
520 {
521         unsigned int rc0_in_alpha = 0, rc0_in_rgb = 0;
522         unsigned int rc1_in_alpha = 0, rc1_in_rgb = 0;
523         unsigned int color0 = 0, color1 = 0;
524
525         if ( pass == 1)
526                 {
527                 if ( mask_out_bytes & 1 )
528                         rc0_in_alpha = A_ALPHA_ZERO | B_ALPHA_ZERO | C_ALPHA_ZERO | D_ALPHA_ZERO;
529                 else rc0_in_alpha = 0x19000000 | B_ALPHA_ONE | C_ALPHA_ZERO | D_ALPHA_ZERO;
530                 
531                 rc0_in_rgb = C_RGB_ZERO | D_RGB_ZERO;
532                 
533                 if ( mask_out_bytes & 2 )
534                         rc0_in_rgb |= A_RGB_ZERO | B_RGB_ZERO;
535                 else rc0_in_rgb |= 0x18000000 | 0x00010000;
536                 
537                 color0 = 0x00ff0000; /*R = 1 G = 0 B = 0*/
538                 }
539         else {
540                 rc0_in_alpha = A_ALPHA_ZERO | B_ALPHA_ZERO | C_ALPHA_ZERO | D_ALPHA_ZERO;
541                 
542                 rc0_in_rgb = 0;
543                 
544                 
545                 
546                 if ( mask_out_bytes & 8 )
547                         rc0_in_rgb |= A_RGB_ZERO | B_RGB_ZERO;
548                 else  rc0_in_rgb |= 0x18000000 | 0x00010000; /*A = a_0, B= cst color 0*/
549                 
550                 color0 = 0x000000ff; 
551                 
552                 if ( mask_out_bytes & 4)
553                         rc0_in_rgb |= C_RGB_ZERO | D_RGB_ZERO;
554                 else rc0_in_rgb |= 0x1900 | 0x02; /*C = a_1, D = cst color 1*/
555                         
556                 color1 = 0x0000ff00; /*R = 0, G = 1, B = 0*/
557                 }
558
559         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_RC_IN_ALPHA(0), 12);
560         OUT_RING(rc0_in_alpha);
561         OUT_RING  (rc1_in_alpha);
562         OUT_RING (rc0_in_rgb);
563         OUT_RING  (rc1_in_rgb);
564         OUT_RING  (color0); /*COLOR 0*/
565         OUT_RING  (color1); /*COLOR 1*/
566         OUT_RING  (0x00000c00);
567         OUT_RING  (0);
568         OUT_RING  (0x00000c00);
569         OUT_RING  (0x18000000);
570         OUT_RING  (0x300c0000);
571         OUT_RING  (0x00001c80);
572 }
573
574 static void NV10SetPictOp(NVPtr pNv,int op)
575 {
576         struct {int src;int dst;} pictops[] =
577         {
578                 {0x0000,0x0000}, /* PictOpClear */
579                 {0x0001,0x0000}, /* PictOpSrc */
580                 {0x0000,0x0001}, /* PictOpDst */
581                 {0x0001,0x0303}, /* PictOpOver */
582                 {0x0305,0x0001}, /* PictOpOverReverse */
583                 {0x0304,0x0000}, /* PictOpIn */
584                 {0x0000,0x0302}, /* PictOpInReverse */
585                 {0x0305,0x0000}, /* PictOpOut */
586                 {0x0000,0x0303}, /* PictOpOutReverse */
587                 {0x0304,0x0303}, /* PictOpAtop */
588                 {0x0305,0x0302}, /* PictOpAtopReverse - DOES NOT WORK*/
589                 {0x0305,0x0303}, /* PictOpXor */
590                 {0x0001,0x0001}, /* PictOpAdd */
591         };
592         
593         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_BLEND_FUNC_SRC, 2);
594         OUT_RING  (pictops[op].src);
595         OUT_RING  (pictops[op].dst);
596         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_BLEND_FUNC_ENABLE, 1);
597         OUT_RING  (1);
598 }
599
600 Bool NV10PrepareComposite(int     op,
601                                PicturePtr pSrcPicture,
602                                PicturePtr pMaskPicture,
603                                PicturePtr pDstPicture,
604                                PixmapPtr  pSrc,
605                                PixmapPtr  pMask,
606                                PixmapPtr  pDst)
607 {
608         ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
609         NVPtr pNv = NVPTR(pScrn);
610
611         if (NV10Check_A8plusA8_Feasability(pSrcPicture,pMaskPicture,pDstPicture,op))
612                 {
613                 state.have_mask = FALSE;
614                 state.is_a8_plus_a8 = TRUE;
615                 NV10SetBuffer(pNv,pDstPicture,pDst);
616                 NV10SetPictOp(pNv, op);
617                 NV10SetTexture(pNv, 0, pSrcPicture, pSrc);
618                 NV10SetTexture(pNv, 1, pSrcPicture, pSrc);
619                 return TRUE;
620                 }
621         
622         state.is_a8_plus_a8 = FALSE;
623                 
624         /* Set dst format */
625         NV10SetBuffer(pNv,pDstPicture,pDst);
626
627         /* Set src format */
628         NV10SetTexture(pNv,0,pSrcPicture,pSrc);
629
630         /* Set mask format */
631         if (pMaskPicture)
632                 NV10SetTexture(pNv,1,pMaskPicture,pMask);
633
634         NV10SetRegCombs(pNv, pSrcPicture, pMaskPicture);
635
636         /* Set PictOp */
637         NV10SetPictOp(pNv, op);
638
639         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_BEGIN_END, 1);
640         OUT_RING  (NV10_TCL_PRIMITIVE_3D_VERTEX_BEGIN_END_QUADS);
641
642         state.have_mask=(pMaskPicture!=NULL);
643         return TRUE;
644 }
645
646 static inline void NV10Vertex(NVPtr pNv,float vx,float vy,float tx,float ty)
647 {
648         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_TX0_2F_S, 2);
649         OUT_RINGf (tx);
650         OUT_RINGf (ty);
651         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_POS_3F_X, 3);
652         OUT_RINGf (vx);
653         OUT_RINGf (vy);
654         OUT_RINGf (0.f);
655 }
656
657 static inline void NV10MVertex(NVPtr pNv,float vx,float vy,float t0x,float t0y,float t1x,float t1y)
658 {
659         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_TX0_2F_S, 2);
660         OUT_RINGf (t0x);
661         OUT_RINGf (t0y);
662         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_TX1_2F_S, 2);
663         OUT_RINGf (t1x);
664         OUT_RINGf (t1y);
665         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_POS_3F_X, 3);
666         OUT_RINGf (vx);
667         OUT_RINGf (vy);
668         OUT_RINGf (0.f);
669 }
670
671 #define xFixedToFloat(v) \
672         ((float)xFixedToInt((v)) + ((float)xFixedFrac(v) / 65536.0))
673
674 static void
675 NV10EXATransformCoord(PictTransformPtr t, int x, int y, float sx, float sy,
676                                           float *x_ret, float *y_ret)
677 {
678         PictVector v;
679
680         if (t) {
681                 v.vector[0] = IntToxFixed(x);
682                 v.vector[1] = IntToxFixed(y);
683                 v.vector[2] = xFixed1;
684                 PictureTransformPoint(t, &v);
685                 *x_ret = xFixedToFloat(v.vector[0]);
686                 *y_ret = xFixedToFloat(v.vector[1]);
687         } else {
688                 *x_ret = (float)x;
689                 *y_ret = (float)y;
690         }
691 }
692
693
694 void NV10Composite(PixmapPtr pDst,
695                         int       srcX,
696                         int       srcY,
697                         int       maskX,
698                         int       maskY,
699                         int       dstX,
700                         int       dstY,
701                         int       width,
702                         int       height)
703 {
704         ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
705         NVPtr pNv = NVPTR(pScrn);
706         float sX0, sX1, sX2, sY0, sY1, sY2, sX3, sY3;
707         float mX0, mX1, mX2, mY0, mY1, mY2, mX3, mY3;
708
709         NV10EXATransformCoord(state.unit[0].transform, srcX, srcY,
710                               state.unit[0].width,
711                               state.unit[0].height, &sX0, &sY0);
712         NV10EXATransformCoord(state.unit[0].transform,
713                               srcX + width, srcY,
714                               state.unit[0].width,
715                               state.unit[0].height, &sX1, &sY1);
716         NV10EXATransformCoord(state.unit[0].transform,
717                               srcX + width, srcY + height,
718                               state.unit[0].width,
719                               state.unit[0].height, &sX2, &sY2);
720         NV10EXATransformCoord(state.unit[0].transform,
721                               srcX, srcY + height,
722                               state.unit[0].width,
723                               state.unit[0].height, &sX3, &sY3);
724
725         if ( state.is_a8_plus_a8 )
726                 {
727                 /*We do A8 + A8 in 2-pass : setup the source texture as A8 twice, 
728                         with different tex coords, do B and G on first pass
729                 Then setup again and do R and A on second pass
730                 */
731                 int part_pos_dX = 0;
732                 int part_pos_sX = 0;
733                 int mask_out_bytes = 0;
734                 
735                 part_pos_dX = (dstX &~ 3) >> 2; /*we start at the 4byte boundary to the left of the image*/
736                 part_pos_sX = sX0 + (dstX &~ 3) - dstX; 
737
738                 /*xf86DrvMsg(0, X_INFO, "drawing - srcX %f dstX %d w %d\n", sX0, dstX, width);*/
739                 for ( ; part_pos_dX <= (((dstX + width) &~ 3) >> 2); part_pos_sX += 4, part_pos_dX ++ )
740                         {
741                         mask_out_bytes = 0;
742                         if ( part_pos_dX == (dstX &~ 3) >> 2  ) /*then we're slightly on the left of the image, bytes to mask out*/
743                                 {
744                                 /*xf86DrvMsg(0, X_INFO, "on left border...\n");*/
745                                 switch ( dstX - (dstX &~ 3) ) /*mask out the extra pixels on the left*/
746                                         {
747                                         case 4: 
748                                                 mask_out_bytes |= 1 << 0;
749                                         case 3: 
750                                                 mask_out_bytes |= 1 << 1;
751                                         case 2:
752                                                 mask_out_bytes |= 1 << 2;
753                                         case 1: 
754                                                 mask_out_bytes |= 1 << 3;
755                                         case 0:
756                                                 break;
757                                         }
758                                         
759                                 /*mask out extra pixels on the right, in case the picture never touches an alignment marker*/
760                                 switch ( width + (dstX & 3) )
761                                         {
762                                         case 0:
763                                                 mask_out_bytes |= 1 << 3;
764                                         case 1:
765                                                 mask_out_bytes |= 1 << 2;
766                                         case 2:
767                                                 mask_out_bytes |= 1 << 1;
768                                         case 3:
769                                                 mask_out_bytes |= 1 << 0;
770                                         default : break;
771                                         }
772                                 }
773                         else if ( part_pos_dX == (((dstX + width) &~ 3) >> 2) ) 
774                                 {
775                                 /*xf86DrvMsg(0, X_INFO, "on right border...\n");*/
776                                 switch (4 - ((dstX + width) & 3))
777                                         {
778                                         case 4:
779                                                 mask_out_bytes |= 1 << 3;
780                                         case 3: 
781                                                 mask_out_bytes |= 1 << 2;
782                                         case 2: 
783                                                 mask_out_bytes |= 1 << 1;
784                                         case 1:
785                                                 mask_out_bytes |= 1 << 0;
786                                         case 0:
787                                                 break;
788                                         }
789                                 }
790                                 
791                         /*Pass number 0*/
792                         
793                         NV10SetRegCombs_A8plusA8(pNv, 0, mask_out_bytes);
794                         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_BEGIN_END, 1);
795                         OUT_RING  (NV10_TCL_PRIMITIVE_3D_VERTEX_BEGIN_END_QUADS);               
796                                         
797                         NV10MVertex(pNv , part_pos_dX   , dstY              , part_pos_sX, sY0, part_pos_sX + 1, sY0);
798                         NV10MVertex(pNv , part_pos_dX + 1, dstY              , part_pos_sX, sY0, part_pos_sX + 1, sY0);
799                         NV10MVertex(pNv , part_pos_dX + 1, dstY + height, part_pos_sX,  sY2, part_pos_sX + 1, sY2);
800                         NV10MVertex(pNv , part_pos_dX   , dstY + height, part_pos_sX, sY2, part_pos_sX + 1, sY2);
801                         
802                         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_BEGIN_END, 1);
803                         OUT_RING  (NV10_TCL_PRIMITIVE_3D_VERTEX_BEGIN_END_STOP);
804                         
805                         /*Pass number 1*/
806                         
807                         NV10SetRegCombs_A8plusA8(pNv, 1, mask_out_bytes);
808                         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_BEGIN_END, 1);
809                         OUT_RING  (NV10_TCL_PRIMITIVE_3D_VERTEX_BEGIN_END_QUADS);               
810                                         
811                         NV10MVertex(pNv , part_pos_dX, dstY              , part_pos_sX + 2, sY0, part_pos_sX + 3, sY0);
812                         NV10MVertex(pNv , part_pos_dX + 1 , dstY              , part_pos_sX + 2, sY0, part_pos_sX + 3, sY0);
813                         NV10MVertex(pNv , part_pos_dX + 1 , dstY + height, part_pos_sX + 2, sY2, part_pos_sX + 3, sY2);
814                         NV10MVertex(pNv , part_pos_dX, dstY + height, part_pos_sX + 2, sY2, part_pos_sX + 3, sY2);
815
816                         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_BEGIN_END, 1);
817                         OUT_RING  (NV10_TCL_PRIMITIVE_3D_VERTEX_BEGIN_END_STOP);
818                         
819                         }
820                 }
821
822         if (state.have_mask) {
823                 NV10EXATransformCoord(state.unit[1].transform, maskX, maskY,
824                                       state.unit[1].width,
825                                       state.unit[1].height, &mX0, &mY0);
826                 NV10EXATransformCoord(state.unit[1].transform,
827                                       maskX + width, maskY,
828                                       state.unit[1].width,
829                                       state.unit[1].height, &mX1, &mY1);
830                 NV10EXATransformCoord(state.unit[1].transform,
831                                       maskX + width, maskY + height,
832                                       state.unit[1].width,
833                                       state.unit[1].height, &mX2, &mY2);
834                 NV10EXATransformCoord(state.unit[1].transform,
835                                       maskX, maskY + height,
836                                       state.unit[1].width,
837                                       state.unit[1].height, &mX3, &mY3);
838                 NV10MVertex(pNv , dstX         ,          dstY,sX0 , sY0 , mX0 , mY0);
839                 NV10MVertex(pNv , dstX + width ,          dstY,sX1 , sY1 , mX1 , mY1);
840                 NV10MVertex(pNv , dstX + width , dstY + height,sX2 , sY2 , mX2 , mY2);
841                 NV10MVertex(pNv , dstX         , dstY + height,sX3 , sY3 , mX3 , mY3);
842         } else {
843                 NV10Vertex(pNv , dstX         ,          dstY , sX0 , sY0);
844                 NV10Vertex(pNv , dstX + width ,          dstY , sX1 , sY1);
845                 NV10Vertex(pNv , dstX + width , dstY + height , sX2 , sY2);
846                 NV10Vertex(pNv , dstX         , dstY + height , sX3 , sY3);
847         }
848
849         FIRE_RING();
850 }
851
852 void NV10DoneComposite (PixmapPtr pDst)
853 {
854         ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
855         NVPtr pNv = NVPTR(pScrn);
856
857         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_BEGIN_END, 1);
858         OUT_RING  (NV10_TCL_PRIMITIVE_3D_VERTEX_BEGIN_END_STOP);
859
860         exaMarkSync(pDst->drawable.pScreen);
861 }
862
863
864 Bool
865 NVAccelInitNV10TCL(ScrnInfoPtr pScrn)
866 {
867         NVPtr pNv = NVPTR(pScrn);
868         uint32_t class = 0, chipset;
869         int i;
870
871         chipset = (nvReadMC(pNv, 0) >> 20) & 0xff;
872         if (    ((chipset & 0xf0) != NV_ARCH_10) &&
873                 ((chipset & 0xf0) != NV_ARCH_20) )
874                 return FALSE;
875
876         if (chipset>=0x20)
877                 class = NV11_TCL_PRIMITIVE_3D;
878         else if (chipset>=0x17)
879                 class = NV17_TCL_PRIMITIVE_3D;
880         else if (chipset>=0x11)
881                 class = NV11_TCL_PRIMITIVE_3D;
882         else
883                 class = NV10_TCL_PRIMITIVE_3D;
884
885         if (!pNv->Nv3D) {
886                 if (nouveau_grobj_alloc(pNv->chan, Nv3D, class, &pNv->Nv3D))
887                         return FALSE;
888         }
889
890         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_DMA_NOTIFY, 1);
891         OUT_RING  (pNv->NvNull->handle);
892
893         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_DMA_IN_MEMORY0, 2);
894         OUT_RING  (pNv->chan->vram->handle);
895         OUT_RING  (pNv->chan->gart->handle);
896
897         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_DMA_IN_MEMORY2, 2);
898         OUT_RING  (pNv->chan->vram->handle);
899         OUT_RING  (pNv->chan->vram->handle);
900
901         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_NOP, 1);
902         OUT_RING  (0);
903
904         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VIEWPORT_HORIZ, 2);
905         OUT_RING  (0);
906         OUT_RING  (0);
907
908         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_HORIZ(0), 1);
909         OUT_RING  ((0x7ff<<16)|0x800);
910         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_VERT(0), 1);
911         OUT_RING  ((0x7ff<<16)|0x800);
912
913         for (i=1;i<8;i++) {
914                 BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_HORIZ(i), 1);
915                 OUT_RING  (0);
916                 BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_VERT(i), 1);
917                 OUT_RING  (0);
918         }
919
920         BEGIN_RING(Nv3D, 0x290, 1);
921         OUT_RING  ((0x10<<16)|1);
922         BEGIN_RING(Nv3D, 0x3f4, 1);
923         OUT_RING  (0);
924
925         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_NOP, 1);
926         OUT_RING  (0);
927
928         if (class != NV10_TCL_PRIMITIVE_3D) {
929                 /* For nv11, nv17 */
930                 BEGIN_RING(Nv3D, 0x120, 3);
931                 OUT_RING  (0);
932                 OUT_RING  (1);
933                 OUT_RING  (2);
934
935                 BEGIN_RING(NvImageBlit, 0x120, 3);
936                 OUT_RING  (0);
937                 OUT_RING  (1);
938                 OUT_RING  (2);
939
940                 BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_NOP, 1);
941                 OUT_RING  (0);
942         }
943
944         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_NOP, 1);
945         OUT_RING  (0);
946
947         /* Set state */
948         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_FOG_ENABLE, 1);
949         OUT_RING  (0);
950         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_ALPHA_FUNC_ENABLE, 1);
951         OUT_RING  (0);
952         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_ALPHA_FUNC_FUNC, 2);
953         OUT_RING  (0x207);
954         OUT_RING  (0);
955         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_TX_ENABLE(0), 2);
956         OUT_RING  (0);
957         OUT_RING  (0);
958         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_RC_IN_ALPHA(0), 12);
959         OUT_RING  (0x30141010);
960         OUT_RING  (0);
961         OUT_RING  (0x20040000);
962         OUT_RING  (0);
963         OUT_RING  (0);
964         OUT_RING  (0);
965         OUT_RING  (0x00000c00);
966         OUT_RING  (0);
967         OUT_RING  (0x00000c00);
968         OUT_RING  (0x18000000);
969         OUT_RING  (0x300e0300);
970         OUT_RING  (0x0c091c80);
971         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_BLEND_FUNC_ENABLE, 1);
972         OUT_RING  (0);
973         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_DITHER_ENABLE, 2);
974         OUT_RING  (1);
975         OUT_RING  (0);
976         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_LINE_SMOOTH_ENABLE, 1);
977         OUT_RING  (0);
978         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_WEIGHT_ENABLE, 2);
979         OUT_RING  (0);
980         OUT_RING  (0);
981         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_BLEND_FUNC_SRC, 4);
982         OUT_RING  (1);
983         OUT_RING  (0);
984         OUT_RING  (0);
985         OUT_RING  (0x8006);
986         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_STENCIL_MASK, 8);
987         OUT_RING  (0xff);
988         OUT_RING  (0x207);
989         OUT_RING  (0);
990         OUT_RING  (0xff);
991         OUT_RING  (0x1e00);
992         OUT_RING  (0x1e00);
993         OUT_RING  (0x1e00);
994         OUT_RING  (0x1d01);
995         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_NORMALIZE_ENABLE, 1);
996         OUT_RING  (0);
997         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_FOG_ENABLE, 2);
998         OUT_RING  (0);
999         OUT_RING  (0);
1000         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_LIGHT_MODEL, 1);
1001         OUT_RING  (0);
1002         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_COLOR_CONTROL, 1);
1003         OUT_RING  (0);
1004         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_ENABLED_LIGHTS, 1);
1005         OUT_RING  (0);
1006         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_POLYGON_OFFSET_POINT_ENABLE, 3);
1007         OUT_RING  (0);
1008         OUT_RING  (0);
1009         OUT_RING  (0);
1010         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_DEPTH_FUNC, 1);
1011         OUT_RING  (0x201);
1012         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_DEPTH_WRITE_ENABLE, 1);
1013         OUT_RING  (0);
1014         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_DEPTH_TEST_ENABLE, 1);
1015         OUT_RING  (0);
1016         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FACTOR, 2);
1017         OUT_RING  (0);
1018         OUT_RING  (0);
1019         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_POINT_SIZE, 1);
1020         OUT_RING  (8);
1021         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_POINT_PARAMETERS_ENABLE, 2);
1022         OUT_RING  (0);
1023         OUT_RING  (0);
1024         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_LINE_WIDTH, 1);
1025         OUT_RING  (8);
1026         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_LINE_SMOOTH_ENABLE, 1);
1027         OUT_RING  (0);
1028         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_POLYGON_MODE_FRONT, 2);
1029         OUT_RING  (0x1b02);
1030         OUT_RING  (0x1b02);
1031         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_CULL_FACE, 2);
1032         OUT_RING  (0x405);
1033         OUT_RING  (0x901);
1034         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_POLYGON_SMOOTH_ENABLE, 1);
1035         OUT_RING  (0);
1036         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_CULL_FACE_ENABLE, 1);
1037         OUT_RING  (0);
1038         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_CLIP_PLANE_ENABLE(0), 8);
1039         for (i=0;i<8;i++) {
1040                 OUT_RING  (0);
1041         }
1042         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_FOG_EQUATION_CONSTANT, 3);
1043         OUT_RING  (0x3fc00000); /* -1.50 */
1044         OUT_RING  (0xbdb8aa0a); /* -0.09 */
1045         OUT_RING  (0);          /*  0.00 */
1046
1047         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_NOP, 1);
1048         OUT_RING  (0);
1049
1050         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_FOG_MODE, 2);
1051         OUT_RING  (0x802);
1052         OUT_RING  (2);
1053         /* for some reason VIEW_MATRIX_ENABLE need to be 6 instead of 4 when
1054          * using texturing, except when using the texture matrix
1055          */
1056         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VIEW_MATRIX_ENABLE, 1);
1057         OUT_RING  (6);
1058         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_COLOR_MASK, 1);
1059         OUT_RING  (0x01010101);
1060
1061         /* Set vertex component */
1062         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_COL_4F_R, 4);
1063         OUT_RINGf (1.0);
1064         OUT_RINGf (1.0);
1065         OUT_RINGf (1.0);
1066         OUT_RINGf (1.0);
1067         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_COL2_3F_R, 3);
1068         OUT_RING  (0);
1069         OUT_RING  (0);
1070         OUT_RING  (0);
1071         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_NOR_3F_X, 3);
1072         OUT_RING  (0);
1073         OUT_RING  (0);
1074         OUT_RINGf (1.0);
1075         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_TX0_4F_S, 4);
1076         OUT_RINGf (0.0);
1077         OUT_RINGf (0.0);
1078         OUT_RINGf (0.0);
1079         OUT_RINGf (1.0);
1080         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_TX1_4F_S, 4);
1081         OUT_RINGf (0.0);
1082         OUT_RINGf (0.0);
1083         OUT_RINGf (0.0);
1084         OUT_RINGf (1.0);
1085         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_FOG_1F, 1);
1086         OUT_RINGf (0.0);
1087         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_EDGEFLAG_ENABLE, 1);
1088         OUT_RING  (1);
1089
1090         return TRUE;
1091 }
1092
1093
1094
1095