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