Initial DRI2 support.
[nouveau] / src / nv_accel_common.c
1 /*
2  * Copyright 2007 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 "nv_include.h"
24
25 static Bool
26 NVAccelInitDmaNotifier0(ScrnInfoPtr pScrn)
27 {
28         NVPtr pNv = NVPTR(pScrn);
29
30         if (!pNv->notify0) {
31                 if (nouveau_notifier_alloc(pNv->chan, NvDmaNotifier0, 1,
32                                            &pNv->notify0))
33                         return FALSE;
34         }
35
36         return TRUE;
37 }
38
39 /* FLAGS_ROP_AND, DmaFB, DmaFB, 0 */
40 static Bool
41 NVAccelInitContextSurfaces(ScrnInfoPtr pScrn)
42 {
43         NVPtr pNv = NVPTR(pScrn);
44         struct nouveau_channel *chan = pNv->chan;
45         struct nouveau_grobj *surf2d;
46         uint32_t class;
47
48         class = (pNv->Architecture >= NV_10) ? NV10_CONTEXT_SURFACES_2D :
49                                                NV04_CONTEXT_SURFACES_2D;
50
51         if (!pNv->NvContextSurfaces) {
52                 if (nouveau_grobj_alloc(chan, NvContextSurfaces, class,
53                                         &pNv->NvContextSurfaces))
54                         return FALSE;
55         }
56         surf2d = pNv->NvContextSurfaces;
57
58         BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_DMA_NOTIFY, 1);
59         OUT_RING  (chan, chan->nullobj->handle);
60         BEGIN_RING(chan, surf2d,
61                    NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2);
62         OUT_RING  (chan, pNv->chan->vram->handle);
63         OUT_RING  (chan, pNv->chan->vram->handle);
64
65         return TRUE;
66 }
67
68 /* FLAGS_ROP_AND, DmaFB, DmaFB, 0 */
69 static Bool
70 NVAccelInitContextBeta1(ScrnInfoPtr pScrn)
71 {
72         NVPtr pNv = NVPTR(pScrn);
73         struct nouveau_channel *chan = pNv->chan;
74         struct nouveau_grobj *beta1;
75
76         if (!pNv->NvContextBeta1) {
77                 if (nouveau_grobj_alloc(chan, NvContextBeta1, 0x12,
78                                         &pNv->NvContextBeta1))
79                         return FALSE;
80         }
81         beta1 = pNv->NvContextBeta1;
82
83         BEGIN_RING(chan, beta1, 0x300, 1); /*alpha factor*/
84         OUT_RING  (chan, 0xff << 23);
85
86         return TRUE;
87 }
88
89
90 static Bool
91 NVAccelInitContextBeta4(ScrnInfoPtr pScrn)
92 {
93         NVPtr pNv = NVPTR(pScrn);
94         struct nouveau_channel *chan = pNv->chan;
95         struct nouveau_grobj *beta4;
96         
97         if (!pNv->NvContextBeta4) {
98                 if (nouveau_grobj_alloc(chan, NvContextBeta4, 0x72,
99                                         &pNv->NvContextBeta4))
100                         return FALSE;
101         }
102         beta4 = pNv->NvContextBeta4;
103
104         BEGIN_RING(chan, beta4, 0x300, 1); /*RGBA factor*/
105         OUT_RING  (chan, 0xffff0000);
106         return TRUE;
107 }
108
109 Bool
110 NVAccelGetCtxSurf2DFormatFromPixmap(PixmapPtr pPix, int *fmt_ret)
111 {
112         switch (pPix->drawable.bitsPerPixel) {
113         case 32:
114                 *fmt_ret = NV04_CONTEXT_SURFACES_2D_FORMAT_A8R8G8B8;
115                 break;
116         case 24:
117                 *fmt_ret = NV04_CONTEXT_SURFACES_2D_FORMAT_X8R8G8B8_Z8R8G8B8;
118                 break;
119         case 16:
120                 *fmt_ret = NV04_CONTEXT_SURFACES_2D_FORMAT_R5G6B5;
121                 break;
122         case 8:
123                 *fmt_ret = NV04_CONTEXT_SURFACES_2D_FORMAT_Y8;
124                 break;
125         default:
126                 return FALSE;
127         }
128
129         return TRUE;
130 }
131
132 Bool
133 NVAccelGetCtxSurf2DFormatFromPicture(PicturePtr pPict, int *fmt_ret)
134 {
135         switch (pPict->format) {
136         case PICT_a8r8g8b8:
137                 *fmt_ret = NV04_CONTEXT_SURFACES_2D_FORMAT_A8R8G8B8;
138                 break;
139         case PICT_x8r8g8b8:
140                 *fmt_ret = NV04_CONTEXT_SURFACES_2D_FORMAT_X8R8G8B8_Z8R8G8B8;
141                 break;
142         case PICT_r5g6b5:
143                 *fmt_ret = NV04_CONTEXT_SURFACES_2D_FORMAT_R5G6B5;
144                 break;
145         case PICT_a8:
146                 *fmt_ret = NV04_CONTEXT_SURFACES_2D_FORMAT_Y8;
147                 break;
148         default:
149                 return FALSE;
150         }
151
152         return TRUE;
153 }
154
155 /* A copy of exaGetOffscreenPixmap(), since it's private. */
156 PixmapPtr
157 NVGetDrawablePixmap(DrawablePtr pDraw)
158 {
159         if (pDraw->type == DRAWABLE_WINDOW)
160                 return pDraw->pScreen->GetWindowPixmap ((WindowPtr) pDraw);
161         else
162                 return (PixmapPtr) pDraw;
163 }
164
165 static Bool
166 NVAccelInitImagePattern(ScrnInfoPtr pScrn)
167 {
168         NVPtr pNv = NVPTR(pScrn);
169         struct nouveau_channel *chan = pNv->chan;
170         struct nouveau_grobj *patt;
171
172         if (!pNv->NvImagePattern) {
173                 if (nouveau_grobj_alloc(chan, NvImagePattern,
174                                         NV04_IMAGE_PATTERN,
175                                         &pNv->NvImagePattern))
176                         return FALSE;
177         }
178         patt = pNv->NvImagePattern;
179
180         BEGIN_RING(chan, patt, NV04_IMAGE_PATTERN_DMA_NOTIFY, 1);
181         OUT_RING  (chan, chan->nullobj->handle);
182         BEGIN_RING(chan, patt, NV04_IMAGE_PATTERN_MONOCHROME_FORMAT, 3);
183 #if X_BYTE_ORDER == X_BIG_ENDIAN
184         OUT_RING  (chan, NV04_IMAGE_PATTERN_MONOCHROME_FORMAT_LE);
185 #else
186         OUT_RING  (chan, NV04_IMAGE_PATTERN_MONOCHROME_FORMAT_CGA6);
187 #endif
188         OUT_RING  (chan, NV04_IMAGE_PATTERN_MONOCHROME_SHAPE_8X8);
189         OUT_RING  (chan, NV04_IMAGE_PATTERN_PATTERN_SELECT_MONO);
190
191         return TRUE;
192 }
193
194 static Bool
195 NVAccelInitRasterOp(ScrnInfoPtr pScrn)
196 {
197         NVPtr pNv = NVPTR(pScrn);
198         struct nouveau_channel *chan = pNv->chan;
199         struct nouveau_grobj *rop;
200
201         if (!pNv->NvRop) {
202                 if (nouveau_grobj_alloc(chan, NvRop, NV03_CONTEXT_ROP,
203                                         &pNv->NvRop))
204                         return FALSE;
205         }
206         rop = pNv->NvRop;
207
208         BEGIN_RING(chan, rop, NV03_CONTEXT_ROP_DMA_NOTIFY, 1);
209         OUT_RING  (chan, chan->nullobj->handle);
210
211         pNv->currentRop = ~0;
212         return TRUE;
213 }
214
215 static Bool
216 NVAccelInitRectangle(ScrnInfoPtr pScrn)
217 {
218         NVPtr pNv = NVPTR(pScrn);
219         struct nouveau_channel *chan = pNv->chan;
220         struct nouveau_grobj *rect;
221
222         if (!pNv->NvRectangle) {
223                 if (nouveau_grobj_alloc(chan, NvRectangle,
224                                         NV04_GDI_RECTANGLE_TEXT,
225                                         &pNv->NvRectangle))
226                         return FALSE;
227         }
228         rect = pNv->NvRectangle;
229
230         BEGIN_RING(chan, rect, NV04_GDI_RECTANGLE_TEXT_DMA_NOTIFY, 1);
231         OUT_RING  (chan, pNv->notify0->handle);
232         BEGIN_RING(chan, rect, NV04_GDI_RECTANGLE_TEXT_DMA_FONTS, 1);
233         OUT_RING  (chan, chan->nullobj->handle);
234         BEGIN_RING(chan, rect, NV04_GDI_RECTANGLE_TEXT_SURFACE, 1);
235         OUT_RING  (chan, pNv->NvContextSurfaces->handle);
236         BEGIN_RING(chan, rect, NV04_GDI_RECTANGLE_TEXT_ROP, 1);
237         OUT_RING  (chan, pNv->NvRop->handle);
238         BEGIN_RING(chan, rect, NV04_GDI_RECTANGLE_TEXT_PATTERN, 1);
239         OUT_RING  (chan, pNv->NvImagePattern->handle);
240         BEGIN_RING(chan, rect, NV04_GDI_RECTANGLE_TEXT_OPERATION, 1);
241         OUT_RING  (chan, NV04_GDI_RECTANGLE_TEXT_OPERATION_ROP_AND);
242         BEGIN_RING(chan, rect, NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT, 1);
243         /* XXX why putting 1 like renouveau dump, swap the text */
244 #if 1 || X_BYTE_ORDER == X_BIG_ENDIAN
245         OUT_RING  (chan, NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT_LE);
246 #else
247         OUT_RING  (chan, NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT_CGA6);
248 #endif
249
250         return TRUE;
251 }
252
253 static Bool
254 NVAccelInitImageBlit(ScrnInfoPtr pScrn)
255 {
256         NVPtr pNv = NVPTR(pScrn);
257         struct nouveau_channel *chan = pNv->chan;
258         struct nouveau_grobj *blit;
259         uint32_t class;
260
261         class = (pNv->WaitVSyncPossible) ? NV12_IMAGE_BLIT : NV04_IMAGE_BLIT;
262
263         if (!pNv->NvImageBlit) {
264                 if (nouveau_grobj_alloc(chan, NvImageBlit, class,
265                                         &pNv->NvImageBlit))
266                         return FALSE;
267         }
268         blit = pNv->NvImageBlit;
269
270         BEGIN_RING(chan, blit, NV04_IMAGE_BLIT_DMA_NOTIFY, 1);
271         OUT_RING  (chan, pNv->notify0->handle);
272         BEGIN_RING(chan, blit, NV04_IMAGE_BLIT_COLOR_KEY, 1);
273         OUT_RING  (chan, chan->nullobj->handle);
274         BEGIN_RING(chan, blit, NV04_IMAGE_BLIT_SURFACE, 1);
275         OUT_RING  (chan, pNv->NvContextSurfaces->handle);
276         BEGIN_RING(chan, blit, NV04_IMAGE_BLIT_CLIP_RECTANGLE, 3);
277         OUT_RING  (chan, chan->nullobj->handle);
278         OUT_RING  (chan, pNv->NvImagePattern->handle);
279         OUT_RING  (chan, pNv->NvRop->handle);
280         BEGIN_RING(chan, blit, NV04_IMAGE_BLIT_OPERATION, 1);
281         OUT_RING  (chan, NV04_IMAGE_BLIT_OPERATION_ROP_AND);
282
283         if (pNv->WaitVSyncPossible) {
284                 BEGIN_RING(chan, blit, 0x0120, 3);
285                 OUT_RING  (chan, 0);
286                 OUT_RING  (chan, 1);
287                 OUT_RING  (chan, 2);
288         }
289
290         return TRUE;
291 }
292
293 static Bool
294 NVAccelInitScaledImage(ScrnInfoPtr pScrn)
295 {
296         NVPtr pNv = NVPTR(pScrn);
297         struct nouveau_channel *chan = pNv->chan;
298         struct nouveau_grobj *sifm;
299         uint32_t class;
300
301         switch (pNv->Architecture) {
302         case NV_ARCH_04:
303                 class = NV04_SCALED_IMAGE_FROM_MEMORY;
304                 break;
305         case NV_ARCH_10:
306         case NV_ARCH_20:
307         case NV_ARCH_30:
308                 class = NV10_SCALED_IMAGE_FROM_MEMORY;
309                 break;
310         case NV_ARCH_40:
311         default:
312                 class = NV10_SCALED_IMAGE_FROM_MEMORY | 0x3000;
313                 break;
314         }
315
316         if (!pNv->NvScaledImage) {
317                 if (nouveau_grobj_alloc(chan, NvScaledImage, class,
318                                         &pNv->NvScaledImage))
319                         return FALSE;
320         }
321         sifm = pNv->NvScaledImage;
322
323         BEGIN_RING(chan, sifm,
324                          NV04_SCALED_IMAGE_FROM_MEMORY_DMA_NOTIFY, 7);
325         OUT_RING  (chan, pNv->notify0->handle);
326         OUT_RING  (chan, pNv->chan->vram->handle);
327         OUT_RING  (chan, chan->nullobj->handle);
328         OUT_RING  (chan, chan->nullobj->handle);
329         OUT_RING  (chan, pNv->NvContextBeta1->handle);
330         OUT_RING  (chan, pNv->NvContextBeta4->handle);
331         OUT_RING  (chan, pNv->NvContextSurfaces->handle);
332         if (pNv->Architecture>=NV_ARCH_10) {
333         BEGIN_RING(chan, sifm,
334                          NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION, 1);
335         OUT_RING  (chan, NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_DITHER);
336         }
337         BEGIN_RING(chan, sifm, NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION, 1);
338         OUT_RING  (chan, NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY);
339
340         return TRUE;
341 }
342
343 static Bool
344 NVAccelInitClipRectangle(ScrnInfoPtr pScrn)
345 {
346         NVPtr pNv = NVPTR(pScrn);
347         struct nouveau_channel *chan = pNv->chan;
348         struct nouveau_grobj *clip;
349
350         if (!pNv->NvClipRectangle) {
351                 if (nouveau_grobj_alloc(pNv->chan, NvClipRectangle,
352                                         NV01_CONTEXT_CLIP_RECTANGLE,
353                                         &pNv->NvClipRectangle))
354                         return FALSE;
355         }
356         clip = pNv->NvClipRectangle;
357
358         BEGIN_RING(chan, clip, NV01_CONTEXT_CLIP_RECTANGLE_DMA_NOTIFY, 1);
359         OUT_RING  (chan, chan->nullobj->handle);
360
361         return TRUE;
362 }
363
364 /* FLAGS_NONE, NvDmaFB, NvDmaAGP, NvDmaNotifier0 */
365 static Bool
366 NVAccelInitMemFormat(ScrnInfoPtr pScrn)
367 {
368         NVPtr pNv = NVPTR(pScrn);
369         struct nouveau_channel *chan = pNv->chan;
370         struct nouveau_grobj *m2mf;
371         uint32_t class;
372
373         if (pNv->Architecture < NV_ARCH_50)
374                 class = NV04_MEMORY_TO_MEMORY_FORMAT;
375         else
376                 class = NV50_MEMORY_TO_MEMORY_FORMAT;
377
378         if (!pNv->NvMemFormat) {
379                 if (nouveau_grobj_alloc(chan, NvMemFormat, class,
380                                         &pNv->NvMemFormat))
381                         return FALSE;
382         }
383         m2mf = pNv->NvMemFormat;
384
385         BEGIN_RING(chan, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
386         OUT_RING  (chan, pNv->notify0->handle);
387         BEGIN_RING(chan, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2);
388         OUT_RING  (chan, chan->vram->handle);
389         OUT_RING  (chan, chan->vram->handle);
390
391         return TRUE;
392 }
393
394 static Bool
395 NVAccelInitImageFromCpu(ScrnInfoPtr pScrn)
396 {
397         NVPtr pNv = NVPTR(pScrn);
398         struct nouveau_channel *chan = pNv->chan;
399         struct nouveau_grobj *ifc;
400         uint32_t class;
401
402         switch (pNv->Architecture) {
403         case NV_ARCH_04:
404                 class = NV04_IMAGE_FROM_CPU;
405                 break;
406         case NV_ARCH_10:
407         case NV_ARCH_20:
408         case NV_ARCH_30:
409         case NV_ARCH_40:
410         default:
411                 class = NV10_IMAGE_FROM_CPU;
412                 break;
413         }
414
415         if (!pNv->NvImageFromCpu) {
416                 if (nouveau_grobj_alloc(chan, NvImageFromCpu, class,
417                                         &pNv->NvImageFromCpu))
418                         return FALSE;
419         }
420         ifc = pNv->NvImageFromCpu;
421
422         BEGIN_RING(chan, ifc, NV01_IMAGE_FROM_CPU_DMA_NOTIFY, 1);
423         OUT_RING  (chan, pNv->notify0->handle);
424         BEGIN_RING(chan, ifc, NV01_IMAGE_FROM_CPU_CLIP_RECTANGLE, 1);
425         OUT_RING  (chan, chan->nullobj->handle);
426         BEGIN_RING(chan, ifc, NV01_IMAGE_FROM_CPU_PATTERN, 1);
427         OUT_RING  (chan, chan->nullobj->handle);
428         BEGIN_RING(chan, ifc, NV01_IMAGE_FROM_CPU_ROP, 1);
429         OUT_RING  (chan, chan->nullobj->handle);
430         if (pNv->Architecture >= NV_ARCH_10) {
431                 BEGIN_RING(chan, ifc, NV01_IMAGE_FROM_CPU_BETA1, 1);
432                 OUT_RING  (chan, chan->nullobj->handle);
433                 BEGIN_RING(chan, ifc, NV05_IMAGE_FROM_CPU_BETA4, 1);
434                 OUT_RING  (chan, chan->nullobj->handle);
435         }
436         BEGIN_RING(chan, ifc, NV05_IMAGE_FROM_CPU_SURFACE, 1);
437         OUT_RING  (chan, pNv->NvContextSurfaces->handle);
438         BEGIN_RING(chan, ifc, NV01_IMAGE_FROM_CPU_OPERATION, 1);
439         OUT_RING  (chan, NV01_IMAGE_FROM_CPU_OPERATION_SRCCOPY);
440
441         return TRUE;
442 }
443
444 static Bool
445 NVAccelInit2D_NV50(ScrnInfoPtr pScrn)
446 {
447         NVPtr pNv = NVPTR(pScrn);
448         struct nouveau_channel *chan = pNv->chan;
449         struct nouveau_grobj *eng2d;
450
451         if (!pNv->Nv2D) {
452                 if (nouveau_grobj_alloc(chan, Nv2D, 0x502d, &pNv->Nv2D))
453                         return FALSE;
454         }
455         eng2d = pNv->Nv2D;
456
457         BEGIN_RING(chan, eng2d, 0x180, 3);
458         OUT_RING  (chan, pNv->notify0->handle);
459         OUT_RING  (chan, pNv->chan->vram->handle);
460         OUT_RING  (chan, pNv->chan->vram->handle);
461
462         /* Magics from nv, no clue what they do, but at least some
463          * of them are needed to avoid crashes.
464          */
465         BEGIN_RING(chan, eng2d, 0x260, 1);
466         OUT_RING  (chan, 1);
467         BEGIN_RING(chan, eng2d, 0x290, 1);
468         OUT_RING  (chan, 1);
469         BEGIN_RING(chan, eng2d, 0x29c, 1);
470         OUT_RING  (chan, 0);
471         BEGIN_RING(chan, eng2d, 0x58c, 1);
472         OUT_RING  (chan, 0x111);
473
474         pNv->currentRop = 0xfffffffa;
475         return TRUE;
476 }
477
478 #define INIT_CONTEXT_OBJECT(name) do {                                        \
479         ret = NVAccelInit##name(pScrn);                                       \
480         if (!ret) {                                                           \
481                 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,                         \
482                            "Failed to initialise context object: "#name       \
483                            " (%d)\n", ret);                                   \
484                 return FALSE;                                                 \
485         }                                                                     \
486 } while(0)
487
488 Bool
489 NVAccelCommonInit(ScrnInfoPtr pScrn)
490 {
491         NVPtr pNv = NVPTR(pScrn);
492         Bool ret;
493         if(pNv->NoAccel) return TRUE;
494
495         /* General engine objects */
496         INIT_CONTEXT_OBJECT(DmaNotifier0);
497
498         /* 2D engine */
499         if (pNv->Architecture < NV_ARCH_50) {
500                 INIT_CONTEXT_OBJECT(ContextSurfaces);
501                 INIT_CONTEXT_OBJECT(ContextBeta1);
502                 INIT_CONTEXT_OBJECT(ContextBeta4);
503                 INIT_CONTEXT_OBJECT(ImagePattern);
504                 INIT_CONTEXT_OBJECT(RasterOp);
505                 INIT_CONTEXT_OBJECT(Rectangle);
506                 INIT_CONTEXT_OBJECT(ImageBlit);
507                 INIT_CONTEXT_OBJECT(ScaledImage);
508                 INIT_CONTEXT_OBJECT(ClipRectangle);
509                 INIT_CONTEXT_OBJECT(ImageFromCpu);
510         } else {
511                 INIT_CONTEXT_OBJECT(2D_NV50);
512         }
513         INIT_CONTEXT_OBJECT(MemFormat);
514
515         /* 3D init */
516         switch (pNv->Architecture) {
517         case NV_ARCH_50:
518                 INIT_CONTEXT_OBJECT(NV50TCL);
519                 break;
520         case NV_ARCH_40:
521                 INIT_CONTEXT_OBJECT(NV40TCL);
522                 break;
523         case NV_ARCH_30:
524                 INIT_CONTEXT_OBJECT(NV30TCL);
525                 break;
526         case NV_ARCH_20:
527         case NV_ARCH_10:
528                 INIT_CONTEXT_OBJECT(NV10TCL);
529                 break;
530         default:
531                 break;
532         }
533
534         return TRUE;
535 }
536
537 void NVAccelFree(NVPtr pNv)
538 {
539         if (pNv->NoAccel)
540                 return;
541
542         nouveau_notifier_free(&pNv->notify0);
543         if (pNv->Architecture < NV_ARCH_50) {
544                 nouveau_grobj_free(&pNv->NvContextSurfaces);
545                 nouveau_grobj_free(&pNv->NvContextBeta1);
546                 nouveau_grobj_free(&pNv->NvContextBeta4);
547                 nouveau_grobj_free(&pNv->NvImagePattern);
548                 nouveau_grobj_free(&pNv->NvRop);
549                 nouveau_grobj_free(&pNv->NvRectangle);
550                 nouveau_grobj_free(&pNv->NvImageBlit);
551                 nouveau_grobj_free(&pNv->NvScaledImage);
552                 nouveau_grobj_free(&pNv->NvClipRectangle);
553                 nouveau_grobj_free(&pNv->NvImageFromCpu);
554         } else
555                 nouveau_grobj_free(&pNv->Nv2D);
556         nouveau_grobj_free(&pNv->NvMemFormat);
557
558         nouveau_grobj_free(&pNv->Nv3D);
559
560         if (pNv->tesla_scratch)
561                 nouveau_bo_ref(NULL, &pNv->tesla_scratch);
562         if (pNv->shader_mem)
563                 nouveau_bo_ref(NULL, &pNv->shader_mem);
564 }