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