Import nv10 exa code. Does not work yet.
[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 static nv_pict_texture_format_t
136 NV30TextureFormat[] = {
137         _(a8r8g8b8, 0x85,   S1,   S1,   S1,   S1, X, Y, Z, W),
138         _(x8r8g8b8, 0x85,   S1,   S1,   S1,  ONE, X, Y, Z, W),
139         _(x8b8g8r8, 0x85,   S1,   S1,   S1,  ONE, Z, Y, X, W),
140         _(a1r5g5b5, 0x82,   S1,   S1,   S1,   S1, X, Y, Z, W),
141         _(x1r5g5b5, 0x82,   S1,   S1,   S1,  ONE, X, Y, Z, W),
142         _(  r5g6b5, 0x84,   S1,   S1,   S1,   S1, X, Y, Z, W),
143         _(      a8, 0x81, ZERO, ZERO, ZERO,   S1, X, X, X, X),
144         { -1, ~0, ~0 }
145 };
146
147 static nv_pict_texture_format_t *
148 NV30_GetPictTextureFormat(int format)
149 {
150         int i = 0;
151
152         while (NV30TextureFormat[i].pict_fmt != -1) {
153                 if (NV30TextureFormat[i].pict_fmt == format)
154                         return &NV30TextureFormat[i];
155                 i++;
156         }
157
158         return NULL;
159 }
160
161 #define NV30_TCL_PRIMITIVE_3D_BF_ZERO                                     0x0000
162 #define NV30_TCL_PRIMITIVE_3D_BF_ONE                                      0x0001
163 #define NV30_TCL_PRIMITIVE_3D_BF_SRC_COLOR                                0x0300
164 #define NV30_TCL_PRIMITIVE_3D_BF_ONE_MINUS_SRC_COLOR                      0x0301
165 #define NV30_TCL_PRIMITIVE_3D_BF_SRC_ALPHA                                0x0302
166 #define NV30_TCL_PRIMITIVE_3D_BF_ONE_MINUS_SRC_ALPHA                      0x0303
167 #define NV30_TCL_PRIMITIVE_3D_BF_DST_ALPHA                                0x0304
168 #define NV30_TCL_PRIMITIVE_3D_BF_ONE_MINUS_DST_ALPHA                      0x0305
169 #define NV30_TCL_PRIMITIVE_3D_BF_DST_COLOR                                0x0306
170 #define NV30_TCL_PRIMITIVE_3D_BF_ONE_MINUS_DST_COLOR                      0x0307
171 #define NV30_TCL_PRIMITIVE_3D_BF_ALPHA_SATURATE                           0x0308
172 #define BF(bf) NV30_TCL_PRIMITIVE_3D_BF_##bf
173
174 static nv_pict_op_t 
175 NV30PictOp[] = {
176 /* Clear       */ { 0, 0, BF(               ZERO), BF(               ZERO) },
177 /* Src         */ { 0, 0, BF(                ONE), BF(               ZERO) },
178 /* Dst         */ { 0, 0, BF(               ZERO), BF(                ONE) },
179 /* Over        */ { 1, 0, BF(                ONE), BF(ONE_MINUS_SRC_ALPHA) },
180 /* OverReverse */ { 0, 1, BF(ONE_MINUS_DST_ALPHA), BF(                ONE) },
181 /* In          */ { 0, 1, BF(          DST_ALPHA), BF(               ZERO) },
182 /* InReverse   */ { 1, 0, BF(               ZERO), BF(          SRC_ALPHA) },
183 /* Out         */ { 0, 1, BF(ONE_MINUS_DST_ALPHA), BF(               ZERO) },
184 /* OutReverse  */ { 1, 0, BF(               ZERO), BF(ONE_MINUS_SRC_ALPHA) },
185 /* Atop        */ { 1, 1, BF(          DST_ALPHA), BF(ONE_MINUS_SRC_ALPHA) },
186 /* AtopReverse */ { 1, 1, BF(ONE_MINUS_DST_ALPHA), BF(          SRC_ALPHA) },
187 /* Xor         */ { 1, 1, BF(ONE_MINUS_DST_ALPHA), BF(ONE_MINUS_SRC_ALPHA) },
188 /* Add         */ { 0, 0, BF(                ONE), BF(                ONE) }
189 };
190
191 static nv_pict_op_t *
192 NV30_GetPictOpRec(int op)
193 {
194         if (op >= PictOpSaturate)
195                 return NULL;
196         return &NV30PictOp[op];
197 }
198
199 #if 0
200 #define FALLBACK(fmt,args...) do {                                      \
201         ErrorF("FALLBACK %s:%d> " fmt, __func__, __LINE__, ##args);     \
202         return FALSE;                                                   \
203 } while(0)
204 #else
205 #define FALLBACK(fmt,args...) do { \
206         return FALSE;              \
207 } while(0)
208 #endif
209
210 static void
211 NV30_LoadVtxProg(ScrnInfoPtr pScrn, nv_shader_t *shader)
212 {
213         NVPtr pNv = NVPTR(pScrn);
214         static int next_hw_id = 0;
215         int i;
216
217         if (!shader->hw_id) {
218                 shader->hw_id = next_hw_id;
219
220                 NVDmaStart(pNv, Nv3D,
221                                 NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_FROM_ID, 1);
222                 NVDmaNext (pNv, (shader->hw_id));
223
224                 for (i=0; i<shader->size; i+=4) {
225                         NVDmaStart(pNv, Nv3D,
226                                         NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_INST0,
227                                         4);
228                         NVDmaNext (pNv, shader->data[i + 0]);
229                         NVDmaNext (pNv, shader->data[i + 1]);
230                         NVDmaNext (pNv, shader->data[i + 2]);
231                         NVDmaNext (pNv, shader->data[i + 3]);
232                         next_hw_id++;
233                 }
234         }
235
236         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_VP_PROGRAM_START_ID, 1);
237         NVDmaNext (pNv, (shader->hw_id));
238
239         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_VP_IN_REG, 2);
240         NVDmaNext (pNv, shader->card_priv.NV30VP.vp_in_reg);
241         NVDmaNext (pNv, shader->card_priv.NV30VP.vp_out_reg);
242 }
243
244 static void
245 NV30_LoadFragProg(ScrnInfoPtr pScrn, nv_shader_t *shader)
246 {
247         NVPtr pNv = NVPTR(pScrn);
248         static NVAllocRec *fp_mem = NULL;
249         static int next_hw_id_offset = 0;
250
251         if (!fp_mem) {
252                 fp_mem = NVAllocateMemory(pNv, NOUVEAU_MEM_FB, 0x1000);
253                 if (!fp_mem) {
254                         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
255                                    "Couldn't alloc fragprog buffer!\n");
256                         return;
257                 }
258         }
259
260         if (!shader->hw_id) {
261                 memcpy(fp_mem->map + next_hw_id_offset, shader->data,
262                                                         shader->size *
263                                                         sizeof(uint32_t));
264
265                 shader->hw_id  = fp_mem->offset;
266                 shader->hw_id += next_hw_id_offset;
267
268                 next_hw_id_offset += (shader->size * sizeof(uint32_t));
269                 next_hw_id_offset = (next_hw_id_offset + 63) & ~63;
270         }
271
272         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_FP_ACTIVE_PROGRAM, 1);
273         NVDmaNext (pNv, shader->hw_id | 1);
274
275         if (pNv->Architecture == NV_30) {
276                 NVDmaStart(pNv, Nv3D, 0x1d60, 1);
277                 NVDmaNext (pNv, 0); /* USES_KIL (1<<7) == 0 */
278                 NVDmaStart(pNv, Nv3D, 0x1450, 1);
279                 NVDmaNext (pNv, shader->card_priv.NV30FP.num_regs << 16);
280         } else {
281                 NVDmaStart(pNv, Nv3D, 0x1d60, 1);
282                 NVDmaNext (pNv, (0<<7) /* !USES_KIL */ |
283                          (shader->card_priv.NV30FP.num_regs << 24));
284         }
285 }
286
287 static void
288 NV30_SetupBlend(ScrnInfoPtr pScrn, nv_pict_op_t *blend,
289                 PictFormatShort dest_format, Bool component_alpha)
290 {
291         NVPtr pNv = NVPTR(pScrn);
292         uint32_t sblend, dblend;
293
294         sblend = blend->src_card_op;
295         dblend = blend->dst_card_op;
296
297         if (!PICT_FORMAT_A(dest_format) && blend->dst_alpha) {
298                 if (sblend == BF(DST_ALPHA))
299                         sblend = BF(ONE);
300                 else if (sblend == BF(ONE_MINUS_DST_ALPHA))
301                         sblend = BF(ZERO);
302         }
303
304         if (component_alpha && blend->src_alpha) {
305                 if (dblend == BF(SRC_ALPHA))
306                         dblend = BF(SRC_COLOR);
307                 else if (dblend == BF(ONE_MINUS_SRC_ALPHA))
308                         dblend = BF(ONE_MINUS_SRC_COLOR);
309         }
310
311         if (dest_format == PICT_a8 && blend->dst_alpha) {
312                 if (sblend == BF(DST_ALPHA))
313                         sblend = BF(DST_COLOR);
314                 else
315                 if (sblend == BF(ONE_MINUS_DST_ALPHA))
316                         sblend = BF(ONE_MINUS_DST_COLOR);
317         }
318
319         if (sblend == BF(ONE) && dblend == BF(ZERO)) {
320         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_BLEND_FUNC_ENABLE, 1);
321         NVDmaNext (pNv, 0);
322         } else {
323         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_BLEND_FUNC_ENABLE, 5);
324         NVDmaNext (pNv, 1);
325         NVDmaNext (pNv, (sblend << 16) | sblend);
326         NVDmaNext (pNv, (dblend << 16) | dblend);
327         NVDmaNext (pNv, 0x00000000);                    /* Blend colour */
328         NVDmaNext (pNv, (0x8006 << 16) | 0x8006);       /* FUNC_ADD, FUNC_ADD */
329         }
330 }
331
332 static Bool
333 NV30EXATexture(ScrnInfoPtr pScrn, PixmapPtr pPix, PicturePtr pPict, int unit)
334 {
335         NVPtr pNv = NVPTR(pScrn);
336         nv_pict_texture_format_t *fmt;
337         uint32_t card_filter, card_repeat, chipset;
338         NV30EXA_STATE;
339
340         fmt = NV30_GetPictTextureFormat(pPict->format);
341         if (!fmt)
342                 return FALSE;
343
344         if (pPict->repeat && pPict->repeatType == RepeatNormal)
345                 card_repeat = 1;
346         else
347                 card_repeat = 3;
348
349         if (pPict->filter == PictFilterBilinear)
350                 card_filter = 2;
351         else
352                 card_filter = 1;
353
354         chipset = (nvReadMC(pNv, 0) >> 20) & 0xff;
355         if ((chipset & 0xf0) == NV_ARCH_30)
356         {
357                 NVDmaStart(pNv, Nv3D,
358                                 NV30_TCL_PRIMITIVE_3D_TX_ADDRESS_UNIT(unit), 8);
359                 NVDmaNext (pNv, NVAccelGetPixmapOffset(pPix));
360                 NVDmaNext (pNv, (2 << 4)  /* 2D */ |
361                                 (fmt->card_fmt << 8) |
362                                 (1 << 13) /* NPOT */ |
363                                 (1<<16) /* 1 mipmap level */ |
364                                 (1<<0) /* NvDmaFB */ |
365                                 (1<<3) /* border disable? */);
366                 NVDmaNext (pNv, (card_repeat <<  0) /* S */ |
367                                 (card_repeat <<  8) /* T */ |
368                                 (card_repeat << 16) /* R */);
369                 NVDmaNext (pNv, 0x40000000);
370                 NVDmaNext (pNv, (((uint32_t)exaGetPixmapPitch(pPix))<<16) | fmt->card_swz);
371                 NVDmaNext (pNv, (card_filter << 16) /* min */ |
372                                 (card_filter << 24) /* mag */ |
373                                 0x3fd6 /* engine lock */);
374                 NVDmaNext (pNv, (pPix->drawable.width << 16) | pPix->drawable.height);
375                 NVDmaNext (pNv, 0); /* border ARGB */
376                 NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_TX_DEPTH_UNIT(unit), 1);
377                 NVDmaNext (pNv, 0x0);/* there should be an offset here, but what is it for ??? */
378         } else {
379                 NVDmaStart(pNv, Nv3D,
380                                 NV30_TCL_PRIMITIVE_3D_TX_ADDRESS_UNIT(unit), 8);
381                 NVDmaNext (pNv, NVAccelGetPixmapOffset(pPix));
382                 NVDmaNext (pNv, (2 << 4)  /* 2D */ |
383                                 (fmt->card_fmt << 8) |
384                                 (1 << 13) /* NPOT */ |
385                                 (1<<16) /* 1 mipmap level */ |
386                                 (1<<0) /* NvDmaFB */ |
387                                 (1<<3) /* border disable? */);
388                 NVDmaNext (pNv, (card_repeat <<  0) /* S */ |
389                                 (card_repeat <<  8) /* T */ |
390                                 (card_repeat << 16) /* R */);
391                 NVDmaNext (pNv, 0x80000000);
392                 NVDmaNext (pNv, fmt->card_swz);
393                 NVDmaNext (pNv, (card_filter << 16) /* min */ |
394                                 (card_filter << 24) /* mag */ |
395                                 0x3fd6 /* engine lock */);
396                 NVDmaNext (pNv, (pPix->drawable.width << 16) | pPix->drawable.height);
397                 NVDmaNext (pNv, 0); /* border ARGB */
398                 NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_TX_DEPTH_UNIT(unit), 1);
399                 NVDmaNext (pNv, (1 << 20) /* depth */ |
400                                 (uint32_t)exaGetPixmapPitch(pPix));
401         }
402
403                 state->unit[unit].width         = (float)pPix->drawable.width;
404                 state->unit[unit].height        = (float)pPix->drawable.height;
405                 state->unit[unit].transform     = pPict->transform;
406
407         return TRUE;
408 }
409
410 static Bool
411 NV30_SetupSurface(ScrnInfoPtr pScrn, PixmapPtr pPix, PictFormatShort format)
412 {
413         NVPtr pNv = NVPTR(pScrn);
414         nv_pict_surface_format_t *fmt;
415
416         fmt = NV30_GetPictSurfaceFormat(format);
417         if (!fmt) {
418                 ErrorF("AIII no format\n");
419                 return FALSE;
420         }
421
422         NVDmaStart(pNv, Nv3D, 0x208, 3);
423         NVDmaNext (pNv, fmt->card_fmt);
424         NVDmaNext (pNv, (uint32_t)exaGetPixmapPitch(pPix));
425         NVDmaNext (pNv, NVAccelGetPixmapOffset(pPix));
426
427         return TRUE;
428 }
429
430 static Bool
431 NV30EXACheckCompositeTexture(PicturePtr pPict)
432 {
433         nv_pict_texture_format_t *fmt;
434         int w = pPict->pDrawable->width;
435         int h = pPict->pDrawable->height;
436
437         if ((w > 4096) || (h>4096))
438                 FALLBACK("picture too large, %dx%d\n", w, h);
439
440         fmt = NV30_GetPictTextureFormat(pPict->format);
441         if (!fmt)
442                 FALLBACK("picture format 0x%08x not supported\n",
443                                 pPict->format);
444
445         if (pPict->filter != PictFilterNearest &&
446                         pPict->filter != PictFilterBilinear)
447                 FALLBACK("filter 0x%x not supported\n", pPict->filter);
448
449         if (pPict->repeat && (pPict->repeat != RepeatNormal &&
450                                 pPict->repeatType != RepeatNone))
451                 FALLBACK("repeat 0x%x not supported\n", pPict->repeatType);
452
453         return TRUE;
454 }
455
456 Bool
457 NV30EXACheckComposite(int op, PicturePtr psPict,
458                               PicturePtr pmPict,
459                               PicturePtr pdPict)
460 {
461         nv_pict_surface_format_t *fmt;
462         nv_pict_op_t *opr;
463
464         opr = NV30_GetPictOpRec(op);
465         if (!opr)
466                 FALLBACK("unsupported blend op 0x%x\n", op);
467
468         fmt = NV30_GetPictSurfaceFormat(pdPict->format);
469         if (!fmt)
470                 FALLBACK("dst picture format 0x%08x not supported\n",
471                                 pdPict->format);
472
473         if (!NV30EXACheckCompositeTexture(psPict))
474                 FALLBACK("src picture\n");
475         if (pmPict) {
476                 if (pmPict->componentAlpha &&
477                                 PICT_FORMAT_RGB(pmPict->format) &&
478                                 opr->src_alpha && opr->src_card_op != BF(ZERO))
479                         FALLBACK("mask CA + SA\n");
480                 if (!NV30EXACheckCompositeTexture(pmPict))
481                         FALLBACK("mask picture\n");
482         }
483         
484         return TRUE;
485 }
486
487 Bool
488 NV30EXAPrepareComposite(int op, PicturePtr psPict,
489                                 PicturePtr pmPict,
490                                 PicturePtr pdPict,
491                                 PixmapPtr  psPix,
492                                 PixmapPtr  pmPix,
493                                 PixmapPtr  pdPix)
494 {
495         ScrnInfoPtr pScrn = xf86Screens[psPix->drawable.pScreen->myNum];
496         NVPtr pNv = NVPTR(pScrn);
497         nv_pict_op_t *blend;
498         int fpid = NV30EXA_FPID_PASS_COL0;
499         NV30EXA_STATE;
500
501         blend = NV30_GetPictOpRec(op);
502
503         NV30_SetupBlend(pScrn, blend, pdPict->format,
504                         (pmPict && pmPict->componentAlpha &&
505                          PICT_FORMAT_RGB(pmPict->format)));
506
507         NV30_SetupSurface(pScrn, pdPix, pdPict->format);
508         NV30EXATexture(pScrn, psPix, psPict, 0);
509
510         NV30_LoadVtxProg(pScrn, &nv40_vp_exa_render);
511         if (pmPict) {
512                 NV30EXATexture(pScrn, pmPix, pmPict, 1);
513
514                 if (pmPict->componentAlpha && PICT_FORMAT_RGB(pmPict->format)) {
515                         if (blend->src_alpha)
516                                 fpid = NV30EXA_FPID_COMPOSITE_MASK_SA_CA;
517                         else
518                                 fpid = NV30EXA_FPID_COMPOSITE_MASK_CA;
519                 } else {
520                         fpid = NV30EXA_FPID_COMPOSITE_MASK;
521                 }
522
523                 state->have_mask = TRUE;
524         } else {
525                 fpid = NV30EXA_FPID_PASS_TEX0;
526
527                 state->have_mask = FALSE;
528         }
529
530         if (pdPict->format == PICT_a8)
531                 NV30_LoadFragProg(pScrn, nv40_fp_map_a8[fpid]);
532         else
533                 NV30_LoadFragProg(pScrn, nv40_fp_map[fpid]);
534
535         /* Appears to be some kind of cache flush, needed here at least
536          * sometimes.. funky text rendering otherwise :)
537          */
538         NVDmaStart(pNv, Nv3D, 0x1fd8, 1);
539         NVDmaNext (pNv, 2);
540         NVDmaStart(pNv, Nv3D, 0x1fd8, 1);
541         NVDmaNext (pNv, 1);
542
543         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_BEGIN_END, 1);
544         NVDmaNext (pNv, 8); /* GL_QUADS */
545
546         return TRUE;
547 }
548
549 #define xFixedToFloat(v) \
550         ((float)xFixedToInt((v)) + ((float)xFixedFrac(v) / 65536.0))
551
552 static void
553 NV30EXATransformCoord(PictTransformPtr t, int x, int y, float sx, float sy,
554                                           float *x_ret, float *y_ret)
555 {
556         PictVector v;
557
558         if (t) {
559                 v.vector[0] = IntToxFixed(x);
560                 v.vector[1] = IntToxFixed(y);
561                 v.vector[2] = xFixed1;
562                 PictureTransformPoint(t, &v);
563                 *x_ret = xFixedToFloat(v.vector[0]) / sx;
564                 *y_ret = xFixedToFloat(v.vector[1]) / sy;
565         } else {
566                 *x_ret = (float)x / sx;
567                 *y_ret = (float)y / sy;
568         }
569 }
570
571 #define CV_OUTm(sx,sy,mx,my,dx,dy) do {                                        \
572         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_VTX_ATTR_2F_X(8), 4);   \
573         NVDmaFloat(pNv, (sx)); NVDmaFloat(pNv, (sy));                          \
574         NVDmaFloat(pNv, (mx)); NVDmaFloat(pNv, (my));                          \
575         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_VTX_ATTR_2I(0), 1);     \
576         NVDmaNext (pNv, ((dy)<<16)|(dx));                                      \
577 } while(0)
578 #define CV_OUT(sx,sy,dx,dy) do {                                               \
579         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_VTX_ATTR_2F_X(8), 2);   \
580         NVDmaFloat(pNv, (sx)); NVDmaFloat(pNv, (sy));                          \
581         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_VTX_ATTR_2I(0), 1);     \
582         NVDmaNext (pNv, ((dy)<<16)|(dx));                                      \
583 } while(0)
584
585 void
586 NV30EXAComposite(PixmapPtr pdPix, int srcX , int srcY,
587                                   int maskX, int maskY,
588                                   int dstX , int dstY,
589                                   int width, int height)
590 {
591         ScrnInfoPtr pScrn = xf86Screens[pdPix->drawable.pScreen->myNum];
592         NVPtr pNv = NVPTR(pScrn);
593         float sX0, sX1, sY0, sY1;
594         float mX0, mX1, mY0, mY1;
595         NV30EXA_STATE;
596
597         NV30EXATransformCoord(state->unit[0].transform, srcX, srcY,
598                               state->unit[0].width,
599                               state->unit[0].height, &sX0, &sY0);
600         NV30EXATransformCoord(state->unit[0].transform,
601                               srcX + width, srcY + height,
602                               state->unit[0].width,
603                               state->unit[0].height, &sX1, &sY1);
604
605         if (state->have_mask) {
606                 NV30EXATransformCoord(state->unit[1].transform, maskX, maskY,
607                                       state->unit[1].width,
608                                       state->unit[1].height, &mX0, &mY0);
609                 NV30EXATransformCoord(state->unit[1].transform,
610                                       maskX + width, maskY + height,
611                                       state->unit[1].width,
612                                       state->unit[1].height, &mX1, &mY1);
613                 CV_OUTm(sX0 , sY0 , mX0, mY0, dstX        ,          dstY);
614                 CV_OUTm(sX1 , sY0 , mX1, mY0, dstX + width,          dstY);
615                 CV_OUTm(sX1 , sY1 , mX1, mY1, dstX + width, dstY + height);
616                 CV_OUTm(sX0 , sY1 , mX0, mY1, dstX        , dstY + height);
617         } else {
618                 CV_OUT(sX0 , sY0 , dstX        ,          dstY);
619                 CV_OUT(sX1 , sY0 , dstX + width,          dstY);
620                 CV_OUT(sX1 , sY1 , dstX + width, dstY + height);
621                 CV_OUT(sX0 , sY1 , dstX        , dstY + height);
622         }
623
624         NVDmaKickoff(pNv);
625 }
626
627 void
628 NV30EXADoneComposite(PixmapPtr pdPix)
629 {
630         ScrnInfoPtr pScrn = xf86Screens[pdPix->drawable.pScreen->myNum];
631         NVPtr pNv = NVPTR(pScrn);
632
633         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_BEGIN_END, 1);
634         NVDmaNext (pNv, 0);
635 }
636
637 Bool
638 NVAccelInitNV30TCL(ScrnInfoPtr pScrn)
639 {
640         NVPtr pNv = NVPTR(pScrn);
641         static int have_object = FALSE;
642         uint32_t class = 0, chipset;
643         int i;
644
645 #undef  NV30_TCL_PRIMITIVE_3D
646 #define NV30_TCL_PRIMITIVE_3D                 0x0397
647 #define NV30_TCL_PRIMITIVE_3D_CHIPSET_3X_MASK 0x00000003
648 #define NV35_TCL_PRIMITIVE_3D                 0x0497
649 #define NV35_TCL_PRIMITIVE_3D_CHIPSET_3X_MASK 0x000001e0
650 #define NV34_TCL_PRIMITIVE_3D                 0x0697
651 #define NV34_TCL_PRIMITIVE_3D_CHIPSET_3X_MASK 0x00000010
652
653         chipset = (nvReadMC(pNv, 0) >> 20) & 0xff;
654         if ((chipset & 0xf0) != NV_ARCH_30)
655                 return TRUE;
656         chipset &= 0xf;
657
658         if (NV30_TCL_PRIMITIVE_3D_CHIPSET_3X_MASK & (1<<chipset))
659                 class = NV30_TCL_PRIMITIVE_3D;
660         else if (NV35_TCL_PRIMITIVE_3D_CHIPSET_3X_MASK & (1<<chipset))
661                 class = NV35_TCL_PRIMITIVE_3D;
662         else if (NV34_TCL_PRIMITIVE_3D_CHIPSET_3X_MASK & (1<<chipset))
663                 class = NV34_TCL_PRIMITIVE_3D;
664         else {
665                 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
666                            "NV30EXA: Unknown chipset NV3%1x\n", chipset);
667                 return FALSE;
668         }
669
670         if (!have_object) {
671                 if (!NVDmaCreateContextObject(pNv, Nv3D, class))
672                         return FALSE;
673                 have_object = TRUE;
674         }
675
676         NVDmaStart(pNv, Nv3D, 0x180, 1);
677         NVDmaNext (pNv, NvDmaNotifier0);
678         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_SET_OBJECT1, 3);
679         NVDmaNext (pNv, NvDmaFB);
680         NVDmaNext (pNv, NvDmaFB);
681         NVDmaNext (pNv, NvDmaFB);
682         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_SET_OBJECT8, 1);
683         NVDmaNext (pNv, NvDmaFB);
684         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_SET_OBJECT4, 2);
685         NVDmaNext (pNv, NvDmaFB);
686         NVDmaNext (pNv, NvDmaFB);
687         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_SET_OBJECT3, 1);
688         NVDmaNext (pNv, NvDmaFB);
689         NVDmaStart(pNv, Nv3D, 0x1b0, 1);
690         NVDmaNext (pNv, NvDmaFB);
691
692         NVDmaStart(pNv, Nv3D, 0x2b8, 1);
693         NVDmaNext(pNv, 0);
694         NVDmaStart(pNv, Nv3D, 0x200, 2);
695         NVDmaNext(pNv, 0);
696         NVDmaNext(pNv, 0);
697         NVDmaStart(pNv, Nv3D, 0x2c0, 1);
698         NVDmaNext(pNv, 0x0fff0000);
699         NVDmaStart(pNv, Nv3D, 0x2c4, 1);
700         NVDmaNext(pNv, 0x0fff0000);
701         /* voodoo */
702         for(i = 0x2c8; i <= 0x2fc; i += 4)
703         {
704                 NVDmaStart(pNv, Nv3D, i, 1);
705                 NVDmaNext(pNv, 0x0);
706         }
707         NVDmaStart(pNv, Nv3D, 0x02bc, 1);
708         NVDmaNext(pNv, 0);
709         NVDmaStart(pNv, Nv3D, 0x0220, 1);
710         NVDmaNext(pNv, 1);
711         NVDmaStart(pNv, Nv3D, 0x03b0, 1);
712         NVDmaNext(pNv, 0x00100000);
713         NVDmaStart(pNv, Nv3D, 0x1454, 1);
714         NVDmaNext(pNv, 0);
715         NVDmaStart(pNv, Nv3D, 0x1d80, 1);
716         NVDmaNext(pNv, 3);
717         NVDmaStart(pNv, Nv3D, 0x1450, 1);
718         NVDmaNext(pNv, 0x00030004);
719
720         /* NEW */
721         NVDmaStart(pNv, Nv3D, 0x1e98, 1);
722         NVDmaNext(pNv, 0);
723         NVDmaStart(pNv, Nv3D, 0x17e0, 3);
724         NVDmaNext(pNv, 0);
725         NVDmaNext(pNv, 0);
726         NVDmaNext(pNv, 0x3f800000);
727         NVDmaStart(pNv, Nv3D, 0x1f80, 16);
728         NVDmaNext(pNv, 0); 
729         NVDmaNext(pNv, 0); 
730         NVDmaNext(pNv, 0); 
731         NVDmaNext(pNv, 0);
732         NVDmaNext(pNv, 0); 
733         NVDmaNext(pNv, 0); 
734         NVDmaNext(pNv, 0); 
735         NVDmaNext(pNv, 0);
736         NVDmaNext(pNv, 0x0000ffff);
737         NVDmaNext(pNv, 0); 
738         NVDmaNext(pNv, 0); 
739         NVDmaNext(pNv, 0); 
740         NVDmaNext(pNv, 0);
741         NVDmaNext(pNv, 0); 
742         NVDmaNext(pNv, 0); 
743         NVDmaNext(pNv, 0);
744
745         NVDmaStart(pNv, Nv3D, 0x120, 3);
746         NVDmaNext(pNv, 0);
747         NVDmaNext(pNv, 1);
748         NVDmaNext(pNv, 2);
749
750         NVDmaStart(pNv, Nv3D, 0x1d88, 1);
751         NVDmaNext(pNv, 0x00001200);
752
753         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_RC_ENABLE, 1);
754         NVDmaNext       (pNv, 0);
755
756
757         /* identity viewport transform */
758         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_VIEWPORT_XFRM_OX, 8);
759         NVDmaFloat(pNv, 0.0);
760         NVDmaFloat(pNv, 0.0);
761         NVDmaFloat(pNv, 0.0);
762         NVDmaFloat(pNv, 0.0);
763         NVDmaFloat(pNv, 1.0);
764         NVDmaFloat(pNv, 1.0);
765         NVDmaFloat(pNv, 1.0);
766         NVDmaFloat(pNv, 0.0);
767
768         /* default 3D state */
769         /*XXX: replace with the same state that the DRI emits on startup */
770         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_STENCIL_FRONT_ENABLE, 1);
771         NVDmaNext (pNv, 0);
772         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_STENCIL_BACK_ENABLE, 1);
773         NVDmaNext (pNv, 0);
774         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_ALPHA_FUNC_ENABLE, 1);
775         NVDmaNext (pNv, 0);
776         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_DEPTH_WRITE_ENABLE, 2);
777         NVDmaNext (pNv, 0); /* wr disable */
778         NVDmaNext (pNv, 0); /* test disable */
779         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_COLOR_MASK, 1);
780         NVDmaNext (pNv, 0x01010101); /* TR,TR,TR,TR */
781         NVDmaStart(pNv, Nv3D, NV40_TCL_PRIMITIVE_3D_COLOR_MASK_BUFFER123, 1);
782         NVDmaNext (pNv, 0x0000fff0);
783         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_CULL_FACE_ENABLE, 1);
784         NVDmaNext (pNv, 0);
785         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_BLEND_FUNC_ENABLE, 1);
786         NVDmaNext (pNv, 0);
787         NVDmaStart(pNv, Nv3D,
788                         NV30_TCL_PRIMITIVE_3D_COLOR_LOGIC_OP_ENABLE, 2);
789         NVDmaNext (pNv, 0);
790         NVDmaNext (pNv, 0x1503);
791         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_DITHER_ENABLE, 1);
792         NVDmaNext (pNv, 0);
793         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_SHADE_MODEL, 1);
794         NVDmaNext (pNv, 0x1d01); /* GL_SMOOTH */
795         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FACTOR,2);
796         NVDmaFloat(pNv, 0.0);
797         NVDmaFloat(pNv, 0.0);
798         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_POLYGON_MODE_FRONT, 2);
799         NVDmaNext (pNv, 0x1b02); /* FRONT = GL_FILL */
800         NVDmaNext (pNv, 0x1b02); /* BACK  = GL_FILL */
801         NVDmaStart(pNv, Nv3D,
802                         NV30_TCL_PRIMITIVE_3D_POLYGON_STIPPLE_PATTERN(0), 0x20);
803         for (i=0;i<0x20;i++)
804                 NVDmaNext(pNv, 0xFFFFFFFF);
805         for (i=0;i<16;i++) {
806                 NVDmaStart(pNv, Nv3D,
807                                 NV30_TCL_PRIMITIVE_3D_TX_ENABLE_UNIT(i), 1);
808                 NVDmaNext(pNv, 0);
809         }
810
811         NVDmaStart(pNv, Nv3D, 0x1d78, 1);
812         NVDmaNext (pNv, 0x110);
813
814         NVDmaStart(pNv, Nv3D, 0x0220, 1);
815         NVDmaNext (pNv, 1);
816         NVDmaStart(pNv, Nv3D,
817                         NV30_TCL_PRIMITIVE_3D_VIEWPORT_COLOR_BUFFER_DIM0, 2);
818         NVDmaNext (pNv, (4096 << 16));
819         NVDmaNext (pNv, (4096 << 16));
820         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_SCISSOR_WIDTH_XPOS, 2);
821         NVDmaNext (pNv, (4096 << 16));
822         NVDmaNext (pNv, (4096 << 16));
823         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_VIEWPORT_DIMS_0, 2);
824         NVDmaNext (pNv, (4096 << 16));
825         NVDmaNext (pNv, (4096 << 16));
826         NVDmaStart(pNv, Nv3D,
827                         NV30_TCL_PRIMITIVE_3D_VIEWPORT_COLOR_BUFFER_OFS0, 2);
828         NVDmaNext (pNv, (4095 << 16));
829         NVDmaNext (pNv, (4095 << 16));
830
831         return TRUE;
832 }
833
834 Bool
835 NVAccelInitNV40TCL(ScrnInfoPtr pScrn)
836 {
837         NVPtr pNv = NVPTR(pScrn);
838         static int have_object = FALSE;
839         uint32_t class = 0, chipset;
840         int i;
841
842         NV30EXAHackupA8Shaders(pScrn);
843
844 #undef  NV40_TCL_PRIMITIVE_3D
845 #define NV40_TCL_PRIMITIVE_3D                 0x4097
846 #define NV40_TCL_PRIMITIVE_3D_CHIPSET_4X_MASK 0x00000baf
847 #define NV44_TCL_PRIMITIVE_3D                 0x4497
848 #define NV44_TCL_PRIMITIVE_3D_CHIPSET_4X_MASK 0x00005450
849
850         chipset = (nvReadMC(pNv, 0) >> 20) & 0xff;
851         if ((chipset & 0xf0) != NV_ARCH_40)
852                 return TRUE;
853         chipset &= 0xf;
854
855         if (NV40_TCL_PRIMITIVE_3D_CHIPSET_4X_MASK & (1<<chipset))
856                 class = NV40_TCL_PRIMITIVE_3D;
857         else if (NV44_TCL_PRIMITIVE_3D_CHIPSET_4X_MASK & (1<<chipset))
858                 class = NV44_TCL_PRIMITIVE_3D;
859         else {
860                 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
861                            "NV30EXA: Unknown chipset NV4%1x\n", chipset);
862                 return FALSE;
863         }
864
865         if (!have_object) {
866                 if (!NVDmaCreateContextObject(pNv, Nv3D, class))
867                         return FALSE;
868                 have_object = TRUE;
869         }
870
871         NVDmaStart(pNv, Nv3D, 0x180, 1);
872         NVDmaNext (pNv, NvDmaNotifier0);
873         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_SET_OBJECT1, 2);
874         NVDmaNext (pNv, NvDmaFB);
875         NVDmaNext (pNv, NvDmaFB);
876         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_SET_OBJECT8, 1);
877         NVDmaNext (pNv, NvDmaFB);
878         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_SET_OBJECT4, 2);
879         NVDmaNext (pNv, NvDmaFB);
880         NVDmaNext (pNv, NvDmaFB);
881
882         /* voodoo */
883         NVDmaStart(pNv, Nv3D, 0x1ea4, 3);
884         NVDmaNext(pNv, 0x00000010);
885         NVDmaNext(pNv, 0x01000100);
886         NVDmaNext(pNv, 0xff800006);
887         NVDmaStart(pNv, Nv3D, 0x1fc4, 1);
888         NVDmaNext(pNv, 0x06144321);
889         NVDmaStart(pNv, Nv3D, 0x1fc8, 2);
890         NVDmaNext(pNv, 0xedcba987);
891         NVDmaNext(pNv, 0x00000021);
892         NVDmaStart(pNv, Nv3D, 0x1fd0, 1);
893         NVDmaNext(pNv, 0x00171615);
894         NVDmaStart(pNv, Nv3D, 0x1fd4, 1);
895         NVDmaNext(pNv, 0x001b1a19);
896         NVDmaStart(pNv, Nv3D, 0x1ef8, 1);
897         NVDmaNext(pNv, 0x0020ffff);
898         NVDmaStart(pNv, Nv3D, 0x1d64, 1);
899         NVDmaNext(pNv, 0x00d30000);
900         NVDmaStart(pNv, Nv3D, 0x1e94, 1);
901         NVDmaNext(pNv, 0x00000001);
902
903         /* identity viewport transform */
904         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_VIEWPORT_XFRM_OX, 8);
905         NVDmaFloat(pNv, 0.0);
906         NVDmaFloat(pNv, 0.0);
907         NVDmaFloat(pNv, 0.0);
908         NVDmaFloat(pNv, 0.0);
909         NVDmaFloat(pNv, 1.0);
910         NVDmaFloat(pNv, 1.0);
911         NVDmaFloat(pNv, 1.0);
912         NVDmaFloat(pNv, 0.0);
913
914         /* default 3D state */
915         /*XXX: replace with the same state that the DRI emits on startup */
916         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_STENCIL_FRONT_ENABLE, 1);
917         NVDmaNext (pNv, 0);
918         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_STENCIL_BACK_ENABLE, 1);
919         NVDmaNext (pNv, 0);
920         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_ALPHA_FUNC_ENABLE, 1);
921         NVDmaNext (pNv, 0);
922         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_DEPTH_WRITE_ENABLE, 2);
923         NVDmaNext (pNv, 0); /* wr disable */
924         NVDmaNext (pNv, 0); /* test disable */
925         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_COLOR_MASK, 1);
926         NVDmaNext (pNv, 0x01010101); /* TR,TR,TR,TR */
927         NVDmaStart(pNv, Nv3D, NV40_TCL_PRIMITIVE_3D_COLOR_MASK_BUFFER123, 1);
928         NVDmaNext (pNv, 0x0000fff0);
929         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_CULL_FACE_ENABLE, 1);
930         NVDmaNext (pNv, 0);
931         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_BLEND_FUNC_ENABLE, 1);
932         NVDmaNext (pNv, 0);
933         NVDmaStart(pNv, Nv3D,
934                         NV30_TCL_PRIMITIVE_3D_COLOR_LOGIC_OP_ENABLE, 2);
935         NVDmaNext (pNv, 0);
936         NVDmaNext (pNv, 0x1503);
937         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_DITHER_ENABLE, 1);
938         NVDmaNext (pNv, 0);
939         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_SHADE_MODEL, 1);
940         NVDmaNext (pNv, 0x1d01); /* GL_SMOOTH */
941         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FACTOR,2);
942         NVDmaFloat(pNv, 0.0);
943         NVDmaFloat(pNv, 0.0);
944         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_POLYGON_MODE_FRONT, 2);
945         NVDmaNext (pNv, 0x1b02); /* FRONT = GL_FILL */
946         NVDmaNext (pNv, 0x1b02); /* BACK  = GL_FILL */
947         NVDmaStart(pNv, Nv3D,
948                         NV30_TCL_PRIMITIVE_3D_POLYGON_STIPPLE_PATTERN(0), 0x20);
949         for (i=0;i<0x20;i++)
950                 NVDmaNext(pNv, 0xFFFFFFFF);
951         for (i=0;i<16;i++) {
952                 NVDmaStart(pNv, Nv3D,
953                                 NV30_TCL_PRIMITIVE_3D_TX_ENABLE_UNIT(i), 1);
954                 NVDmaNext(pNv, 0);
955         }
956
957         NVDmaStart(pNv, Nv3D, 0x1d78, 1);
958         NVDmaNext (pNv, 0x110);
959
960         NVDmaStart(pNv, Nv3D, 0x0220, 1);
961         NVDmaNext (pNv, 1);
962         NVDmaStart(pNv, Nv3D,
963                         NV30_TCL_PRIMITIVE_3D_VIEWPORT_COLOR_BUFFER_DIM0, 2);
964         NVDmaNext (pNv, (4096 << 16));
965         NVDmaNext (pNv, (4096 << 16));
966         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_SCISSOR_WIDTH_XPOS, 2);
967         NVDmaNext (pNv, (4096 << 16));
968         NVDmaNext (pNv, (4096 << 16));
969         NVDmaStart(pNv, Nv3D, NV30_TCL_PRIMITIVE_3D_VIEWPORT_DIMS_0, 2);
970         NVDmaNext (pNv, (4096 << 16));
971         NVDmaNext (pNv, (4096 << 16));
972         NVDmaStart(pNv, Nv3D,
973                         NV30_TCL_PRIMITIVE_3D_VIEWPORT_COLOR_BUFFER_OFS0, 2);
974         NVDmaNext (pNv, (4095 << 16));
975         NVDmaNext (pNv, (4095 << 16));
976
977         return TRUE;
978 }
979
980 #endif /* ENABLE_NV30EXA */