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