Squashed commit of the following:
[profile/ivi/mesa.git] / src / gallium / drivers / nv50 / nv50_screen.c
1 /*
2  * Copyright 2008 Ben Skeggs
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20  * SOFTWARE.
21  */
22
23 #include "pipe/p_screen.h"
24
25 #include "nv50_context.h"
26 #include "nv50_screen.h"
27 #include "nv50_resource.h"
28
29 #include "nouveau/nouveau_stateobj.h"
30
31 static boolean
32 nv50_screen_is_format_supported(struct pipe_screen *pscreen,
33                                 enum pipe_format format,
34                                 enum pipe_texture_target target,
35                                 unsigned tex_usage, unsigned geom_flags)
36 {
37         if (tex_usage & PIPE_BIND_RENDER_TARGET) {
38                 switch (format) {
39                 case PIPE_FORMAT_B8G8R8X8_UNORM:
40                 case PIPE_FORMAT_B8G8R8A8_UNORM:
41                 case PIPE_FORMAT_B5G6R5_UNORM:
42                 case PIPE_FORMAT_R16G16B16A16_SNORM:
43                 case PIPE_FORMAT_R16G16B16A16_UNORM:
44                 case PIPE_FORMAT_R32G32B32A32_FLOAT:
45                 case PIPE_FORMAT_R16G16_SNORM:
46                 case PIPE_FORMAT_R16G16_UNORM:
47                         return TRUE;
48                 default:
49                         break;
50                 }
51         } else
52         if (tex_usage & PIPE_BIND_DEPTH_STENCIL) {
53                 switch (format) {
54                 case PIPE_FORMAT_Z32_FLOAT:
55                 case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
56                 case PIPE_FORMAT_Z24X8_UNORM:
57                 case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
58                         return TRUE;
59                 default:
60                         break;
61                 }
62         } else {
63                 switch (format) {
64                 case PIPE_FORMAT_B8G8R8A8_UNORM:
65                 case PIPE_FORMAT_B8G8R8X8_UNORM:
66                 case PIPE_FORMAT_B8G8R8A8_SRGB:
67                 case PIPE_FORMAT_B8G8R8X8_SRGB:
68                 case PIPE_FORMAT_B5G5R5A1_UNORM:
69                 case PIPE_FORMAT_B4G4R4A4_UNORM:
70                 case PIPE_FORMAT_B5G6R5_UNORM:
71                 case PIPE_FORMAT_L8_UNORM:
72                 case PIPE_FORMAT_A8_UNORM:
73                 case PIPE_FORMAT_I8_UNORM:
74                 case PIPE_FORMAT_L8A8_UNORM:
75                 case PIPE_FORMAT_DXT1_RGB:
76                 case PIPE_FORMAT_DXT1_RGBA:
77                 case PIPE_FORMAT_DXT3_RGBA:
78                 case PIPE_FORMAT_DXT5_RGBA:
79                 case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
80                 case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
81                 case PIPE_FORMAT_Z32_FLOAT:
82                 case PIPE_FORMAT_R16G16B16A16_SNORM:
83                 case PIPE_FORMAT_R16G16B16A16_UNORM:
84                 case PIPE_FORMAT_R32G32B32A32_FLOAT:
85                 case PIPE_FORMAT_R16G16_SNORM:
86                 case PIPE_FORMAT_R16G16_UNORM:
87                         return TRUE;
88                 default:
89                         break;
90                 }
91         }
92
93         return FALSE;
94 }
95
96 static int
97 nv50_screen_get_param(struct pipe_screen *pscreen, int param)
98 {
99         struct nv50_screen *screen = nv50_screen(pscreen);
100
101         switch (param) {
102         case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS:
103                 return 32;
104         case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS:
105                 return 32;
106         case PIPE_CAP_MAX_COMBINED_SAMPLERS:
107                 return 64;
108         case PIPE_CAP_NPOT_TEXTURES:
109                 return 1;
110         case PIPE_CAP_TWO_SIDED_STENCIL:
111                 return 1;
112         case PIPE_CAP_GLSL:
113                 return 1;
114         case PIPE_CAP_ANISOTROPIC_FILTER:
115                 return 1;
116         case PIPE_CAP_POINT_SPRITE:
117                 return 1;
118         case PIPE_CAP_MAX_RENDER_TARGETS:
119                 return 8;
120         case PIPE_CAP_OCCLUSION_QUERY:
121                 return 1;
122         case PIPE_CAP_TEXTURE_SHADOW_MAP:
123                 return 1;
124         case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
125                 return 13;
126         case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
127                 return 10;
128         case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
129                 return 13;
130         case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
131         case PIPE_CAP_TEXTURE_MIRROR_REPEAT:
132                 return 1;
133         case PIPE_CAP_TGSI_CONT_SUPPORTED:
134                 return 1;
135         case PIPE_CAP_BLEND_EQUATION_SEPARATE:
136                 return 1;
137         case NOUVEAU_CAP_HW_VTXBUF:
138                 return screen->force_push ? 0 : 1;
139         case NOUVEAU_CAP_HW_IDXBUF:
140                 return screen->force_push ? 0 : 1;
141         case PIPE_CAP_INDEP_BLEND_ENABLE:
142                 return 1;
143         case PIPE_CAP_INDEP_BLEND_FUNC:
144                 return 0;
145         case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT:
146         case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER:
147                 return 1;
148         case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT:
149         case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER:
150                 return 0;
151         default:
152                 NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
153                 return 0;
154         }
155 }
156
157 static float
158 nv50_screen_get_paramf(struct pipe_screen *pscreen, int param)
159 {
160         switch (param) {
161         case PIPE_CAP_MAX_LINE_WIDTH:
162         case PIPE_CAP_MAX_LINE_WIDTH_AA:
163                 return 10.0;
164         case PIPE_CAP_MAX_POINT_WIDTH:
165         case PIPE_CAP_MAX_POINT_WIDTH_AA:
166                 return 64.0;
167         case PIPE_CAP_MAX_TEXTURE_ANISOTROPY:
168                 return 16.0;
169         case PIPE_CAP_MAX_TEXTURE_LOD_BIAS:
170                 return 4.0;
171         default:
172                 NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
173                 return 0.0;
174         }
175 }
176
177 static void
178 nv50_screen_destroy(struct pipe_screen *pscreen)
179 {
180         struct nv50_screen *screen = nv50_screen(pscreen);
181         unsigned i;
182
183         for (i = 0; i < 3; i++) {
184                 if (screen->constbuf_parm[i])
185                         nouveau_bo_ref(NULL, &screen->constbuf_parm[i]);
186         }
187
188         if (screen->constbuf_misc[0])
189                 nouveau_bo_ref(NULL, &screen->constbuf_misc[0]);
190         if (screen->tic)
191                 nouveau_bo_ref(NULL, &screen->tic);
192         if (screen->tsc)
193                 nouveau_bo_ref(NULL, &screen->tsc);
194
195         nouveau_notifier_free(&screen->sync);
196         nouveau_grobj_free(&screen->tesla);
197         nouveau_grobj_free(&screen->eng2d);
198         nouveau_grobj_free(&screen->m2mf);
199         nouveau_resource_destroy(&screen->immd_heap[0]);
200         nouveau_resource_destroy(&screen->parm_heap[0]);
201         nouveau_resource_destroy(&screen->parm_heap[1]);
202         nouveau_screen_fini(&screen->base);
203         FREE(screen);
204 }
205
206 #define BGN_RELOC(ch, bo, gr, m, n, fl) \
207    OUT_RELOC(ch, bo, (n << 18) | (gr->subc << 13) | m, fl, 0, 0)
208
209 void
210 nv50_screen_relocs(struct nv50_screen *screen)
211 {
212         struct nouveau_channel *chan = screen->base.channel;
213         struct nouveau_grobj *tesla = screen->tesla;
214         unsigned i;
215         const unsigned rl = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_DUMMY;
216
217         MARK_RING (chan, 28, 26);
218
219         /* cause grobj autobind */
220         BEGIN_RING(chan, tesla, 0x0100, 1);
221         OUT_RING  (chan, 0);
222
223         BGN_RELOC (chan, screen->tic, tesla, NV50TCL_TIC_ADDRESS_HIGH, 2, rl);
224         OUT_RELOCh(chan, screen->tic, 0, rl);
225         OUT_RELOCl(chan, screen->tic, 0, rl);
226
227         BGN_RELOC (chan, screen->tsc, tesla, NV50TCL_TSC_ADDRESS_HIGH, 2, rl);
228         OUT_RELOCh(chan, screen->tsc, 0, rl);
229         OUT_RELOCl(chan, screen->tsc, 0, rl);
230
231         BGN_RELOC (chan, screen->constbuf_misc[0],
232                    tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3, rl);
233         OUT_RELOCh(chan, screen->constbuf_misc[0], 0, rl);
234         OUT_RELOCl(chan, screen->constbuf_misc[0], 0, rl);
235         OUT_RELOC (chan, screen->constbuf_misc[0],
236                    (NV50_CB_PMISC << 16) | 0x0200, rl, 0, 0);
237
238         BGN_RELOC (chan, screen->constbuf_misc[0],
239                    tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3, rl);
240         OUT_RELOCh(chan, screen->constbuf_misc[0], 0x200, rl);
241         OUT_RELOCl(chan, screen->constbuf_misc[0], 0x200, rl);
242         OUT_RELOC (chan, screen->constbuf_misc[0],
243                    (NV50_CB_AUX << 16) | 0x0200, rl, 0, 0);
244
245         for (i = 0; i < 3; ++i) {
246                 BGN_RELOC (chan, screen->constbuf_parm[i],
247                            tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3, rl);
248                 OUT_RELOCh(chan, screen->constbuf_parm[i], 0, rl);
249                 OUT_RELOCl(chan, screen->constbuf_parm[i], 0, rl);
250                 OUT_RELOC (chan, screen->constbuf_parm[i],
251                            ((NV50_CB_PVP + i) << 16) | 0x0800, rl, 0, 0);
252         }
253 }
254
255 struct pipe_screen *
256 nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
257 {
258         struct nv50_screen *screen = CALLOC_STRUCT(nv50_screen);
259         struct nouveau_channel *chan;
260         struct pipe_screen *pscreen;
261         unsigned chipset = dev->chipset;
262         unsigned tesla_class = 0;
263         int ret, i;
264         const unsigned rl = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD;
265
266         if (!screen)
267                 return NULL;
268         pscreen = &screen->base.base;
269
270         ret = nouveau_screen_init(&screen->base, dev);
271         if (ret) {
272                 nv50_screen_destroy(pscreen);
273                 return NULL;
274         }
275         chan = screen->base.channel;
276
277         pscreen->winsys = ws;
278         pscreen->destroy = nv50_screen_destroy;
279         pscreen->get_param = nv50_screen_get_param;
280         pscreen->get_paramf = nv50_screen_get_paramf;
281         pscreen->is_format_supported = nv50_screen_is_format_supported;
282         pscreen->context_create = nv50_create;
283
284         nv50_screen_init_resource_functions(pscreen);
285
286         /* DMA engine object */
287         ret = nouveau_grobj_alloc(chan, 0xbeef5039,
288                 NV50_MEMORY_TO_MEMORY_FORMAT, &screen->m2mf);
289         if (ret) {
290                 NOUVEAU_ERR("Error creating M2MF object: %d\n", ret);
291                 nv50_screen_destroy(pscreen);
292                 return NULL;
293         }
294
295         /* 2D object */
296         ret = nouveau_grobj_alloc(chan, 0xbeef502d, NV50_2D, &screen->eng2d);
297         if (ret) {
298                 NOUVEAU_ERR("Error creating 2D object: %d\n", ret);
299                 nv50_screen_destroy(pscreen);
300                 return NULL;
301         }
302
303         /* 3D object */
304         switch (chipset & 0xf0) {
305         case 0x50:
306                 tesla_class = NV50TCL;
307                 break;
308         case 0x80:
309         case 0x90:
310                 tesla_class = NV84TCL;
311                 break;
312         case 0xa0:
313                 switch (chipset) {
314                 case 0xa0:
315                 case 0xaa:
316                 case 0xac:
317                         tesla_class = NVA0TCL;
318                         break;
319                 default:
320                         tesla_class = NVA8TCL;
321                         break;
322                 }
323                 break;
324         default:
325                 NOUVEAU_ERR("Not a known NV50 chipset: NV%02x\n", chipset);
326                 nv50_screen_destroy(pscreen);
327                 return NULL;
328         }
329
330         ret = nouveau_grobj_alloc(chan, 0xbeef5097, tesla_class,
331                 &screen->tesla);
332         if (ret) {
333                 NOUVEAU_ERR("Error creating 3D object: %d\n", ret);
334                 nv50_screen_destroy(pscreen);
335                 return NULL;
336         }
337
338         /* Sync notifier */
339         ret = nouveau_notifier_alloc(chan, 0xbeef0301, 1, &screen->sync);
340         if (ret) {
341                 NOUVEAU_ERR("Error creating notifier object: %d\n", ret);
342                 nv50_screen_destroy(pscreen);
343                 return NULL;
344         }
345
346         /* Static M2MF init */
347         BEGIN_RING(chan, screen->m2mf,
348                    NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 3);
349         OUT_RING  (chan, screen->sync->handle);
350         OUT_RING  (chan, chan->vram->handle);
351         OUT_RING  (chan, chan->vram->handle);
352
353         /* Static 2D init */
354         BEGIN_RING(chan, screen->eng2d, NV50_2D_DMA_NOTIFY, 4);
355         OUT_RING  (chan, screen->sync->handle);
356         OUT_RING  (chan, chan->vram->handle);
357         OUT_RING  (chan, chan->vram->handle);
358         OUT_RING  (chan, chan->vram->handle);
359         BEGIN_RING(chan, screen->eng2d, NV50_2D_OPERATION, 1);
360         OUT_RING  (chan, NV50_2D_OPERATION_SRCCOPY);
361         BEGIN_RING(chan, screen->eng2d, NV50_2D_CLIP_ENABLE, 1);
362         OUT_RING  (chan, 0);
363         BEGIN_RING(chan, screen->eng2d, 0x0888, 1);
364         OUT_RING  (chan, 1);
365
366         /* Static tesla init */
367         BEGIN_RING(chan, screen->tesla, NV50TCL_COND_MODE, 1);
368         OUT_RING  (chan, NV50TCL_COND_MODE_ALWAYS);
369         BEGIN_RING(chan, screen->tesla, NV50TCL_DMA_NOTIFY, 1);
370         OUT_RING  (chan, screen->sync->handle);
371         BEGIN_RING(chan, screen->tesla, NV50TCL_DMA_ZETA, 11);
372         for (i = 0; i < 11; i++)
373                 OUT_RING  (chan, chan->vram->handle);
374         BEGIN_RING(chan, screen->tesla,
375                    NV50TCL_DMA_COLOR(0), NV50TCL_DMA_COLOR__SIZE);
376         for (i = 0; i < NV50TCL_DMA_COLOR__SIZE; i++)
377                 OUT_RING  (chan, chan->vram->handle);
378
379         BEGIN_RING(chan, screen->tesla, NV50TCL_RT_CONTROL, 1);
380         OUT_RING  (chan, 1);
381
382         /* activate all 32 lanes (threads) in a warp */
383         BEGIN_RING(chan, screen->tesla, NV50TCL_REG_MODE, 1);
384         OUT_RING  (chan, NV50TCL_REG_MODE_STRIPED);
385         BEGIN_RING(chan, screen->tesla, 0x1400, 1);
386         OUT_RING  (chan, 0xf);
387
388         /* max TIC (bits 4:8) & TSC (ignored) bindings, per program type */
389         for (i = 0; i < 3; ++i) {
390                 BEGIN_RING(chan, screen->tesla, NV50TCL_TEX_LIMITS(i), 1);
391                 OUT_RING  (chan, 0x54);
392         }
393
394         /* origin is top left (set to 1 for bottom left) */
395         BEGIN_RING(chan, screen->tesla, NV50TCL_Y_ORIGIN_BOTTOM, 1);
396         OUT_RING  (chan, 0);
397         BEGIN_RING(chan, screen->tesla, NV50TCL_VP_REG_ALLOC_RESULT, 1);
398         OUT_RING  (chan, 8);
399
400         /* constant buffers for immediates and VP/FP parameters */
401         ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, (32 * 4) * 4,
402                              &screen->constbuf_misc[0]);
403         if (ret) {
404                 nv50_screen_destroy(pscreen);
405                 return NULL;
406         }
407         BEGIN_RING(chan, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
408         OUT_RELOCh(chan, screen->constbuf_misc[0], 0, rl);
409         OUT_RELOCl(chan, screen->constbuf_misc[0], 0, rl);
410         OUT_RING  (chan, (NV50_CB_PMISC << 16) | 0x0200);
411         BEGIN_RING(chan, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
412         OUT_RELOCh(chan, screen->constbuf_misc[0], 0x200, rl);
413         OUT_RELOCl(chan, screen->constbuf_misc[0], 0x200, rl);
414         OUT_RING  (chan, (NV50_CB_AUX << 16) | 0x0200);
415
416         for (i = 0; i < 3; i++) {
417                 ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, (256 * 4) * 4,
418                                      &screen->constbuf_parm[i]);
419                 if (ret) {
420                         nv50_screen_destroy(pscreen);
421                         return NULL;
422                 }
423                 BEGIN_RING(chan, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
424                 OUT_RELOCh(chan, screen->constbuf_parm[i], 0, rl);
425                 OUT_RELOCl(chan, screen->constbuf_parm[i], 0, rl);
426                 OUT_RING  (chan, ((NV50_CB_PVP + i) << 16) | 0x0800);
427         }
428
429         if (nouveau_resource_init(&screen->immd_heap[0], 0, 128) ||
430             nouveau_resource_init(&screen->parm_heap[0], 0, 512) ||
431             nouveau_resource_init(&screen->parm_heap[1], 0, 512))
432         {
433                 NOUVEAU_ERR("Error initialising constant buffers.\n");
434                 nv50_screen_destroy(pscreen);
435                 return NULL;
436         }
437
438         ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, 3 * 32 * (8 * 4),
439                              &screen->tic);
440         if (ret) {
441                 nv50_screen_destroy(pscreen);
442                 return NULL;
443         }
444         BEGIN_RING(chan, screen->tesla, NV50TCL_TIC_ADDRESS_HIGH, 3);
445         OUT_RELOCh(chan, screen->tic, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
446         OUT_RELOCl(chan, screen->tic, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
447         OUT_RING  (chan, 3 * 32 - 1);
448
449         ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, 3 * 32 * (8 * 4),
450                              &screen->tsc);
451         if (ret) {
452                 nv50_screen_destroy(pscreen);
453                 return NULL;
454         }
455         BEGIN_RING(chan, screen->tesla, NV50TCL_TSC_ADDRESS_HIGH, 3);
456         OUT_RELOCh(chan, screen->tsc, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
457         OUT_RELOCl(chan, screen->tsc, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
458         OUT_RING  (chan, 0); /* ignored if TSC_LINKED (0x1234) == 1 */
459
460         /* map constant buffers:
461          *  B = buffer ID (maybe more than 1 byte)
462          *  N = CB index used in shader instruction
463          *  P = program type (0 = VP, 2 = GP, 3 = FP)
464          * SET_PROGRAM_CB = 0x000BBNP1
465          */
466         BEGIN_RING_NI(chan, screen->tesla, NV50TCL_SET_PROGRAM_CB, 8);
467         /* bind immediate buffer */
468         OUT_RING  (chan, 0x001 | (NV50_CB_PMISC << 12));
469         OUT_RING  (chan, 0x021 | (NV50_CB_PMISC << 12));
470         OUT_RING  (chan, 0x031 | (NV50_CB_PMISC << 12));
471         /* bind auxiliary constbuf to immediate data bo */
472         OUT_RING  (chan, 0x201 | (NV50_CB_AUX << 12));
473         OUT_RING  (chan, 0x221 | (NV50_CB_AUX << 12));
474         /* bind parameter buffers */
475         OUT_RING  (chan, 0x101 | (NV50_CB_PVP << 12));
476         OUT_RING  (chan, 0x121 | (NV50_CB_PGP << 12));
477         OUT_RING  (chan, 0x131 | (NV50_CB_PFP << 12));
478
479         /* Vertex array limits - max them out */
480         for (i = 0; i < 16; i++) {
481                 BEGIN_RING(chan, screen->tesla,
482                            NV50TCL_VERTEX_ARRAY_LIMIT_HIGH(i), 2);
483                 OUT_RING  (chan, 0x000000ff);
484                 OUT_RING  (chan, 0xffffffff);
485         }
486
487         BEGIN_RING(chan, screen->tesla, NV50TCL_DEPTH_RANGE_NEAR(0), 2);
488         OUT_RINGf (chan, 0.0f);
489         OUT_RINGf (chan, 1.0f);
490
491         /* no dynamic combination of TIC & TSC entries => only BIND_TIC used */
492         BEGIN_RING(chan, screen->tesla, NV50TCL_LINKED_TSC, 1);
493         OUT_RING  (chan, 1);
494
495         BEGIN_RING(chan, screen->tesla, NV50TCL_EDGEFLAG_ENABLE, 1);
496         OUT_RING  (chan, 1); /* default edgeflag to TRUE */
497
498         FIRE_RING (chan);
499
500         screen->force_push = debug_get_bool_option("NV50_ALWAYS_PUSH", FALSE);
501         return pscreen;
502 }
503