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