Fix some blending stuff for NV10 EXA
[nouveau] / src / nv10_exa.c
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4
5 #include "nv_include.h"
6
7 typedef struct nv10_exa_state {
8         Bool have_mask;
9
10         struct {
11                 PictTransformPtr transform;
12                 float width;
13                 float height;
14         } unit[2];
15 } nv10_exa_state_t;
16 static nv10_exa_state_t state;
17
18 static int NV10TexFormat(int ExaFormat)
19 {
20         struct {int exa;int hw;} tex_format[] =
21         {
22                 {PICT_a8r8g8b8, NV10_TCL_PRIMITIVE_3D_TX_FORMAT_FORMAT_R8G8B8A8_RECT},
23                 //{PICT_a1r5g5b5,       NV10_TCL_PRIMITIVE_3D_TX_FORMAT_FORMAT_R5G5B5A1},
24                 //{PICT_a4r4g4b4,       NV10_TCL_PRIMITIVE_3D_TX_FORMAT_FORMAT_R4G4B4A4},
25                 //{PICT_a8,     NV10_TCL_PRIMITIVE_3D_TX_FORMAT_FORMAT_A8_RECT}
26                 // FIXME other formats
27         };
28
29         int i;
30         for(i=0;i<sizeof(tex_format)/sizeof(tex_format[0]);i++)
31         {
32                 if(tex_format[i].exa==ExaFormat)
33                         return tex_format[i].hw;
34         }
35
36         return 0;
37 }
38
39 static int NV10DstFormat(int ExaFormat)
40 {
41         struct {int exa;int hw;} dst_format[] =
42         {
43                 {PICT_a8r8g8b8, 0x108},
44                 {PICT_x8r8g8b8, 0x108}, // FIXME that one might need more
45                 {PICT_r5g6b5,   0x103}
46                 // FIXME other formats
47         };
48
49         int i;
50         for(i=0;i<sizeof(dst_format)/sizeof(dst_format[0]);i++)
51         {
52                 if(dst_format[i].exa==ExaFormat)
53                         return dst_format[i].hw;
54         }
55
56         return 0;
57 }
58
59 static Bool NV10CheckTexture(PicturePtr Picture)
60 {
61         int w = Picture->pDrawable->width;
62         int h = Picture->pDrawable->height;
63
64         if ((w > 2046) || (h>2046))
65                 return FALSE;
66         if (!NV10TexFormat(Picture->format))
67                 return FALSE;
68         if (Picture->filter != PictFilterNearest && Picture->filter != PictFilterBilinear)
69                 return FALSE;
70         if (Picture->repeat != RepeatNone)
71                 return FALSE;
72         return TRUE;
73 }
74
75 static Bool NV10CheckBuffer(PicturePtr Picture)
76 {
77         int w = Picture->pDrawable->width;
78         int h = Picture->pDrawable->height;
79
80         if ((w > 4096) || (h>4096))
81                 return FALSE;
82         if (!NV10DstFormat(Picture->format))
83                 return FALSE;
84         return TRUE;
85 }
86
87 Bool NV10CheckComposite(int     op,
88                              PicturePtr pSrcPicture,
89                              PicturePtr pMaskPicture,
90                              PicturePtr pDstPicture)
91 {
92         // XXX A8 + A8 special case "TO BE DONE LATER"
93 /*      if ((!pMaskPicture) &&
94                         (pSrcPicture->format == PICT_a8) &&
95                         (pDstPicture->format == PICT_a8) )
96                 return TRUE;*/
97
98         if (!NV10CheckBuffer(pDstPicture))
99                 return FALSE;
100         if (!NV10CheckTexture(pSrcPicture))
101                 return FALSE;
102         if ((pMaskPicture)&&(!NV10CheckTexture(pMaskPicture)))
103                 return FALSE;
104
105         return TRUE;
106 }
107
108 static void NV10SetTexture(NVPtr pNv,int unit,PicturePtr Pict,PixmapPtr pixmap)
109 {
110         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_TX_OFFSET(unit), 1 );
111         OUT_RING  (NVAccelGetPixmapOffset(pixmap));
112
113         int log2w = log2i(Pict->pDrawable->width);
114         int log2h = log2i(Pict->pDrawable->height);
115         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_TX_FORMAT(unit), 1 );
116         OUT_RING  ((NV10_TCL_PRIMITIVE_3D_TX_FORMAT_WRAP_T_CLAMP_TO_EDGE) |
117                         (NV10_TCL_PRIMITIVE_3D_TX_FORMAT_WRAP_S_CLAMP_TO_EDGE) |
118                         (log2w<<20) |
119                         (log2h<<16) |
120                         (1<<12) | /* lod == 1 */
121                         (1<<11) | /* enable NPOT */
122                         (NV10TexFormat(Pict->format)) |
123                         0x51 /* UNK */
124                         );
125
126         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_TX_ENABLE(unit), 1 );
127         OUT_RING  (NV10_TCL_PRIMITIVE_3D_TX_ENABLE_ENABLE);
128
129         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_TX_NPOT_PITCH(unit), 1);
130         OUT_RING  (exaGetPixmapPitch(pixmap) << 16);
131
132         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_TX_NPOT_SIZE(unit), 1);
133         OUT_RING  ((Pict->pDrawable->width<<16) | Pict->pDrawable->height); /* FIXME alignment restrictions, should be even at least */
134
135         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_TX_FILTER(unit), 1);
136         if (Pict->filter == PictFilterNearest)
137                 OUT_RING  ((NV10_TCL_PRIMITIVE_3D_TX_FILTER_MAGNIFY_NEAREST) |
138                                 (NV10_TCL_PRIMITIVE_3D_TX_FILTER_MINIFY_NEAREST));
139         else
140                 OUT_RING  ((NV10_TCL_PRIMITIVE_3D_TX_FILTER_MAGNIFY_LINEAR) |
141                                 (NV10_TCL_PRIMITIVE_3D_TX_FILTER_MINIFY_LINEAR));
142
143         state.unit[unit].width          = (float)pixmap->drawable.width;
144         state.unit[unit].height         = (float)pixmap->drawable.height;
145         state.unit[unit].transform      = Pict->transform;
146 }
147
148 static void NV10SetBuffer(NVPtr pNv,PicturePtr Pict,PixmapPtr pixmap)
149 {
150         int x = 0,y = 0,i;
151         int w = Pict->pDrawable->width;
152         int h = Pict->pDrawable->height;
153
154         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_BUFFER_FORMAT, 4);
155         OUT_RING  (NV10DstFormat(Pict->format));
156         OUT_RING  (((uint32_t)exaGetPixmapPitch(pixmap) << 16) |(uint32_t)exaGetPixmapPitch(pixmap));
157         OUT_RING  (NVAccelGetPixmapOffset(pixmap));
158         OUT_RING  (0);
159         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VIEWPORT_HORIZ, 2);
160         OUT_RING  ((w<<16)|x);
161         OUT_RING  ((h<<16)|y);
162         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_MODE, 1); /* clip_mode */
163         OUT_RING  (0);
164         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_HORIZ(0), 1);
165         OUT_RING  (((w-1+x)<<16)|x|0x08000800);
166         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_VERT(0), 1);
167         OUT_RING  (((h-1+y)<<16)|y|0x08000800);
168
169         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_PROJECTION_MATRIX(0), 16);
170         for(i=0;i<16;i++)
171                 if (i/4==i%4)
172                         OUT_RINGf (1.0f);
173                 else
174                         OUT_RINGf (0.0f);
175
176         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_DEPTH_RANGE_NEAR, 2);
177         OUT_RING  (0);
178 #if SCREEN_BPP == 32
179         OUT_RINGf (16777216.0);
180 #else
181         OUT_RINGf (65536.0);
182 #endif
183         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VIEWPORT_SCALE_X, 4);
184         OUT_RINGf (-2048.0);
185         OUT_RINGf (-2048.0);
186         OUT_RINGf (0);
187         OUT_RING  (0);
188 }
189
190 static void NV10SetMultitexture(NVPtr pNv,int multitex)
191 {
192         // FIXME
193         if (multitex)
194         {
195 /*
196 18141010    NV10_TCL_PRIMITIVE_3D.RC_IN_ALPHA[0] = D_INPUT=ZERO | D_COMPONENT_USAGE=ALPHA | D_MAPPING=UNSIGNED_IDENTITY_NV | C_INPUT=ZERO | C_COMPONENT_USAGE=ALPHA | C_MAPPING=UNSIGNED_IDENTITY_NV | B_INPUT=PRIMARY_COLOR_NV | B_COMPONENT_USAGE=ALPHA | B_MAPPING=UNSIGNED_IDENTITY_NV | A_INPUT=TEXTURE1_ARB | A_COMPONENT_USAGE=ALPHA | A_MAPPING=UNSIGNED_IDENTITY_NV
197 091c1010    NV10_TCL_PRIMITIVE_3D.RC_IN_ALPHA[1] = D_INPUT=ZERO | D_COMPONENT_USAGE=ALPHA | D_MAPPING=UNSIGNED_IDENTITY_NV | C_INPUT=ZERO | C_COMPONENT_USAGE=ALPHA | C_MAPPING=UNSIGNED_IDENTITY_NV | B_INPUT=SPARE0_NV | B_COMPONENT_USAGE=ALPHA | B_MAPPING=UNSIGNED_IDENTITY_NV | A_INPUT=TEXTURE0_ARB | A_COMPONENT_USAGE=BLUE | A_MAPPING=UNSIGNED_IDENTITY_NV
198 08040820    NV10_TCL_PRIMITIVE_3D.RC_IN_RGB[0] = D_INPUT=ZERO | D_COMPONENT_USAGE=RGB | D_MAPPING=UNSIGNED_INVERT_NV | C_INPUT=TEXTURE1_ARB | C_COMPONENT_USAGE=RGB | C_MAPPING=UNSIGNED_IDENTITY_NV | B_INPUT=PRIMARY_COLOR_NV | B_COMPONENT_USAGE=RGB | B_MAPPING=UNSIGNED_IDENTITY_NV | A_INPUT=TEXTURE1_ARB | A_COMPONENT_USAGE=RGB | A_MAPPING=UNSIGNED_IDENTITY_NV
199 090c0920    NV10_TCL_PRIMITIVE_3D.RC_IN_RGB[1] = D_INPUT=ZERO | D_COMPONENT_USAGE=RGB | D_MAPPING=UNSIGNED_INVERT_NV | C_INPUT=TEXTURE0_ARB | C_COMPONENT_USAGE=RGB | C_MAPPING=UNSIGNED_IDENTITY_NV | B_INPUT=SPARE0_NV | B_COMPONENT_USAGE=RGB | B_MAPPING=UNSIGNED_IDENTITY_NV | A_INPUT=TEXTURE0_ARB | A_COMPONENT_USAGE=RGB | A_MAPPING=UNSIGNED_IDENTITY_NV
200 00000000    NV10_TCL_PRIMITIVE_3D.RC_COLOR[0] = B=0 | G=0 | R=0 | A=0
201 00000000    NV10_TCL_PRIMITIVE_3D.RC_COLOR[1] = B=0 | G=0 | R=0 | A=0
202 00000c00    NV10_TCL_PRIMITIVE_3D.RC_OUT_ALPHA[0] = CD_OUTPUT=ZERO | AB_OUTPUT=ZERO | SUM_OUTPUT=SPARE0_NV | CD_DOT_PRODUCT=FALSE | AB_DOT_PRODUCT=FALSE | MUX_SUM=FALSE | BIAS=NONE | SCALE=NONE | leftover=0x00000000/0x0000ffff
203 00000c00    NV10_TCL_PRIMITIVE_3D.RC_OUT_ALPHA[1] = CD_OUTPUT=ZERO | AB_OUTPUT=ZERO | SUM_OUTPUT=SPARE0_NV | CD_DOT_PRODUCT=FALSE | AB_DOT_PRODUCT=FALSE | MUX_SUM=FALSE | BIAS=NONE | SCALE=NONE | leftover=0x00000000/0x0000ffff
204 000010cd    NV10_TCL_PRIMITIVE_3D.RC_OUT_RGB[0] = CD_OUTPUT=SPARE1_NV | AB_OUTPUT=SPARE0_NV | SUM_OUTPUT=ZERO | CD_DOT_PRODUCT=TRUE | AB_DOT_PRODUCT=FALSE | MUX_SUM=FALSE | BIAS=NONE | SCALE=NONE | OPERATION=0 | leftover=0x00000000/0x3800ffff
205 280010cd    NV10_TCL_PRIMITIVE_3D.RC_OUT_RGB[1] = CD_OUTPUT=SPARE1_NV | AB_OUTPUT=SPARE0_NV | SUM_OUTPUT=ZERO | CD_DOT_PRODUCT=TRUE | AB_DOT_PRODUCT=FALSE | MUX_SUM=FALSE | BIAS=NONE | SCALE=NONE | OPERATION=5 | leftover=0x00000000/0x3800ffff
206 300e0300    NV10_TCL_PRIMITIVE_3D.RC_FINAL0 = D_INPUT=ZERO | D_COMPONENT_USAGE=RGB | D_MAPPING=UNSIGNED_IDENTITY_NV | C_INPUT=FOG | C_COMPONENT_USAGE=RGB | C_MAPPING=UNSIGNED_IDENTITY_NV | B_INPUT=SPARE0_PLUS_SECONDARY_COLOR_NV | B_COMPONENT_USAGE=RGB | B_MAPPING=UNSIGNED_IDENTITY_NV | A_INPUT=ZERO | A_COMPONENT_USAGE=ALPHA | A_MAPPING=UNSIGNED_INVERT_NV
207 0c091c80    NV10_TCL_PRIMITIVE_3D.RC_FINAL1 = COLOR_SUM_CLAMP=TRUE | G_INPUT=SPARE0_NV | G_COMPONENT_USAGE=ALPHA | G_MAPPING=UNSIGNED_IDENTITY_NV | F_INPUT=TEXTURE0_ARB | F_COMPONENT_USAGE=RGB | F_MAPPING=UNSIGNED_IDENTITY_NV | E_INPUT=SPARE0_NV | E_COMPONENT_USAGE=RGB | E_MAPPING=UNSIGNED_IDENTITY_NV | leftover=0x00000000/0xffffff80
208 00042294  size 1, subchannel 1 (0xbeef5601),offset 0x0294,increment
209 00000000    NV10_TCL_PRIMITIVE_3D.LIGHT_MODEL = COLOR_CONTROL=0 | LOCAL_VIEWER=FALSE | leftover=0x00000000/0x00010002
210 000423b8  size 1, subchannel 1 (0xbeef5601),offset 0x03b8,increment
211 00000000    NV10_TCL_PRIMITIVE_3D.COLOR_CONTROL
212 000423bc  size 1, subchannel 1 (0xbeef5601),offset 0x03bc,increment
213 00000000    NV10_TCL_PRIMITIVE_3D.ENABLED_LIGHTS = LIGHT0=FALSE | LIGHT1=FALSE | LIGHT2=FALSE | LIGHT3=FALSE | LIGHT4=FALSE | LIGHT5=FALSE | LIGHT6=FALSE | LIGHT7=FALSE | leftover=0x00000000/0x00005555
214 00402500  size 16, subchannel 1 (0xbeef5601),offset 0x0500,increment
215 */              
216         }
217         else
218         {
219                 BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_RC_IN_ALPHA(0), 12);
220                 OUT_RING  (0x18141010);
221                 OUT_RING  (0);
222                 OUT_RING  (0x08040820);
223                 OUT_RING  (0);
224                 OUT_RING  (0);
225                 OUT_RING  (0);
226                 OUT_RING  (0x00000c00);
227                 OUT_RING  (0);
228                 OUT_RING  (0x000010cd);
229                 OUT_RING  (0x18000000);
230                 OUT_RING  (0x300e0300);
231                 OUT_RING  (0x0c091c80);
232         }
233 }
234
235 static void NV10SetPictOp(NVPtr pNv,int op)
236 {
237         struct {int src;int dst;} pictops[] =
238         {
239                 {0x0000,0x0000}, // PictOpClear
240                 {0x0001,0x0000}, // PictOpSrc 
241                 {0x0000,0x0001}, // PictOpDst
242                 {0x0001,0x0303}, // PictOpOver
243                 {0x0305,0x0001}, // PictOpOverReverse
244                 {0x0304,0x0000}, // PictOpIn
245                 {0x0000,0x0302}, // PictOpInReverse
246                 {0x0305,0x0000}, // PictOpOut
247                 {0x0000,0x0303}, // PictOpOutReverse
248                 {0x0304,0x0303}, // PictOpAtop
249                 {0x0305,0x0302}, // PictOpAtopReverse
250                 {0x0305,0x0303}, // PictOpXor
251                 {0x0001,0x0001}, // PictOpAdd
252         };
253
254         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_BLEND_FUNC_SRC, 2);
255         OUT_RING  (pictops[op].src);
256         OUT_RING  (pictops[op].dst);
257         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_BLEND_FUNC_ENABLE, 1);
258         OUT_RING  (1);
259 }
260
261 Bool NV10PrepareComposite(int     op,
262                                PicturePtr pSrcPicture,
263                                PicturePtr pMaskPicture,
264                                PicturePtr pDstPicture,
265                                PixmapPtr  pSrc,
266                                PixmapPtr  pMask,
267                                PixmapPtr  pDst)
268 {
269         ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
270         NVPtr pNv = NVPTR(pScrn);
271
272         /* Set dst format */
273         NV10SetBuffer(pNv,pDstPicture,pDst);
274
275         /* Set src format */
276         NV10SetTexture(pNv,0,pSrcPicture,pSrc);
277
278         /* Set mask format */
279         if (pMaskPicture)
280                 NV10SetTexture(pNv,1,pMaskPicture,pMask);
281
282         /* Set Multitexturing */
283         NV10SetMultitexture(pNv, (pMaskPicture!=NULL));
284
285         /* Set PictOp */
286         NV10SetPictOp(pNv, op);
287
288         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_BEGIN_END, 1);
289         OUT_RING  (NV10_TCL_PRIMITIVE_3D_VERTEX_BEGIN_END_QUADS);
290
291         state.have_mask=(pMaskPicture!=NULL);
292         return TRUE;
293 }
294
295 static inline void NV10Vertex(NVPtr pNv,float vx,float vy,float tx,float ty)
296 {
297         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_TX0_2F_S, 2);
298         OUT_RINGf (tx);
299         OUT_RINGf (ty);
300         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_POS_3F_X, 3);
301         OUT_RINGf (vx);
302         OUT_RINGf (vy);
303         OUT_RINGf (0.f);
304 }
305
306 static inline void NV10MVertex(NVPtr pNv,float vx,float vy,float t0x,float t0y,float t1x,float t1y)
307 {
308         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_TX0_2F_S, 2);
309         OUT_RINGf (t0x);
310         OUT_RINGf (t0y);
311         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_TX1_2F_S, 2);
312         OUT_RINGf (t1x);
313         OUT_RINGf (t1y);
314         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_POS_3F_X, 3);
315         OUT_RINGf (vx);
316         OUT_RINGf (vy);
317         OUT_RINGf (0.f);
318 }
319
320 #define xFixedToFloat(v) \
321         ((float)xFixedToInt((v)) + ((float)xFixedFrac(v) / 65536.0))
322
323 static void
324 NV10EXATransformCoord(PictTransformPtr t, int x, int y, float sx, float sy,
325                                           float *x_ret, float *y_ret)
326 {
327         PictVector v;
328
329         if (t) {
330                 v.vector[0] = IntToxFixed(x);
331                 v.vector[1] = IntToxFixed(y);
332                 v.vector[2] = xFixed1;
333                 PictureTransformPoint(t, &v);
334                 *x_ret = xFixedToFloat(v.vector[0]);
335                 *y_ret = xFixedToFloat(v.vector[1]);
336         } else {
337                 *x_ret = (float)x;
338                 *y_ret = (float)y;
339         }
340 }
341
342
343 void NV10Composite(PixmapPtr pDst,
344                         int       srcX,
345                         int       srcY,
346                         int       maskX,
347                         int       maskY,
348                         int       dstX,
349                         int       dstY,
350                         int       width,
351                         int       height)
352 {
353         ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
354         NVPtr pNv = NVPTR(pScrn);
355         float sX0, sX1, sY0, sY1;
356         float mX0, mX1, mY0, mY1;
357
358         NV10EXATransformCoord(state.unit[0].transform, srcX, srcY,
359                               state.unit[0].width,
360                               state.unit[0].height, &sX0, &sY0);
361         NV10EXATransformCoord(state.unit[0].transform,
362                               srcX + width, srcY + height,
363                               state.unit[0].width,
364                               state.unit[0].height, &sX1, &sY1);
365
366         if (state.have_mask) {
367                 NV10EXATransformCoord(state.unit[1].transform, maskX, maskY,
368                                       state.unit[1].width,
369                                       state.unit[1].height, &mX0, &mY0);
370                 NV10EXATransformCoord(state.unit[1].transform,
371                                       maskX + width, maskY + height,
372                                       state.unit[1].width,
373                                       state.unit[1].height, &mX1, &mY1);
374                 NV10MVertex(pNv , dstX         ,          dstY,sX0 , sY0 , mX0 , mY0);
375                 NV10MVertex(pNv , dstX + width ,          dstY,sX1 , sY0 , mX1 , mY0);
376                 NV10MVertex(pNv , dstX + width , dstY + height,sX1 , sY1 , mX1 , mY1);
377                 NV10MVertex(pNv , dstX         , dstY + height,sX0 , sY1 , mX0 , mY1);
378         } else {
379                 NV10Vertex(pNv , dstX         ,          dstY , sX0 , sY0);
380                 NV10Vertex(pNv , dstX + width ,          dstY , sX1 , sY0);
381                 NV10Vertex(pNv , dstX + width , dstY + height , sX1 , sY1);
382                 NV10Vertex(pNv , dstX         , dstY + height , sX0 , sY1);
383         }
384
385         FIRE_RING();
386 }
387
388 void NV10DoneComposite (PixmapPtr pDst)
389 {
390         ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
391         NVPtr pNv = NVPTR(pScrn);
392
393         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_BEGIN_END, 1);
394         OUT_RING  (NV10_TCL_PRIMITIVE_3D_VERTEX_BEGIN_END_STOP);
395
396         exaMarkSync(pDst->drawable.pScreen);
397 }
398
399
400 Bool
401 NVAccelInitNV10TCL(ScrnInfoPtr pScrn)
402 {
403         NVPtr pNv = NVPTR(pScrn);
404         static int have_object = FALSE;
405         uint32_t class = 0, chipset;
406         int i;
407
408         chipset = (nvReadMC(pNv, 0) >> 20) & 0xff;
409         if (    ((chipset & 0xf0) != NV_ARCH_10) &&
410                 ((chipset & 0xf0) != NV_ARCH_20) )
411                 return FALSE;
412
413         if (chipset>=0x20)
414                 class = NV11_TCL_PRIMITIVE_3D;
415         else if (chipset>=0x17)
416                 class = NV17_TCL_PRIMITIVE_3D;
417         else if (chipset>=0x11)
418                 class = NV11_TCL_PRIMITIVE_3D;
419         else
420                 class = NV10_TCL_PRIMITIVE_3D;
421
422         if (!have_object) {
423                 if (!NVDmaCreateContextObject(pNv, Nv3D, class))
424                         return FALSE;
425                 have_object = TRUE;
426         }
427
428         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_DMA_NOTIFY, 1);
429         OUT_RING  (NvNullObject);
430
431         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_DMA_IN_MEMORY0, 2);
432         OUT_RING  (NvDmaFB);
433         OUT_RING  (NvDmaTT);
434
435         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_DMA_IN_MEMORY2, 2);
436         OUT_RING  (NvDmaFB);
437         OUT_RING  (NvDmaFB);
438
439         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_NOP, 1);
440         OUT_RING  (0);
441
442         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VIEWPORT_HORIZ, 2);
443         OUT_RING  (0);
444         OUT_RING  (0);
445
446         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_HORIZ(0), 1);
447         OUT_RING  ((0x7ff<<16)|0x800);
448         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_VERT(0), 1);
449         OUT_RING  ((0x7ff<<16)|0x800);
450
451         for (i=1;i<8;i++) {
452                 BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_HORIZ(i), 1);
453                 OUT_RING  (0);
454                 BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_VERT(i), 1);
455                 OUT_RING  (0);
456         }
457
458         BEGIN_RING(Nv3D, 0x290, 1);
459         OUT_RING  ((0x10<<16)|1);
460         BEGIN_RING(Nv3D, 0x3f4, 1);
461         OUT_RING  (0);
462
463 //      BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_NOTIFY, 1);
464 //      OUT_RING  (0);
465         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_NOP, 1);
466         OUT_RING  (0);
467
468         if (class != NV10_TCL_PRIMITIVE_3D) {
469                 /* For nv11, nv17 */
470                 BEGIN_RING(Nv3D, 0x120, 3);
471                 OUT_RING  (0);
472                 OUT_RING  (1);
473                 OUT_RING  (2);
474
475                 BEGIN_RING(NvImageBlit, 0x120, 3);
476                 OUT_RING  (0);
477                 OUT_RING  (1);
478                 OUT_RING  (2);
479
480                 BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_NOP, 1);
481                 OUT_RING  (0);
482         }
483
484         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_NOP, 1);
485         OUT_RING  (0);
486
487         /* Set state */
488         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_FOG_ENABLE, 1);
489         OUT_RING  (0);
490         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_ALPHA_FUNC_ENABLE, 1);
491         OUT_RING  (0);
492         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_ALPHA_FUNC_FUNC, 2);
493         OUT_RING  (0x207);
494         OUT_RING  (0);
495         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_TX_ENABLE(0), 2);
496         OUT_RING  (0);
497         OUT_RING  (0);
498         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_RC_IN_ALPHA(0), 12);
499         OUT_RING  (0x30141010);
500         OUT_RING  (0);
501         OUT_RING  (0x20040000);
502         OUT_RING  (0);
503         OUT_RING  (0);
504         OUT_RING  (0);
505         OUT_RING  (0x00000c00);
506         OUT_RING  (0);
507         OUT_RING  (0x00000c00);
508         OUT_RING  (0x18000000);
509         OUT_RING  (0x300e0300);
510         OUT_RING  (0x0c091c80);
511         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_BLEND_FUNC_ENABLE, 1);
512         OUT_RING  (0);
513         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_DITHER_ENABLE, 2);
514         OUT_RING  (1);
515         OUT_RING  (0);
516         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_LINE_SMOOTH_ENABLE, 1);
517         OUT_RING  (0);
518         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_WEIGHT_ENABLE, 2);
519         OUT_RING  (0);
520         OUT_RING  (0);
521         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_BLEND_FUNC_SRC, 4);
522         OUT_RING  (1);
523         OUT_RING  (0);
524         OUT_RING  (0);
525         OUT_RING  (0x8006);
526         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_STENCIL_MASK, 8);
527         OUT_RING  (0xff);
528         OUT_RING  (0x207);
529         OUT_RING  (0);
530         OUT_RING  (0xff);
531         OUT_RING  (0x1e00);
532         OUT_RING  (0x1e00);
533         OUT_RING  (0x1e00);
534         OUT_RING  (0x1d01);
535         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_NORMALIZE_ENABLE, 1);
536         OUT_RING  (0);
537         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_FOG_ENABLE, 2);
538         OUT_RING  (0);
539         OUT_RING  (0);
540         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_LIGHT_MODEL, 1);
541         OUT_RING  (0);
542         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_COLOR_CONTROL, 1);
543         OUT_RING  (0);
544         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_ENABLED_LIGHTS, 1);
545         OUT_RING  (0);
546         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_POLYGON_OFFSET_POINT_ENABLE, 3);
547         OUT_RING  (0);
548         OUT_RING  (0);
549         OUT_RING  (0);
550         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_DEPTH_FUNC, 1);
551         OUT_RING  (0x201);
552         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_DEPTH_WRITE_ENABLE, 1);
553         OUT_RING  (0);
554         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_DEPTH_TEST_ENABLE, 1);
555         OUT_RING  (0);
556         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FACTOR, 2);
557         OUT_RING  (0);
558         OUT_RING  (0);
559         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_POINT_SIZE, 1);
560         OUT_RING  (8);
561         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_POINT_PARAMETERS_ENABLE, 2);
562         OUT_RING  (0);
563         OUT_RING  (0);
564         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_LINE_WIDTH, 1);
565         OUT_RING  (8);
566         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_LINE_SMOOTH_ENABLE, 1);
567         OUT_RING  (0);
568         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_POLYGON_MODE_FRONT, 2);
569         OUT_RING  (0x1b02);
570         OUT_RING  (0x1b02);
571         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_CULL_FACE, 2);
572         OUT_RING  (0x405);
573         OUT_RING  (0x901);
574         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_POLYGON_SMOOTH_ENABLE, 1);
575         OUT_RING  (0);
576         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_CULL_FACE_ENABLE, 1);
577         OUT_RING  (0);
578         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_CLIP_PLANE_ENABLE(0), 8);
579         for (i=0;i<8;i++) {
580                 OUT_RING  (0);
581         }
582         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_FOG_EQUATION_CONSTANT, 3);
583         OUT_RING  (0x3fc00000); /* -1.50 */
584         OUT_RING  (0xbdb8aa0a); /* -0.09 */
585         OUT_RING  (0);          /*  0.00 */
586
587         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_NOP, 1);
588         OUT_RING  (0);
589
590         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_FOG_MODE, 2);
591         OUT_RING  (0x802);
592         OUT_RING  (2);
593         /* for some reason VIEW_MATRIX_ENABLE need to be 6 instead of 4 when
594          * using texturing, except when using the texture matrix
595          */
596         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VIEW_MATRIX_ENABLE, 1);
597         OUT_RING  (6);
598         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_COLOR_MASK, 1);
599         OUT_RING  (0x01010101);
600
601         /* Set vertex component */
602         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_COL_4F_R, 4);
603         OUT_RINGf (1.0);
604         OUT_RINGf (1.0);
605         OUT_RINGf (1.0);
606         OUT_RINGf (1.0);
607         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_COL2_3F_R, 3);
608         OUT_RING  (0);
609         OUT_RING  (0);
610         OUT_RING  (0);
611         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_NOR_3F_X, 3);
612         OUT_RING  (0);
613         OUT_RING  (0);
614         OUT_RINGf (1.0);
615         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_TX0_4F_S, 4);
616         OUT_RINGf (0.0);
617         OUT_RINGf (0.0);
618         OUT_RINGf (0.0);
619         OUT_RINGf (1.0);
620         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_TX1_4F_S, 4);
621         OUT_RINGf (0.0);
622         OUT_RINGf (0.0);
623         OUT_RINGf (0.0);
624         OUT_RINGf (1.0);
625         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_VERTEX_FOG_1F, 1);
626         OUT_RINGf (0.0);
627         BEGIN_RING(Nv3D, NV10_TCL_PRIMITIVE_3D_EDGEFLAG_ENABLE, 1);
628         OUT_RING  (1);
629
630         return TRUE;
631 }
632
633
634
635