added NV10 EXA functions to proto header
[nouveau] / src / nv30_exa.c
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4
5 #ifdef ENABLE_NV30EXA
6
7 #include "nv_include.h"
8 #include "nv_shaders.h"
9
10 typedef struct nv_pict_surface_format {
11         int      pict_fmt;
12         uint32_t card_fmt;
13 } nv_pict_surface_format_t;
14
15 typedef struct nv_pict_texture_format {
16         int      pict_fmt;
17         uint32_t card_fmt;
18         uint32_t card_swz;
19 } nv_pict_texture_format_t;
20
21 typedef struct nv_pict_op {
22         Bool     src_alpha;
23         Bool     dst_alpha;
24         uint32_t src_card_op;
25         uint32_t dst_card_op;
26 } nv_pict_op_t;
27
28 typedef struct nv30_exa_state {
29         Bool have_mask;
30
31         struct {
32                 PictTransformPtr transform;
33                 float width;
34                 float height;
35         } unit[2];
36 } nv30_exa_state_t;
37 static nv30_exa_state_t exa_state;
38 #define NV30EXA_STATE nv30_exa_state_t *state = &exa_state
39
40 static nv_pict_surface_format_t
41 NV30SurfaceFormat[] = {
42         { PICT_a8r8g8b8 , 0x148 },
43         { PICT_x8r8g8b8 , 0x145 },
44         { PICT_r5g6b5   , 0x143 },
45 //      { PICT_a8       , 0x149 },
46 };
47
48 static nv_pict_surface_format_t *
49 NV30_GetPictSurfaceFormat(int format)
50 {
51         int i;
52
53         for(i=0;i<sizeof(NV30SurfaceFormat)/sizeof(NV30SurfaceFormat[0]);i++)
54         {
55                 if (NV30SurfaceFormat[i].pict_fmt == format)
56                         return &NV30SurfaceFormat[i];
57         }
58
59         return NULL;
60 }
61
62 enum {
63         NV30EXA_FPID_PASS_COL0 = 0,
64         NV30EXA_FPID_PASS_TEX0 = 1,
65         NV30EXA_FPID_COMPOSITE_MASK = 2,
66         NV30EXA_FPID_COMPOSITE_MASK_SA_CA = 3,
67         NV30EXA_FPID_COMPOSITE_MASK_CA = 4,
68         NV30EXA_FPID_MAX = 5
69 } NV30EXA_FPID;
70
71 static nv_shader_t *nv40_fp_map[NV30EXA_FPID_MAX] = {
72         &nv30_fp_pass_col0,
73         &nv30_fp_pass_tex0,
74         &nv30_fp_composite_mask,
75         &nv30_fp_composite_mask_sa_ca,
76         &nv30_fp_composite_mask_ca
77 };
78
79 static nv_shader_t *nv40_fp_map_a8[NV30EXA_FPID_MAX];
80
81 static void
82 NV30EXAHackupA8Shaders(ScrnInfoPtr pScrn)
83 {
84         int s;
85
86         for (s = 0; s < NV30EXA_FPID_MAX; s++) {
87                 nv_shader_t *def, *a8;
88
89                 def = nv40_fp_map[s];
90                 a8 = xcalloc(1, sizeof(nv_shader_t));
91                 a8->card_priv.NV30FP.num_regs = def->card_priv.NV30FP.num_regs;
92                 a8->size = def->size + 4;
93                 memcpy(a8->data, def->data, def->size * sizeof(uint32_t));
94                 nv40_fp_map_a8[s] = a8;
95
96                 a8->data[a8->size - 8 + 0] &= ~0x00000081;
97                 a8->data[a8->size - 4 + 0]  = 0x01401e81;
98                 a8->data[a8->size - 4 + 1]  = 0x1c9dfe00;
99                 a8->data[a8->size - 4 + 2]  = 0x0001c800;
100                 a8->data[a8->size - 4 + 3]  = 0x0001c800;
101         }
102 }
103
104 /* should be in nouveau_reg.h at some point.. */
105 #define NV30TCL_TX_SWIZZLE_UNIT_S0_X_SHIFT      14
106 #define NV30TCL_TX_SWIZZLE_UNIT_S0_X_ZERO        0
107 #define NV30TCL_TX_SWIZZLE_UNIT_S0_X_ONE         1
108 #define NV30TCL_TX_SWIZZLE_UNIT_S0_X_S1          2
109 #define NV30TCL_TX_SWIZZLE_UNIT_S0_Y_SHIFT      12
110 #define NV30TCL_TX_SWIZZLE_UNIT_S0_Z_SHIFT      10
111 #define NV30TCL_TX_SWIZZLE_UNIT_S0_W_SHIFT       8
112 #define NV30TCL_TX_SWIZZLE_UNIT_S1_X_SHIFT       6
113 #define NV30TCL_TX_SWIZZLE_UNIT_S1_X_X           3
114 #define NV30TCL_TX_SWIZZLE_UNIT_S1_X_Y           2
115 #define NV30TCL_TX_SWIZZLE_UNIT_S1_X_Z           1
116 #define NV30TCL_TX_SWIZZLE_UNIT_S1_X_W           0
117 #define NV30TCL_TX_SWIZZLE_UNIT_S1_Y_SHIFT       4
118 #define NV30TCL_TX_SWIZZLE_UNIT_S1_Z_SHIFT       2
119 #define NV30TCL_TX_SWIZZLE_UNIT_S1_W_SHIFT       0
120
121 #define _(r,tf,ts0x,ts0y,ts0z,ts0w,ts1x,ts1y,ts1z,ts1w)                       \
122   {                                                                           \
123   PICT_##r,                                                                   \
124   (tf),                                                                       \
125   (NV30TCL_TX_SWIZZLE_UNIT_S0_X_##ts0x << NV30TCL_TX_SWIZZLE_UNIT_S0_X_SHIFT)|\
126   (NV30TCL_TX_SWIZZLE_UNIT_S0_X_##ts0y << NV30TCL_TX_SWIZZLE_UNIT_S0_Y_SHIFT)|\
127   (NV30TCL_TX_SWIZZLE_UNIT_S0_X_##ts0z << NV30TCL_TX_SWIZZLE_UNIT_S0_Z_SHIFT)|\
128   (NV30TCL_TX_SWIZZLE_UNIT_S0_X_##ts0w << NV30TCL_TX_SWIZZLE_UNIT_S0_W_SHIFT)|\
129   (NV30TCL_TX_SWIZZLE_UNIT_S1_X_##ts1x << NV30TCL_TX_SWIZZLE_UNIT_S1_X_SHIFT)|\
130   (NV30TCL_TX_SWIZZLE_UNIT_S1_X_##ts1y << NV30TCL_TX_SWIZZLE_UNIT_S1_Y_SHIFT)|\
131   (NV30TCL_TX_SWIZZLE_UNIT_S1_X_##ts1z << NV30TCL_TX_SWIZZLE_UNIT_S1_Z_SHIFT)|\
132   (NV30TCL_TX_SWIZZLE_UNIT_S1_X_##ts1w << NV30TCL_TX_SWIZZLE_UNIT_S1_W_SHIFT)\
133   }
134
135 static nv_pict_texture_format_t
136 NV30TextureFormat[] = {
137         _(a8r8g8b8, 0x12,   S1,   S1,   S1,   S1, X, Y, Z, W),
138         _(a8b8g8r8, 0x12,   S1,   S1,   S1,   S1, Z, Y, X, W),
139         _(x8r8g8b8, 0x12,   S1,   S1,   S1,  ONE, X, Y, Z, W),
140         _(x8b8g8r8, 0x12,   S1,   S1,   S1,  ONE, Z, Y, X, W),
141         _(a1r5g5b5, 0x10,   S1,   S1,   S1,   S1, X, Y, Z, W),
142         _(x1r5g5b5, 0x10,   S1,   S1,   S1,  ONE, X, Y, Z, W),
143         _(x4r4g4b4, 0x1d,   S1,   S1,   S1,  ONE, X, Y, Z, W),
144         _(a4r4g4b4, 0x1d,   S1,   S1,   S1,   S1, X, Y, Z, W),
145         _(      a8, 0x1b, ZERO, ZERO, ZERO,   S1, W, W, W, W),
146 };
147
148
149 static nv_pict_texture_format_t *
150 NV30_GetPictTextureFormat(int format)
151 {
152         int i;
153
154         for(i=0;i<sizeof(NV30TextureFormat)/sizeof(NV30TextureFormat[0]);i++)
155         {
156                 if (NV30TextureFormat[i].pict_fmt == format)
157                         return &NV30TextureFormat[i];
158         }
159
160         return NULL;
161 }
162
163 #define NV34_TCL_PRIMITIVE_3D_BF_ZERO                                     0x0000
164 #define NV34_TCL_PRIMITIVE_3D_BF_ONE                                      0x0001
165 #define NV34_TCL_PRIMITIVE_3D_BF_SRC_COLOR                                0x0300
166 #define NV34_TCL_PRIMITIVE_3D_BF_ONE_MINUS_SRC_COLOR                      0x0301
167 #define NV34_TCL_PRIMITIVE_3D_BF_SRC_ALPHA                                0x0302
168 #define NV34_TCL_PRIMITIVE_3D_BF_ONE_MINUS_SRC_ALPHA                      0x0303
169 #define NV34_TCL_PRIMITIVE_3D_BF_DST_ALPHA                                0x0304
170 #define NV34_TCL_PRIMITIVE_3D_BF_ONE_MINUS_DST_ALPHA                      0x0305
171 #define NV34_TCL_PRIMITIVE_3D_BF_DST_COLOR                                0x0306
172 #define NV34_TCL_PRIMITIVE_3D_BF_ONE_MINUS_DST_COLOR                      0x0307
173 #define NV34_TCL_PRIMITIVE_3D_BF_ALPHA_SATURATE                           0x0308
174 #define BF(bf) NV34_TCL_PRIMITIVE_3D_BF_##bf
175
176 static nv_pict_op_t 
177 NV30PictOp[] = {
178 /* Clear       */ { 0, 0, BF(               ZERO), BF(               ZERO) },
179 /* Src         */ { 0, 0, BF(                ONE), BF(               ZERO) },
180 /* Dst         */ { 0, 0, BF(               ZERO), BF(                ONE) },
181 /* Over        */ { 1, 0, BF(                ONE), BF(ONE_MINUS_SRC_ALPHA) },
182 /* OverReverse */ { 0, 1, BF(ONE_MINUS_DST_ALPHA), BF(                ONE) },
183 /* In          */ { 0, 1, BF(          DST_ALPHA), BF(               ZERO) },
184 /* InReverse   */ { 1, 0, BF(               ZERO), BF(          SRC_ALPHA) },
185 /* Out         */ { 0, 1, BF(ONE_MINUS_DST_ALPHA), BF(               ZERO) },
186 /* OutReverse  */ { 1, 0, BF(               ZERO), BF(ONE_MINUS_SRC_ALPHA) },
187 /* Atop        */ { 1, 1, BF(          DST_ALPHA), BF(ONE_MINUS_SRC_ALPHA) },
188 /* AtopReverse */ { 1, 1, BF(ONE_MINUS_DST_ALPHA), BF(          SRC_ALPHA) },
189 /* Xor         */ { 1, 1, BF(ONE_MINUS_DST_ALPHA), BF(ONE_MINUS_SRC_ALPHA) },
190 /* Add         */ { 0, 0, BF(                ONE), BF(                ONE) }
191 };
192
193 static nv_pict_op_t *
194 NV30_GetPictOpRec(int op)
195 {
196         if (op >= PictOpSaturate)
197                 return NULL;
198 #if 0
199         switch(op)
200         {
201                 case 0:ErrorF("Op Clear\n");break;
202                 case 1:ErrorF("Op Src\n");break;
203                 case 2:ErrorF("Op Dst\n");break;
204                 case 3:ErrorF("Op Over\n");break;
205                 case 4:ErrorF("Op OverReverse\n");break;
206                 case 5:ErrorF("Op In\n");break;
207                 case 6:ErrorF("Op InReverse\n");break;
208                 case 7:ErrorF("Op Out\n");break;
209                 case 8:ErrorF("Op OutReverse\n");break;
210                 case 9:ErrorF("Op Atop\n");break;
211                 case 10:ErrorF("Op AtopReverse\n");break;
212                 case 11:ErrorF("Op Xor\n");break;
213                 case 12:ErrorF("Op Add\n");break;
214         }
215 #endif
216         return &NV30PictOp[op];
217 }
218
219 #define FALLBACK_DEBUG 0
220 #if FALLBACK_DEBUG == 1
221 #define FALLBACK(fmt,args...) do {                                      \
222         ErrorF("FALLBACK %s:%d> " fmt, __func__, __LINE__, ##args);     \
223         return FALSE;                                                   \
224 } while(0)
225 #else
226 #define FALLBACK(fmt,args...) do { \
227         return FALSE;              \
228 } while(0)
229 #endif
230
231 static void
232 NV30_LoadFragProg(ScrnInfoPtr pScrn, nv_shader_t *shader)
233 {
234         NVPtr pNv = NVPTR(pScrn);
235         static NVAllocRec *fp_mem = NULL;
236         static int next_hw_id_offset = 0;
237
238         if (!fp_mem) {
239                 fp_mem = NVAllocateMemory(pNv, NOUVEAU_MEM_FB, 0x1000);
240                 if (!fp_mem) {
241                         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
242                                         "Couldn't alloc fragprog buffer!\n");
243                         return;
244                 }
245         }
246
247         if (!shader->hw_id) {
248                 memcpy(fp_mem->map + next_hw_id_offset, shader->data,
249                                 shader->size *
250                                 sizeof(uint32_t));
251
252                 shader->hw_id  = fp_mem->offset;
253                 shader->hw_id += next_hw_id_offset;
254
255                 next_hw_id_offset += (shader->size * sizeof(uint32_t));
256                 next_hw_id_offset = (next_hw_id_offset + 63) & ~63;
257         }
258
259         BEGIN_RING(Nv3D, NV34_TCL_PRIMITIVE_3D_FP_ACTIVE_PROGRAM, 1);
260         OUT_RING  (shader->hw_id|1);
261
262         BEGIN_RING(Nv3D, 0x23c, 1);
263         OUT_RING  (3);
264         BEGIN_RING(Nv3D, 0x1d60, 1);
265         OUT_RING  (0); /* USES_KIL (1<<7) == 0 */
266         BEGIN_RING(Nv3D, 0x1450, 1);
267         OUT_RING  (shader->card_priv.NV30FP.num_regs << 16| 4);
268         BEGIN_RING(Nv3D, 0x1d7c, 1);
269         OUT_RING  (0xffff0000);
270
271 }
272
273 static void
274 NV30_SetupBlend(ScrnInfoPtr pScrn, nv_pict_op_t *blend,
275                 PictFormatShort dest_format, Bool component_alpha)
276 {
277         NVPtr pNv = NVPTR(pScrn);
278         uint32_t sblend, dblend;
279
280         sblend = blend->src_card_op;
281         dblend = blend->dst_card_op;
282
283         if (blend->dst_alpha) {
284                 if (!PICT_FORMAT_A(dest_format)) {
285                         if (sblend == BF(DST_ALPHA)) {
286                                 sblend = BF(ONE);
287                         } else if (sblend == BF(ONE_MINUS_DST_ALPHA)) {
288                                 sblend = BF(ZERO);
289                         }
290                 } else if (dest_format == PICT_a8) {
291                         if (sblend == BF(DST_ALPHA)) {
292                                 sblend = BF(DST_COLOR);
293                         } else if (sblend == BF(ONE_MINUS_DST_ALPHA)) {
294                                 sblend = BF(ONE_MINUS_DST_COLOR);
295                         }
296                 }
297         }
298
299         if (blend->src_alpha && (component_alpha || dest_format == PICT_a8)) {
300                 if (dblend == BF(SRC_ALPHA)) {
301                         dblend = BF(SRC_COLOR);
302                 } else if (dblend == BF(ONE_MINUS_SRC_ALPHA)) {
303                         dblend = BF(ONE_MINUS_SRC_COLOR);
304                 }
305         }
306
307         if (sblend == BF(ONE) && dblend == BF(ZERO)) {
308                 BEGIN_RING(Nv3D, NV34_TCL_PRIMITIVE_3D_BLEND_FUNC_ENABLE, 1);
309                 OUT_RING  (0);
310         } else {
311                 BEGIN_RING(Nv3D, NV34_TCL_PRIMITIVE_3D_BLEND_FUNC_ENABLE, 5);
312                 OUT_RING  (1);
313                 OUT_RING  ((sblend << 16) | sblend);
314                 OUT_RING  ((dblend << 16) | dblend);
315                 OUT_RING  (0x00000000);                 /* Blend colour */
316                 OUT_RING  ((0x8006 << 16) | 0x8006);    /* FUNC_ADD, FUNC_ADD */
317         }
318 }
319
320 static Bool
321 NV30EXATexture(ScrnInfoPtr pScrn, PixmapPtr pPix, PicturePtr pPict, int unit)
322 {
323         NVPtr pNv = NVPTR(pScrn);
324         nv_pict_texture_format_t *fmt;
325         uint32_t card_filter, card_repeat;
326         NV30EXA_STATE;
327
328         fmt = NV30_GetPictTextureFormat(pPict->format);
329         if (!fmt)
330                 return FALSE;
331
332         card_repeat = 3; /* repeatNone */
333
334         if (pPict->filter == PictFilterBilinear)
335                 card_filter = 2;
336         else
337                 card_filter = 1;
338
339         BEGIN_RING(Nv3D,
340                         NV34_TCL_PRIMITIVE_3D_TX_OFFSET(unit), 8);
341         OUT_RING  (NVAccelGetPixmapOffset(pPix));
342
343         OUT_RING  ((2 << 4) /* 2D */ |
344                         (fmt->card_fmt << 8) |
345                         (1 << 16) /* 1 mipmap level */ |
346 /*                      (log2i(pPix->drawable.width)  << 20) |
347                         (log2i(pPix->drawable.height) << 24) |*/
348                         9);
349
350         OUT_RING  ((card_repeat <<  0) /* S */ |
351                         (card_repeat <<  8) /* T */ |
352                         (card_repeat << 16) /* R */);
353         OUT_RING  (0x40000000); /* enable */
354         OUT_RING  ((((uint32_t)exaGetPixmapPitch(pPix))<<16) | fmt->card_swz);
355
356         OUT_RING  ((card_filter << 16) /* min */ |
357                         (card_filter << 24) /* mag */ |
358                         0x3fd6 /* engine lock */);
359         OUT_RING  ((pPix->drawable.width << 16) | pPix->drawable.height);
360         OUT_RING  (0); /* border ARGB */
361
362         state->unit[unit].width         = (float)pPix->drawable.width;
363         state->unit[unit].height        = (float)pPix->drawable.height;
364         state->unit[unit].transform     = pPict->transform;
365
366         return TRUE;
367 }
368
369 static Bool
370 NV30_SetupSurface(ScrnInfoPtr pScrn, PixmapPtr pPix, PicturePtr pPict)
371 {
372         NVPtr pNv = NVPTR(pScrn);
373         nv_pict_surface_format_t *fmt;
374
375         fmt = NV30_GetPictSurfaceFormat(pPict->format);
376         if (!fmt) {
377                 ErrorF("AIII no format\n");
378                 return FALSE;
379         }
380
381         uint32_t pitch = (uint32_t)exaGetPixmapPitch(pPix);
382
383         int w = pPict->pDrawable->width;
384         int h = pPict->pDrawable->height;
385         BEGIN_RING(Nv3D, NV34_TCL_PRIMITIVE_3D_VIEWPORT_HORIZ, 5);
386         OUT_RING  (w<<16);
387         OUT_RING  (h<<16);
388         OUT_RING  (fmt->card_fmt); /* format */
389         OUT_RING  (pitch << 16 | pitch);
390         OUT_RING  (NVAccelGetPixmapOffset(pPix));
391         BEGIN_RING(Nv3D, NV34_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_HORIZ(0), 2);
392         OUT_RING  ((w-1)<<16);
393         OUT_RING  ((h-1)<<16);
394         BEGIN_RING(Nv3D, NV34_TCL_PRIMITIVE_3D_VIEWPORT_HORIZ, 2);
395         OUT_RING  (w<<16);
396         OUT_RING  (h<<16);
397
398         return TRUE;
399 }
400
401 static Bool
402 NV30EXACheckCompositeTexture(PicturePtr pPict)
403 {
404         nv_pict_texture_format_t *fmt;
405         int w = pPict->pDrawable->width;
406         int h = pPict->pDrawable->height;
407
408         if ((w > 4096) || (h>4096))
409                 FALLBACK("picture too large, %dx%d\n", w, h);
410
411         fmt = NV30_GetPictTextureFormat(pPict->format);
412         if (!fmt)
413                 FALLBACK("picture format 0x%08x not supported\n",
414                                 pPict->format);
415
416         if (pPict->filter != PictFilterNearest &&
417                         pPict->filter != PictFilterBilinear)
418                 FALLBACK("filter 0x%x not supported\n", pPict->filter);
419
420         if (pPict->repeat && pPict->repeatType != RepeatNone)
421                 FALLBACK("repeat 0x%x not supported\n", pPict->repeatType);
422
423         return TRUE;
424 }
425
426 Bool
427 NV30EXACheckComposite(int op, PicturePtr psPict,
428                 PicturePtr pmPict,
429                 PicturePtr pdPict)
430 {
431         nv_pict_surface_format_t *fmt;
432         nv_pict_op_t *opr;
433
434         opr = NV30_GetPictOpRec(op);
435         if (!opr)
436                 FALLBACK("unsupported blend op 0x%x\n", op);
437
438         fmt = NV30_GetPictSurfaceFormat(pdPict->format);
439         if (!fmt)
440                 FALLBACK("dst picture format 0x%08x not supported\n",
441                                 pdPict->format);
442
443         if (!NV30EXACheckCompositeTexture(psPict))
444                 FALLBACK("src picture\n");
445         if (pmPict) {
446                 if (pmPict->componentAlpha &&
447                                 PICT_FORMAT_RGB(pmPict->format) &&
448                                 opr->src_alpha && opr->src_card_op != BF(ZERO))
449                         FALLBACK("mask CA + SA\n");
450                 if (!NV30EXACheckCompositeTexture(pmPict))
451                         FALLBACK("mask picture\n");
452         }
453
454         return TRUE;
455 }
456
457 void NV30_SetVtx(ScrnInfoPtr pScrn, int multitex)
458 {
459         NVPtr pNv = NVPTR(pScrn);
460
461         BEGIN_RING(Nv3D, NV34_TCL_PRIMITIVE_3D_VERTEX_ARRAY_FORMAT(0), 16);
462         OUT_RING  (0x22);
463         OUT_RING  (0x2);
464         OUT_RING  (0x2);
465         OUT_RING  (0x2);
466         OUT_RING  (0x2);
467         OUT_RING  (0x2);
468         OUT_RING  (0x2);
469         OUT_RING  (0x2);
470
471         OUT_RING  (0x22);
472         if (multitex)
473                 OUT_RING  (0x22);
474         else
475                 OUT_RING  (0x02);
476         OUT_RING  (0x2);
477         OUT_RING  (0x2);
478         OUT_RING  (0x2);
479         OUT_RING  (0x2);
480         OUT_RING  (0x2);
481         OUT_RING  (0x2);
482 }
483
484 Bool
485 NV30EXAPrepareComposite(int op, PicturePtr psPict,
486                 PicturePtr pmPict,
487                 PicturePtr pdPict,
488                 PixmapPtr  psPix,
489                 PixmapPtr  pmPix,
490                 PixmapPtr  pdPix)
491 {
492         ScrnInfoPtr pScrn = xf86Screens[psPix->drawable.pScreen->myNum];
493         NVPtr pNv = NVPTR(pScrn);
494         nv_pict_op_t *blend;
495         int fpid = NV30EXA_FPID_PASS_COL0;
496         NV30EXA_STATE;
497
498         blend = NV30_GetPictOpRec(op);
499
500         NV30_SetupBlend(pScrn, blend, pdPict->format,
501                         (pmPict && pmPict->componentAlpha &&
502                          PICT_FORMAT_RGB(pmPict->format)));
503
504         NV30_SetupSurface(pScrn, pdPix, pdPict);
505         NV30EXATexture(pScrn, psPix, psPict, 0);
506
507 #if 0
508 #define printformat(f) ErrorF("(%xh %dbpp A%dR%dG%dB%d)",f,(f>>24),(f&0xf000)>>12,(f&0xf00)>>8,(f&0xf0)>>4,f&0xf)
509         ErrorF("Preparecomposite src(%dx%d)",psPict->pDrawable->width,psPict->pDrawable->height);
510         printformat((psPict->format));
511         ErrorF(" dst(%dx%d)",pdPict->pDrawable->width,pdPict->pDrawable->height);
512         printformat((pdPict->format));
513         if (pmPict)
514         {
515                 ErrorF(" mask(%dx%d)",pmPict->pDrawable->width,pmPict->pDrawable->height);
516                 printformat((pmPict->format));
517         }
518         ErrorF("\n");
519 #endif
520
521         NV30_SetVtx(pScrn,pmPict?1:0);
522         if (pmPict) {
523                 NV30EXATexture(pScrn, pmPix, pmPict, 1);
524
525                 if (pmPict->componentAlpha && PICT_FORMAT_RGB(pmPict->format)) {
526                         if (blend->src_alpha)
527                                 fpid = NV30EXA_FPID_COMPOSITE_MASK_SA_CA;
528                         else
529                                 fpid = NV30EXA_FPID_COMPOSITE_MASK_CA;
530                 } else {
531                         fpid = NV30EXA_FPID_COMPOSITE_MASK;
532                 }
533
534                 state->have_mask = TRUE;
535         } else {
536                 fpid = NV30EXA_FPID_PASS_TEX0;
537
538                 state->have_mask = FALSE;
539         }
540
541         if (pdPict->format == PICT_a8)
542                 NV30_LoadFragProg(pScrn, nv40_fp_map_a8[fpid]);
543         else
544                 NV30_LoadFragProg(pScrn, nv40_fp_map[fpid]);
545
546         BEGIN_RING(Nv3D, NV34_TCL_PRIMITIVE_3D_VERTEX_BEGIN_END, 1);
547         OUT_RING  (8); /* GL_QUADS */
548
549         return TRUE;
550 }
551
552 #define xFixedToFloat(v) \
553         ((float)xFixedToInt((v)) + ((float)xFixedFrac(v) / 65536.0))
554
555 static void
556 NV30EXATransformCoord(PictTransformPtr t, int x, int y, float sx, float sy,
557                                           float *x_ret, float *y_ret)
558 {
559         PictVector v;
560
561         if (t) {
562                 v.vector[0] = IntToxFixed(x);
563                 v.vector[1] = IntToxFixed(y);
564                 v.vector[2] = xFixed1;
565                 PictureTransformPoint(t, &v);
566                 *x_ret = xFixedToFloat(v.vector[0]);
567                 *y_ret = xFixedToFloat(v.vector[1]);
568         } else {
569                 *x_ret = (float)x;
570                 *y_ret = (float)y;
571         }
572 }
573
574 #define CV_OUTm(sx,sy,mx,my,dx,dy) do {                                        \
575         BEGIN_RING(Nv3D, NV34_TCL_PRIMITIVE_3D_VERTEX_ATTR_2F_X(8), 4);        \
576         OUT_RINGf ((sx)); OUT_RINGf ((sy));                          \
577         OUT_RINGf ((mx)); OUT_RINGf ((my));                          \
578         BEGIN_RING(Nv3D, NV34_TCL_PRIMITIVE_3D_VERTEX_ATTR_2I(0), 1);          \
579         OUT_RING  (((dy)<<16)|(dx));                                           \
580 } while(0)
581 #define CV_OUT(sx,sy,dx,dy) do {                                               \
582         BEGIN_RING(Nv3D, NV34_TCL_PRIMITIVE_3D_VERTEX_ATTR_2F_X(8), 2);        \
583         OUT_RINGf ((sx)); OUT_RINGf ((sy));                          \
584         BEGIN_RING(Nv3D, NV34_TCL_PRIMITIVE_3D_VERTEX_ATTR_2I(0), 1);          \
585         OUT_RING  (((dy)<<16)|(dx));                                           \
586 } while(0)
587
588 void
589 NV30EXAComposite(PixmapPtr pdPix, int srcX , int srcY,
590                                   int maskX, int maskY,
591                                   int dstX , int dstY,
592                                   int width, int height)
593 {
594         ScrnInfoPtr pScrn = xf86Screens[pdPix->drawable.pScreen->myNum];
595         NVPtr pNv = NVPTR(pScrn);
596         float sX0, sX1, sY0, sY1;
597         float mX0, mX1, mY0, mY1;
598         NV30EXA_STATE;
599
600 #if 0
601         ErrorF("Composite [%dx%d] (%d,%d)IN(%d,%d)OP(%d,%d)\n",width,height,srcX,srcY,maskX,maskY,dstX,dstY);
602 #endif
603         NV30EXATransformCoord(state->unit[0].transform, srcX, srcY,
604                               state->unit[0].width,
605                               state->unit[0].height, &sX0, &sY0);
606         NV30EXATransformCoord(state->unit[0].transform,
607                               srcX + width, srcY + height,
608                               state->unit[0].width,
609                               state->unit[0].height, &sX1, &sY1);
610
611         if (state->have_mask) {
612                 NV30EXATransformCoord(state->unit[1].transform, maskX, maskY,
613                                       state->unit[1].width,
614                                       state->unit[1].height, &mX0, &mY0);
615                 NV30EXATransformCoord(state->unit[1].transform,
616                                       maskX + width, maskY + height,
617                                       state->unit[1].width,
618                                       state->unit[1].height, &mX1, &mY1);
619                 CV_OUTm(sX0 , sY0 , mX0, mY0, dstX        ,          dstY);
620                 CV_OUTm(sX1 , sY0 , mX1, mY0, dstX + width,          dstY);
621                 CV_OUTm(sX1 , sY1 , mX1, mY1, dstX + width, dstY + height);
622                 CV_OUTm(sX0 , sY1 , mX0, mY1, dstX        , dstY + height);
623         } else {
624                 CV_OUT(sX0 , sY0 , dstX        ,          dstY);
625                 CV_OUT(sX1 , sY0 , dstX + width,          dstY);
626                 CV_OUT(sX1 , sY1 , dstX + width, dstY + height);
627                 CV_OUT(sX0 , sY1 , dstX        , dstY + height);
628         }
629
630         FIRE_RING();
631 }
632
633 void
634 NV30EXADoneComposite(PixmapPtr pdPix)
635 {
636         ScrnInfoPtr pScrn = xf86Screens[pdPix->drawable.pScreen->myNum];
637         NVPtr pNv = NVPTR(pScrn);
638
639         BEGIN_RING(Nv3D, NV34_TCL_PRIMITIVE_3D_VERTEX_BEGIN_END, 1);
640         OUT_RING  (0);
641 }
642
643 Bool
644 NVAccelInitNV30TCL(ScrnInfoPtr pScrn)
645 {
646         NVPtr pNv = NVPTR(pScrn);
647         static int have_object = FALSE;
648         uint32_t class = 0, chipset;
649         int i;
650
651         NV30EXAHackupA8Shaders(pScrn);
652
653 #undef  NV30_TCL_PRIMITIVE_3D
654 #define NV30_TCL_PRIMITIVE_3D                 0x0397
655 #define NV30_TCL_PRIMITIVE_3D_CHIPSET_3X_MASK 0x00000003
656 #define NV35_TCL_PRIMITIVE_3D                 0x0497
657 #define NV35_TCL_PRIMITIVE_3D_CHIPSET_3X_MASK 0x000001e0
658 #define NV34_TCL_PRIMITIVE_3D_CHIPSET_3X_MASK 0x00000010
659
660         chipset = (nvReadMC(pNv, 0) >> 20) & 0xff;
661         if ((chipset & 0xf0) != NV_ARCH_30)
662                 return TRUE;
663         chipset &= 0xf;
664
665         if (NV30_TCL_PRIMITIVE_3D_CHIPSET_3X_MASK & (1<<chipset))
666                 class = NV30_TCL_PRIMITIVE_3D;
667         else if (NV35_TCL_PRIMITIVE_3D_CHIPSET_3X_MASK & (1<<chipset))
668                 class = NV35_TCL_PRIMITIVE_3D;
669         else if (NV34_TCL_PRIMITIVE_3D_CHIPSET_3X_MASK & (1<<chipset))
670                 class = NV34_TCL_PRIMITIVE_3D;
671         else {
672                 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
673                            "NV30EXA: Unknown chipset NV3%1x\n", chipset);
674                 return FALSE;
675         }
676
677         if (!have_object) {
678                 if (!NVDmaCreateContextObject(pNv, Nv3D, class))
679                         return FALSE;
680                 have_object = TRUE;
681         }
682
683         BEGIN_RING(Nv3D, NV34_TCL_PRIMITIVE_3D_DMA_IN_MEMORY0, 3);
684         OUT_RING  (NvDmaFB);
685         OUT_RING  (NvDmaFB);
686         OUT_RING  (NvDmaFB);
687         BEGIN_RING(Nv3D, NV34_TCL_PRIMITIVE_3D_DMA_IN_MEMORY7, 1);
688         OUT_RING  (NvDmaFB);
689         BEGIN_RING(Nv3D, NV34_TCL_PRIMITIVE_3D_DMA_IN_MEMORY3, 2);
690         OUT_RING  (NvDmaFB);
691         OUT_RING  (NvDmaFB);
692         BEGIN_RING(Nv3D, NV34_TCL_PRIMITIVE_3D_DMA_IN_MEMORY8, 1);
693         OUT_RING  (NvDmaFB);
694
695         for(i = 0x2c8; i <= 0x2fc; i += 4)
696         {
697                 BEGIN_RING(Nv3D, i, 1);
698                 OUT_RING  (0x0);
699         }
700
701         BEGIN_RING(Nv3D, 0x220, 1);
702         OUT_RING  (1);
703
704         BEGIN_RING(Nv3D, 0x03b0, 1);
705         OUT_RING  (0x00100000);
706         BEGIN_RING(Nv3D, 0x1454, 1);
707         OUT_RING  (0);
708         BEGIN_RING(Nv3D, 0x1d80, 1);
709         OUT_RING  (3);
710         
711         /* NEW */
712         BEGIN_RING(Nv3D, 0x1e98, 1);
713         OUT_RING  (0);
714         BEGIN_RING(Nv3D, 0x17e0, 3);
715         OUT_RING  (0);
716         OUT_RING  (0);
717         OUT_RING  (0x3f800000);
718         BEGIN_RING(Nv3D, 0x1f80, 16);
719         OUT_RING  (0); OUT_RING  (0); OUT_RING  (0); OUT_RING  (0); 
720         OUT_RING  (0); OUT_RING  (0); OUT_RING  (0); OUT_RING  (0); 
721         OUT_RING  (0x0000ffff);
722         OUT_RING  (0); OUT_RING  (0); OUT_RING  (0); OUT_RING  (0); 
723         OUT_RING  (0); OUT_RING  (0); OUT_RING  (0); 
724
725         BEGIN_RING(Nv3D, 0x120, 3);
726         OUT_RING  (0);
727         OUT_RING  (1);
728         OUT_RING  (2);
729
730         BEGIN_RING(Nv3D, 0x1d88, 1);
731         OUT_RING  (0x00001200);
732
733         BEGIN_RING(Nv3D, NV34_TCL_PRIMITIVE_3D_RC_ENABLE, 1);
734         OUT_RING  (0);
735
736         /* Attempt to setup a known state.. Probably missing a heap of
737          * stuff here..
738          */
739         BEGIN_RING(Nv3D, NV34_TCL_PRIMITIVE_3D_STENCIL_FRONT_ENABLE, 1);
740         OUT_RING  (0);
741         BEGIN_RING(Nv3D, NV34_TCL_PRIMITIVE_3D_STENCIL_BACK_ENABLE, 1);
742         OUT_RING  (0);
743         BEGIN_RING(Nv3D, NV34_TCL_PRIMITIVE_3D_ALPHA_FUNC_ENABLE, 1);
744         OUT_RING  (0);
745         BEGIN_RING(Nv3D, NV34_TCL_PRIMITIVE_3D_DEPTH_WRITE_ENABLE, 2);
746         OUT_RING  (0); /* wr disable */
747         OUT_RING  (0); /* test disable */
748         BEGIN_RING(Nv3D, NV34_TCL_PRIMITIVE_3D_COLOR_MASK, 1);
749         OUT_RING  (0x01010101); /* TR,TR,TR,TR */
750         BEGIN_RING(Nv3D, NV34_TCL_PRIMITIVE_3D_CULL_FACE_ENABLE, 1);
751         OUT_RING  (0);
752         BEGIN_RING(Nv3D, NV34_TCL_PRIMITIVE_3D_BLEND_FUNC_ENABLE, 1);
753         OUT_RING  (0);
754         BEGIN_RING(Nv3D, NV34_TCL_PRIMITIVE_3D_COLOR_LOGIC_OP_ENABLE, 2);
755         OUT_RING  (0);
756         OUT_RING  (0x1503 /*GL_COPY*/);
757         BEGIN_RING(Nv3D, NV34_TCL_PRIMITIVE_3D_DITHER_ENABLE, 1);
758         OUT_RING  (1);
759         BEGIN_RING(Nv3D, NV34_TCL_PRIMITIVE_3D_SHADE_MODEL, 1);
760         OUT_RING  (0x1d01 /*GL_SMOOTH*/);
761         BEGIN_RING(Nv3D, NV34_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FACTOR,2);
762         OUT_RINGf (0.0);
763         OUT_RINGf (0.0);
764         BEGIN_RING(Nv3D, NV34_TCL_PRIMITIVE_3D_POLYGON_MODE_FRONT, 2);
765         OUT_RING  (0x1b02 /*GL_FILL*/);
766         OUT_RING  (0x1b02 /*GL_FILL*/);
767         /* - Disable texture units
768          * - Set fragprog to MOVR result.color, fragment.color */
769         for (i=0;i<16;i++) {
770                 BEGIN_RING(Nv3D,
771                                 NV34_TCL_PRIMITIVE_3D_TX_ENABLE(i), 1);
772                 OUT_RING  (0);
773         }
774         /* Polygon stipple */
775         BEGIN_RING(Nv3D,
776                         NV34_TCL_PRIMITIVE_3D_POLYGON_STIPPLE_PATTERN(0), 0x20);
777         for (i=0;i<0x20;i++)
778                 OUT_RING  (0xFFFFFFFF);
779
780         /* Ok.  If you start X with the nvidia driver, kill it, and then
781          * start X with nouveau you will get black rendering instead of
782          * what you'd expect.  This fixes the problem, and it seems that
783          * it's not needed between nouveau restarts - which suggests that
784          * the 3D context (wherever it's stored?) survives somehow.
785          */
786         //BEGIN_RING(Nv3D, 0x1d60,1);
787         //OUT_RING  (0x03008000);
788
789         int w=4096;
790         int h=4096;
791         int pitch=4096*4;
792         BEGIN_RING(Nv3D, NV34_TCL_PRIMITIVE_3D_VIEWPORT_HORIZ, 5);
793         OUT_RING  (w<<16);
794         OUT_RING  (h<<16);
795         OUT_RING  (0x148); /* format */
796         OUT_RING  (pitch << 16 | pitch);
797         OUT_RING  (0x0);
798         BEGIN_RING(Nv3D, NV34_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_HORIZ(0), 2);
799         OUT_RING  ((w-1)<<16);
800         OUT_RING  ((h-1)<<16);
801         BEGIN_RING(Nv3D, NV34_TCL_PRIMITIVE_3D_SCISSOR_HORIZ, 2);
802         OUT_RING  (w<<16);
803         OUT_RING  (h<<16);
804         BEGIN_RING(Nv3D, NV34_TCL_PRIMITIVE_3D_VIEWPORT_HORIZ, 2);
805         OUT_RING  (w<<16);
806         OUT_RING  (h<<16);
807
808         BEGIN_RING(Nv3D, NV34_TCL_PRIMITIVE_3D_VIEWPORT_SCALE0_X, 8);
809         OUT_RINGf (0.0);
810         OUT_RINGf (0.0);
811         OUT_RINGf (0.0);
812         OUT_RINGf (0.0);
813         OUT_RINGf (1.0);
814         OUT_RINGf (1.0);
815         OUT_RINGf (1.0);
816         OUT_RINGf (0.0);
817
818         BEGIN_RING(Nv3D, NV34_TCL_PRIMITIVE_3D_MODELVIEW_MATRIX(0), 16);
819         OUT_RINGf (1.0);
820         OUT_RINGf (0.0);
821         OUT_RINGf (0.0);
822         OUT_RINGf (0.0);
823         OUT_RINGf (0.0);
824         OUT_RINGf (1.0);
825         OUT_RINGf (0.0);
826         OUT_RINGf (0.0);
827         OUT_RINGf (0.0);
828         OUT_RINGf (0.0);
829         OUT_RINGf (1.0);
830         OUT_RINGf (0.0);
831         OUT_RINGf (0.0);
832         OUT_RINGf (0.0);
833         OUT_RINGf (0.0);
834         OUT_RINGf (1.0);
835
836         BEGIN_RING(Nv3D, NV34_TCL_PRIMITIVE_3D_PROJECTION_MATRIX(0), 16);
837         OUT_RINGf (1.0);
838         OUT_RINGf (0.0);
839         OUT_RINGf (0.0);
840         OUT_RINGf (0.0);
841         OUT_RINGf (0.0);
842         OUT_RINGf (1.0);
843         OUT_RINGf (0.0);
844         OUT_RINGf (0.0);
845         OUT_RINGf (0.0);
846         OUT_RINGf (0.0);
847         OUT_RINGf (1.0);
848         OUT_RINGf (0.0);
849         OUT_RINGf (0.0);
850         OUT_RINGf (0.0);
851         OUT_RINGf (0.0);
852         OUT_RINGf (1.0);
853
854         BEGIN_RING(Nv3D, NV34_TCL_PRIMITIVE_3D_SCISSOR_HORIZ, 2);
855         OUT_RING  (4096<<16);
856         OUT_RING  (4096<<16);
857
858         return TRUE;
859 }
860
861
862
863 #endif /* ENABLE_NV30EXA */