NV10 EXA: removed left out debug statement
[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_RING  (NVAccelGetPixmapOffset(pixmap));
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_RING  (NVAccelGetPixmapOffset(pixmap));
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, sY0, sY1;
707         float mX0, mX1, mY0, mY1;
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 + height,
714                               state.unit[0].width,
715                               state.unit[0].height, &sX1, &sY1);
716
717         if ( state.is_a8_plus_a8 )
718                 {
719                 /*We do A8 + A8 in 2-pass : setup the source texture as A8 twice, 
720                         with different tex coords, do B and G on first pass
721                 Then setup again and do R and A on second pass
722                 */
723                 int part_pos_dX = 0;
724                 int part_pos_sX = 0;
725                 int mask_out_bytes = 0;
726                 
727                 part_pos_dX = (dstX &~ 3) >> 2; /*we start at the 4byte boundary to the left of the image*/
728                 part_pos_sX = sX0 + (dstX &~ 3) - dstX; 
729
730                 /*xf86DrvMsg(0, X_INFO, "drawing - srcX %f dstX %d w %d\n", sX0, dstX, width);*/
731                 for ( ; part_pos_dX <= (((dstX + width) &~ 3) >> 2); part_pos_sX += 4, part_pos_dX ++ )
732                         {
733                         mask_out_bytes = 0;
734                         if ( part_pos_dX == (dstX &~ 3) >> 2  ) /*then we're slightly on the left of the image, bytes to mask out*/
735                                 {
736                                 /*xf86DrvMsg(0, X_INFO, "on left border...\n");*/
737                                 switch ( dstX - (dstX &~ 3) ) /*mask out the extra pixels on the left*/
738                                         {
739                                         case 4: 
740                                                 mask_out_bytes |= 1 << 0;
741                                         case 3: 
742                                                 mask_out_bytes |= 1 << 1;
743                                         case 2:
744                                                 mask_out_bytes |= 1 << 2;
745                                         case 1: 
746                                                 mask_out_bytes |= 1 << 3;
747                                         case 0:
748                                                 break;
749                                         }
750                                         
751                                 /*mask out extra pixels on the right, in case the picture never touches an alignment marker*/
752                                 switch ( width + (dstX & 3) )
753                                         {
754                                         case 0:
755                                                 mask_out_bytes |= 1 << 3;
756                                         case 1:
757                                                 mask_out_bytes |= 1 << 2;
758                                         case 2:
759                                                 mask_out_bytes |= 1 << 1;
760                                         case 3:
761                                                 mask_out_bytes |= 1 << 0;
762                                         default : break;
763                                         }
764                                 }
765                         else if ( part_pos_dX == (((dstX + width) &~ 3) >> 2) ) 
766                                 {
767                                 /*xf86DrvMsg(0, X_INFO, "on right border...\n");*/
768                                 switch (4 - ((dstX + width) & 3))
769                                         {
770                                         case 4:
771                                                 mask_out_bytes |= 1 << 3;
772                                         case 3: 
773                                                 mask_out_bytes |= 1 << 2;
774                                         case 2: 
775                                                 mask_out_bytes |= 1 << 1;
776                                         case 1:
777                                                 mask_out_bytes |= 1 << 0;
778                                         case 0:
779                                                 break;
780                                         }
781                                 }
782                                 
783                         /*Pass number 0*/
784                         
785                         NV10SetRegCombs_A8plusA8(pNv, 0, mask_out_bytes);
786                         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_BEGIN_END, 1);
787                         OUT_RING  (NV10_TCL_PRIMITIVE_3D_VERTEX_BEGIN_END_QUADS);               
788                                         
789                         NV10MVertex(pNv , part_pos_dX   , dstY              , part_pos_sX, sY0, part_pos_sX + 1, sY0);
790                         NV10MVertex(pNv , part_pos_dX + 1, dstY              , part_pos_sX, sY0, part_pos_sX + 1, sY0);
791                         NV10MVertex(pNv , part_pos_dX + 1, dstY + height, part_pos_sX,  sY1, part_pos_sX + 1, sY1);
792                         NV10MVertex(pNv , part_pos_dX   , dstY + height, part_pos_sX, sY1, part_pos_sX + 1, sY1);
793                         
794                         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_BEGIN_END, 1);
795                         OUT_RING  (NV10_TCL_PRIMITIVE_3D_VERTEX_BEGIN_END_STOP);
796                         
797                         /*Pass number 1*/
798                         
799                         NV10SetRegCombs_A8plusA8(pNv, 1, mask_out_bytes);
800                         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_BEGIN_END, 1);
801                         OUT_RING  (NV10_TCL_PRIMITIVE_3D_VERTEX_BEGIN_END_QUADS);               
802                                         
803                         NV10MVertex(pNv , part_pos_dX, dstY              , part_pos_sX + 2, sY0, part_pos_sX + 3, sY0);
804                         NV10MVertex(pNv , part_pos_dX + 1 , dstY              , part_pos_sX + 2, sY0, part_pos_sX + 3, sY0);
805                         NV10MVertex(pNv , part_pos_dX + 1 , dstY + height, part_pos_sX + 2, sY1, part_pos_sX + 3, sY1);
806                         NV10MVertex(pNv , part_pos_dX, dstY + height, part_pos_sX + 2, sY1, part_pos_sX + 3, sY1);
807
808                         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_BEGIN_END, 1);
809                         OUT_RING  (NV10_TCL_PRIMITIVE_3D_VERTEX_BEGIN_END_STOP);
810                         
811                         }
812                 }
813                 
814         if (state.have_mask) {
815                 NV10EXATransformCoord(state.unit[1].transform, maskX, maskY,
816                                       state.unit[1].width,
817                                       state.unit[1].height, &mX0, &mY0);
818                 NV10EXATransformCoord(state.unit[1].transform,
819                                       maskX + width, maskY + height,
820                                       state.unit[1].width,
821                                       state.unit[1].height, &mX1, &mY1);
822                 NV10MVertex(pNv , dstX         ,          dstY,sX0 , sY0 , mX0 , mY0);
823                 NV10MVertex(pNv , dstX + width ,          dstY,sX1 , sY0 , mX1 , mY0);
824                 NV10MVertex(pNv , dstX + width , dstY + height,sX1 , sY1 , mX1 , mY1);
825                 NV10MVertex(pNv , dstX         , dstY + height,sX0 , sY1 , mX0 , mY1);
826         } else {
827                 NV10Vertex(pNv , dstX         ,          dstY , sX0 , sY0);
828                 NV10Vertex(pNv , dstX + width ,          dstY , sX1 , sY0);
829                 NV10Vertex(pNv , dstX + width , dstY + height , sX1 , sY1);
830                 NV10Vertex(pNv , dstX         , dstY + height , sX0 , sY1);
831         }
832
833         FIRE_RING();
834 }
835
836 void NV10DoneComposite (PixmapPtr pDst)
837 {
838         ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
839         NVPtr pNv = NVPTR(pScrn);
840
841         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_BEGIN_END, 1);
842         OUT_RING  (NV10_TCL_PRIMITIVE_3D_VERTEX_BEGIN_END_STOP);
843
844         exaMarkSync(pDst->drawable.pScreen);
845 }
846
847
848 Bool
849 NVAccelInitNV10TCL(ScrnInfoPtr pScrn)
850 {
851         NVPtr pNv = NVPTR(pScrn);
852         static int have_object = FALSE;
853         uint32_t class = 0, chipset;
854         int i;
855
856         chipset = (nvReadMC(pNv, 0) >> 20) & 0xff;
857         if (    ((chipset & 0xf0) != NV_ARCH_10) &&
858                 ((chipset & 0xf0) != NV_ARCH_20) )
859                 return FALSE;
860
861         if (chipset>=0x20)
862                 class = NV11_TCL_PRIMITIVE_3D;
863         else if (chipset>=0x17)
864                 class = NV17_TCL_PRIMITIVE_3D;
865         else if (chipset>=0x11)
866                 class = NV11_TCL_PRIMITIVE_3D;
867         else
868                 class = NV10_TCL_PRIMITIVE_3D;
869
870         if (!have_object) {
871                 if (!NVDmaCreateContextObject(pNv, Nv3D, class))
872                         return FALSE;
873                 have_object = TRUE;
874         }
875
876         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_DMA_NOTIFY, 1);
877         OUT_RING  (NvNullObject);
878
879         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_DMA_IN_MEMORY0, 2);
880         OUT_RING  (NvDmaFB);
881         OUT_RING  (NvDmaTT);
882
883         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_DMA_IN_MEMORY2, 2);
884         OUT_RING  (NvDmaFB);
885         OUT_RING  (NvDmaFB);
886
887         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_NOP, 1);
888         OUT_RING  (0);
889
890         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VIEWPORT_HORIZ, 2);
891         OUT_RING  (0);
892         OUT_RING  (0);
893
894         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_HORIZ(0), 1);
895         OUT_RING  ((0x7ff<<16)|0x800);
896         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_VERT(0), 1);
897         OUT_RING  ((0x7ff<<16)|0x800);
898
899         for (i=1;i<8;i++) {
900                 BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_HORIZ(i), 1);
901                 OUT_RING  (0);
902                 BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_VERT(i), 1);
903                 OUT_RING  (0);
904         }
905
906         BEGIN_RING(Nv3D, 0x290, 1);
907         OUT_RING  ((0x10<<16)|1);
908         BEGIN_RING(Nv3D, 0x3f4, 1);
909         OUT_RING  (0);
910
911         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_NOP, 1);
912         OUT_RING  (0);
913
914         if (class != NV10_TCL_PRIMITIVE_3D) {
915                 /* For nv11, nv17 */
916                 BEGIN_RING(Nv3D, 0x120, 3);
917                 OUT_RING  (0);
918                 OUT_RING  (1);
919                 OUT_RING  (2);
920
921                 BEGIN_RING(NvImageBlit, 0x120, 3);
922                 OUT_RING  (0);
923                 OUT_RING  (1);
924                 OUT_RING  (2);
925
926                 BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_NOP, 1);
927                 OUT_RING  (0);
928         }
929
930         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_NOP, 1);
931         OUT_RING  (0);
932
933         /* Set state */
934         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_FOG_ENABLE, 1);
935         OUT_RING  (0);
936         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_ALPHA_FUNC_ENABLE, 1);
937         OUT_RING  (0);
938         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_ALPHA_FUNC_FUNC, 2);
939         OUT_RING  (0x207);
940         OUT_RING  (0);
941         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_TX_ENABLE(0), 2);
942         OUT_RING  (0);
943         OUT_RING  (0);
944         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_RC_IN_ALPHA(0), 12);
945         OUT_RING  (0x30141010);
946         OUT_RING  (0);
947         OUT_RING  (0x20040000);
948         OUT_RING  (0);
949         OUT_RING  (0);
950         OUT_RING  (0);
951         OUT_RING  (0x00000c00);
952         OUT_RING  (0);
953         OUT_RING  (0x00000c00);
954         OUT_RING  (0x18000000);
955         OUT_RING  (0x300e0300);
956         OUT_RING  (0x0c091c80);
957         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_BLEND_FUNC_ENABLE, 1);
958         OUT_RING  (0);
959         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_DITHER_ENABLE, 2);
960         OUT_RING  (1);
961         OUT_RING  (0);
962         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_LINE_SMOOTH_ENABLE, 1);
963         OUT_RING  (0);
964         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_WEIGHT_ENABLE, 2);
965         OUT_RING  (0);
966         OUT_RING  (0);
967         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_BLEND_FUNC_SRC, 4);
968         OUT_RING  (1);
969         OUT_RING  (0);
970         OUT_RING  (0);
971         OUT_RING  (0x8006);
972         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_STENCIL_MASK, 8);
973         OUT_RING  (0xff);
974         OUT_RING  (0x207);
975         OUT_RING  (0);
976         OUT_RING  (0xff);
977         OUT_RING  (0x1e00);
978         OUT_RING  (0x1e00);
979         OUT_RING  (0x1e00);
980         OUT_RING  (0x1d01);
981         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_NORMALIZE_ENABLE, 1);
982         OUT_RING  (0);
983         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_FOG_ENABLE, 2);
984         OUT_RING  (0);
985         OUT_RING  (0);
986         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_LIGHT_MODEL, 1);
987         OUT_RING  (0);
988         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_COLOR_CONTROL, 1);
989         OUT_RING  (0);
990         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_ENABLED_LIGHTS, 1);
991         OUT_RING  (0);
992         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_POLYGON_OFFSET_POINT_ENABLE, 3);
993         OUT_RING  (0);
994         OUT_RING  (0);
995         OUT_RING  (0);
996         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_DEPTH_FUNC, 1);
997         OUT_RING  (0x201);
998         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_DEPTH_WRITE_ENABLE, 1);
999         OUT_RING  (0);
1000         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_DEPTH_TEST_ENABLE, 1);
1001         OUT_RING  (0);
1002         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FACTOR, 2);
1003         OUT_RING  (0);
1004         OUT_RING  (0);
1005         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_POINT_SIZE, 1);
1006         OUT_RING  (8);
1007         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_POINT_PARAMETERS_ENABLE, 2);
1008         OUT_RING  (0);
1009         OUT_RING  (0);
1010         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_LINE_WIDTH, 1);
1011         OUT_RING  (8);
1012         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_LINE_SMOOTH_ENABLE, 1);
1013         OUT_RING  (0);
1014         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_POLYGON_MODE_FRONT, 2);
1015         OUT_RING  (0x1b02);
1016         OUT_RING  (0x1b02);
1017         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_CULL_FACE, 2);
1018         OUT_RING  (0x405);
1019         OUT_RING  (0x901);
1020         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_POLYGON_SMOOTH_ENABLE, 1);
1021         OUT_RING  (0);
1022         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_CULL_FACE_ENABLE, 1);
1023         OUT_RING  (0);
1024         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_CLIP_PLANE_ENABLE(0), 8);
1025         for (i=0;i<8;i++) {
1026                 OUT_RING  (0);
1027         }
1028         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_FOG_EQUATION_CONSTANT, 3);
1029         OUT_RING  (0x3fc00000); /* -1.50 */
1030         OUT_RING  (0xbdb8aa0a); /* -0.09 */
1031         OUT_RING  (0);          /*  0.00 */
1032
1033         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_NOP, 1);
1034         OUT_RING  (0);
1035
1036         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_FOG_MODE, 2);
1037         OUT_RING  (0x802);
1038         OUT_RING  (2);
1039         /* for some reason VIEW_MATRIX_ENABLE need to be 6 instead of 4 when
1040          * using texturing, except when using the texture matrix
1041          */
1042         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VIEW_MATRIX_ENABLE, 1);
1043         OUT_RING  (6);
1044         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_COLOR_MASK, 1);
1045         OUT_RING  (0x01010101);
1046
1047         /* Set vertex component */
1048         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_COL_4F_R, 4);
1049         OUT_RINGf (1.0);
1050         OUT_RINGf (1.0);
1051         OUT_RINGf (1.0);
1052         OUT_RINGf (1.0);
1053         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_COL2_3F_R, 3);
1054         OUT_RING  (0);
1055         OUT_RING  (0);
1056         OUT_RING  (0);
1057         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_NOR_3F_X, 3);
1058         OUT_RING  (0);
1059         OUT_RING  (0);
1060         OUT_RINGf (1.0);
1061         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_TX0_4F_S, 4);
1062         OUT_RINGf (0.0);
1063         OUT_RINGf (0.0);
1064         OUT_RINGf (0.0);
1065         OUT_RINGf (1.0);
1066         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_TX1_4F_S, 4);
1067         OUT_RINGf (0.0);
1068         OUT_RINGf (0.0);
1069         OUT_RINGf (0.0);
1070         OUT_RINGf (1.0);
1071         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_FOG_1F, 1);
1072         OUT_RINGf (0.0);
1073         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_EDGEFLAG_ENABLE, 1);
1074         OUT_RING  (1);
1075
1076         return TRUE;
1077 }
1078
1079
1080
1081