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