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