Merge branch 'randr-1.2' into nv50-branch
[nouveau] / src / nv_accel_common.c
1 #include "nv_include.h"
2
3 static Bool
4 NVAccelInitNullObject(ScrnInfoPtr pScrn)
5 {
6         NVPtr pNv = NVPTR(pScrn);
7         static int have_object = FALSE;
8
9         if (!have_object) {
10                 if (!NVDmaCreateContextObject(pNv, NvNullObject,
11                                                    0x30))
12                         return FALSE;
13                 have_object = TRUE;
14         }
15
16         return TRUE;
17 }
18
19 static Bool
20 NVAccelInitNull3D(ScrnInfoPtr pScrn)
21 {
22         NVPtr pNv = NVPTR(pScrn);
23         static int have_object = FALSE;
24
25         if (!have_object) {
26                 if (!NVDmaCreateContextObject(pNv, Nv3D, 0x30))
27                         return FALSE;
28                 have_object = TRUE;
29         }
30
31         return TRUE;
32 }
33
34 uint32_t
35 NVAccelGetPixmapOffset(PixmapPtr pPix)
36 {
37         ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum];
38         NVPtr pNv = NVPTR(pScrn);
39         CARD32 offset;
40
41         if (pPix->drawable.type == DRAWABLE_WINDOW) {
42                 offset = pNv->FB->offset;
43         } else {
44                 offset  = (uint32_t)((unsigned long)pPix->devPrivate.ptr -
45                                 (unsigned long)pNv->FB->map);
46                 offset += pNv->FB->offset;
47         }
48
49         return offset;
50 }
51
52 static Bool
53 NVAccelInitDmaNotifier0(ScrnInfoPtr pScrn)
54 {
55         NVPtr pNv = NVPTR(pScrn);
56         static int have_object = FALSE;
57
58         if (!have_object) {
59                 pNv->Notifier0 = NVNotifierAlloc(pScrn, NvDmaNotifier0);
60                 if (!pNv->Notifier0)
61                         return FALSE;
62                 have_object = TRUE;
63         }
64
65         return TRUE;
66 }
67
68 /* FLAGS_ROP_AND, DmaFB, DmaFB, 0 */
69 static Bool
70 NVAccelInitContextSurfaces(ScrnInfoPtr pScrn)
71 {
72         NVPtr pNv = NVPTR(pScrn);
73         static int have_object = FALSE;
74         uint32_t   class;
75
76         class = (pNv->Architecture >= NV_10) ? NV10_CONTEXT_SURFACES_2D :
77                                                NV04_SURFACE;
78
79         if (!have_object) {
80                 if (!NVDmaCreateContextObject(pNv, NvContextSurfaces, class))
81                         return FALSE;
82                 have_object = TRUE;
83         }
84
85         NVDmaSetObjectOnSubchannel(pNv, NvSubContextSurfaces,
86                                         NvContextSurfaces);
87         NVDmaStart(pNv, NvSubContextSurfaces, NV04_SURFACE_DMA_NOTIFY, 1);
88         NVDmaNext (pNv, NvNullObject);
89         NVDmaStart(pNv, NvSubContextSurfaces, NV04_SURFACE_DMA_IMAGE_SOURCE, 2);
90         NVDmaNext (pNv, NvDmaFB);
91         NVDmaNext (pNv, NvDmaFB);
92
93         return TRUE;
94 }
95
96 Bool
97 NVAccelGetCtxSurf2DFormatFromPixmap(PixmapPtr pPix, int *fmt_ret)
98 {
99         switch (pPix->drawable.bitsPerPixel) {
100         case 32:
101                 *fmt_ret = SURFACE_FORMAT_A8R8G8B8;
102                 break;
103         case 24:
104                 *fmt_ret = SURFACE_FORMAT_X8R8G8B8;
105                 break;
106         case 16:
107                 *fmt_ret = SURFACE_FORMAT_R5G6B5;
108                 break;
109         case 8:
110                 *fmt_ret = SURFACE_FORMAT_Y8;
111                 break;
112         default:
113                 return FALSE;
114         }
115
116         return TRUE;
117 }
118
119 Bool
120 NVAccelGetCtxSurf2DFormatFromPicture(PicturePtr pPict, int *fmt_ret)
121 {
122         switch (pPict->format) {
123         case PICT_a8r8g8b8:
124                 *fmt_ret = SURFACE_FORMAT_A8R8G8B8;
125                 break;
126         case PICT_x8r8g8b8:
127                 *fmt_ret = SURFACE_FORMAT_X8R8G8B8;
128                 break;
129         case PICT_r5g6b5:
130                 *fmt_ret = SURFACE_FORMAT_R5G6B5;
131                 break;
132         case PICT_a8:
133                 *fmt_ret = SURFACE_FORMAT_Y8;
134                 break;
135         default:
136                 return FALSE;
137         }
138
139         return TRUE;
140 }
141
142 Bool
143 NVAccelSetCtxSurf2D(PixmapPtr psPix, PixmapPtr pdPix, int format)
144 {
145         ScrnInfoPtr pScrn = xf86Screens[psPix->drawable.pScreen->myNum];
146         NVPtr pNv = NVPTR(pScrn);
147
148         NVDmaStart(pNv, NvSubContextSurfaces, SURFACE_FORMAT, 4);
149         NVDmaNext (pNv, format);
150         NVDmaNext (pNv, ((uint32_t)exaGetPixmapPitch(pdPix) << 16) |
151                          (uint32_t)exaGetPixmapPitch(psPix));
152         NVDmaNext (pNv, NVAccelGetPixmapOffset(psPix));
153         NVDmaNext (pNv, NVAccelGetPixmapOffset(pdPix));
154
155         return TRUE;
156 }
157
158 /* FLAGS_ROP_AND|FLAGS_MONO, 0, 0, 0 */
159 static Bool
160 NVAccelInitImagePattern(ScrnInfoPtr pScrn)
161 {
162         NVPtr pNv = NVPTR(pScrn);
163         static int have_object = FALSE;
164         uint32_t   class;
165
166         class = NV04_IMAGE_PATTERN;
167
168         if (!have_object) {
169                 if (!NVDmaCreateContextObject(pNv, NvImagePattern, class))
170                         return FALSE;
171                 have_object = TRUE;
172         }
173
174         NVDmaSetObjectOnSubchannel(pNv, NvSubImagePattern,
175                                         NvImagePattern);
176         NVDmaStart(pNv, NvSubImagePattern,
177                         0x180, /*NV04_IMAGE_PATTERN_SET_DMA_NOTIFY*/ 1);
178         NVDmaNext (pNv, NvNullObject);
179         NVDmaStart(pNv, NvSubImagePattern, NV04_IMAGE_PATTERN_MONO_FORMAT, 3);
180 #if X_BYTE_ORDER == X_BIG_ENDIAN
181         NVDmaNext (pNv, 2 /* NV04_IMAGE_PATTERN_BIGENDIAN/LE_M1 */);
182 #else
183         NVDmaNext (pNv, 1 /* NV04_IMAGE_PATTERN_LOWENDIAN/CGA6_M1 */);
184 #endif
185         NVDmaNext (pNv, 0 /* NV04_IMAGE_PATTERN_MONOCHROME_SHAPE_8X8 */);
186         NVDmaNext (pNv, 1 /* NV04_IMAGE_PATTERN_SELECT_MONOCHROME */);
187
188         return TRUE;
189 }
190
191 /* FLAGS_ROP_AND, 0, 0, 0 */
192 static Bool
193 NVAccelInitRasterOp(ScrnInfoPtr pScrn)
194 {
195         NVPtr pNv = NVPTR(pScrn);
196         static int have_object = FALSE;
197         uint32_t   class;
198
199         class = NV03_PRIMITIVE_RASTER_OP;
200
201         if (!have_object) {
202                 if (!NVDmaCreateContextObject(pNv, NvRop, class))
203                         return FALSE;
204                 have_object = TRUE;
205         }
206
207         NVDmaSetObjectOnSubchannel(pNv, NvSubRop, NvRop);
208         NVDmaStart(pNv, NvSubRop, NV03_PRIMITIVE_RASTER_OP_DMA_NOTIFY, 1);
209         NVDmaNext (pNv, NvNullObject);
210
211         return TRUE;
212 }
213
214 /* FLAGS_ROP_AND | FLAGS_MONO, 0, 0, 0 */
215 static Bool
216 NVAccelInitRectangle(ScrnInfoPtr pScrn)
217 {
218         NVPtr pNv = NVPTR(pScrn);
219         static int have_object = FALSE;
220         uint32_t   class;
221
222         class = NV04_GDI_RECTANGLE_TEXT;
223
224         if (!have_object) {
225                 if (!NVDmaCreateContextObject(pNv, NvRectangle, class))
226                         return FALSE;
227                 have_object = TRUE;
228         }
229
230         NVDmaSetObjectOnSubchannel(pNv, NvSubRectangle, NvRectangle);
231         NVDmaStart(pNv, NvSubRectangle,
232                         NV04_GDI_RECTANGLE_TEXT_SET_DMA_NOTIFY, 1);
233         NVDmaNext (pNv, NvDmaNotifier0);
234         NVDmaStart(pNv, NvSubRectangle,
235                         0x184 /*NV04_GDI_RECTANGLE_TEXT_SET_DMA_FONTS*/, 1);
236         NVDmaNext (pNv, NvNullObject);
237         NVDmaStart(pNv, NvSubRectangle, NV04_GDI_RECTANGLE_TEXT_SURFACE, 1);
238         NVDmaNext (pNv, NvContextSurfaces);
239         NVDmaStart(pNv, NvSubRectangle, NV04_GDI_RECTANGLE_TEXT_ROP5, 1);
240         NVDmaNext (pNv, NvRop);
241         NVDmaStart(pNv, NvSubRectangle, NV04_GDI_RECTANGLE_TEXT_PATTERN, 1);
242         NVDmaNext (pNv, NvImagePattern);
243         NVDmaStart(pNv, NvSubRectangle, NV04_GDI_RECTANGLE_TEXT_OPERATION, 1);
244         NVDmaNext (pNv, 1 /* ROP_AND */);
245
246         return TRUE;
247 }
248
249 /* FLAGS_ROP_AND, DmaFB, DmaFB, 0 */
250 static Bool
251 NVAccelInitImageBlit(ScrnInfoPtr pScrn)
252 {
253         NVPtr pNv = NVPTR(pScrn);
254         static int have_object = FALSE;
255         uint32_t   class;
256
257         class = (pNv->WaitVSyncPossible) ? NV10_IMAGE_BLIT : NV_IMAGE_BLIT;
258
259         if (!have_object) {
260                 if (!NVDmaCreateContextObject(pNv, NvImageBlit, class))
261                         return FALSE;
262                 have_object = TRUE;
263         }
264
265         NVDmaSetObjectOnSubchannel(pNv, NvSubImageBlit, NvImageBlit);
266         NVDmaStart(pNv, NvSubImageBlit, NV_IMAGE_BLIT_DMA_NOTIFY, 1);
267         NVDmaNext (pNv, NvDmaNotifier0);
268         NVDmaStart(pNv, NvSubImageBlit, NV_IMAGE_BLIT_COLOR_KEY, 1);
269         NVDmaNext (pNv, NvNullObject);
270         NVDmaStart(pNv, NvSubImageBlit, NV_IMAGE_BLIT_SURFACE, 1);
271         NVDmaNext (pNv, NvContextSurfaces);
272         NVDmaStart(pNv, NvSubImageBlit, NV_IMAGE_BLIT_CLIP_RECTANGLE, 3);
273         NVDmaNext (pNv, NvNullObject);
274         NVDmaNext (pNv, NvImagePattern);
275         NVDmaNext (pNv, NvRop);
276         NVDmaStart(pNv, NvSubImageBlit, NV_IMAGE_BLIT_OPERATION, 1);
277         NVDmaNext (pNv, 1 /* NV_IMAGE_BLIT_OPERATION_ROP_AND */);
278
279         return TRUE;
280 }
281
282 /* FLAGS_SRCCOPY, DmaFB, DmaFB, 0 */
283 static Bool
284 NVAccelInitScaledImage(ScrnInfoPtr pScrn)
285 {
286         NVPtr pNv = NVPTR(pScrn);
287         static int have_object = FALSE;
288         uint32_t   class;
289
290         switch (pNv->Architecture) {
291         case NV_ARCH_04:
292                 class = NV04_SCALED_IMAGE_FROM_MEMORY;
293                 break;
294         case NV_ARCH_10:
295         case NV_ARCH_20:
296         case NV_ARCH_30:
297                 class = NV10_SCALED_IMAGE_FROM_MEMORY;
298                 break;
299         case NV_ARCH_40:
300         default:
301                 class = NV10_SCALED_IMAGE_FROM_MEMORY | 0x3000;
302                 break;
303         }
304
305         if (!have_object) {
306                 if (!NVDmaCreateContextObject(pNv, NvScaledImage, class))
307                         return FALSE;
308                 have_object = TRUE;
309         }
310
311         NVDmaSetObjectOnSubchannel(pNv, NvSubScaledImage, NvScaledImage);
312         NVDmaStart(pNv, NvSubScaledImage,
313                         NV04_SCALED_IMAGE_FROM_MEMORY_DMA_NOTIFY, 1);
314         NVDmaNext (pNv, NvDmaNotifier0);
315         NVDmaStart(pNv, NvSubScaledImage,
316                         NV04_SCALED_IMAGE_FROM_MEMORY_DMA_IMAGE, 1);
317         NVDmaNext (pNv, NvDmaFB); /* source object */
318         NVDmaStart(pNv, NvSubScaledImage,
319                         NV04_SCALED_IMAGE_FROM_MEMORY_SURFACE, 1);
320         NVDmaNext (pNv, NvContextSurfaces);
321         NVDmaStart(pNv, NvSubScaledImage, 0x188, 1); /* PATTERN */
322         NVDmaNext (pNv, NvNullObject);
323         NVDmaStart(pNv, NvSubScaledImage, 0x18c, 1); /* ROP */
324         NVDmaNext (pNv, NvNullObject);
325         NVDmaStart(pNv, NvSubScaledImage, 0x190, 1); /* BETA1 */
326         NVDmaNext (pNv, NvNullObject);
327         NVDmaStart(pNv, NvSubScaledImage, 0x194, 1); /* BETA4 */
328         NVDmaNext (pNv, NvNullObject);
329         NVDmaStart(pNv, NvSubScaledImage,
330                         NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION, 1);
331         NVDmaNext (pNv, 3 /* SRCCOPY */);
332
333         return TRUE;
334 }
335
336 /* FLAGS_NONE, 0, 0, 0 */
337 static Bool
338 NVAccelInitClipRectangle(ScrnInfoPtr pScrn)
339 {
340         NVPtr pNv = NVPTR(pScrn);
341         static int have_object = FALSE;
342         int class = NV01_CONTEXT_CLIP_RECTANGLE;
343
344         if (!have_object) {
345                 if (!NVDmaCreateContextObject(pNv, NvClipRectangle, class))
346                         return FALSE;
347                 have_object = TRUE;
348         }
349
350         NVDmaSetObjectOnSubchannel(pNv, NvSubClipRectangle, NvClipRectangle);
351         NVDmaStart(pNv, NvSubClipRectangle, 0x180, 1); /* DMA_NOTIFY */
352         NVDmaNext (pNv, NvNullObject);
353
354         return TRUE;
355 }
356
357 /* FLAGS_ROP_AND | FLAGS_CLIP_ENABLE, 0, 0, 0 */
358 static Bool
359 NVAccelInitSolidLine(ScrnInfoPtr pScrn)
360 {
361         NVPtr pNv = NVPTR(pScrn);
362         static int have_object = FALSE;
363         int class = NV04_SOLID_LINE;
364
365         if (!have_object) {
366                 if (!NVDmaCreateContextObject(pNv, NvSolidLine, class))
367                         return FALSE;
368                 have_object = TRUE;
369         }
370
371         NVDmaSetObjectOnSubchannel(pNv, NvSubSolidLine, NvSolidLine);
372         NVDmaStart(pNv, NvSubSolidLine, NV04_SOLID_LINE_CLIP_RECTANGLE, 3);
373         NVDmaNext (pNv, NvClipRectangle);
374         NVDmaNext (pNv, NvImagePattern);
375         NVDmaNext (pNv, NvRop);
376         NVDmaStart(pNv, NvSubSolidLine, NV04_SOLID_LINE_SURFACE, 1);
377         NVDmaNext (pNv, NvContextSurfaces);
378         NVDmaStart(pNv, NvSubSolidLine, NV04_SOLID_LINE_OPERATION, 1);
379         NVDmaNext (pNv, 1); /* ROP_AND */
380
381         return TRUE;
382 }
383
384 /* FLAGS_NONE, NvDmaFB, NvDmaAGP, NvDmaNotifier0 */
385 static Bool
386 NVAccelInitMemFormat(ScrnInfoPtr pScrn)
387 {
388         NVPtr pNv = NVPTR(pScrn);
389         static int have_object = FALSE;
390         uint32_t   class;
391
392         if (pNv->Architecture < NV_ARCH_50)
393                 class = NV_MEMORY_TO_MEMORY_FORMAT;
394         else
395                 class = NV_MEMORY_TO_MEMORY_FORMAT | 0x5000;
396
397         if (!have_object) {
398                 if (!NVDmaCreateContextObject(pNv, NvMemFormat, class))
399                                 return FALSE;
400                 have_object = TRUE;
401         }
402
403         NVDmaSetObjectOnSubchannel(pNv, NvSubMemFormat, NvMemFormat);
404         NVDmaStart(pNv, NvSubMemFormat,
405                         NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
406         NVDmaNext (pNv, NvDmaNotifier0);
407         NVDmaStart(pNv, NvSubMemFormat,
408                         NV_MEMORY_TO_MEMORY_FORMAT_OBJECT_IN, 2);
409         NVDmaNext (pNv, NvDmaFB);
410         NVDmaNext (pNv, NvDmaFB);
411
412         pNv->M2MFDirection = -1;
413         return TRUE;
414 }
415
416 static Bool
417 NVAccelInit2D_NV50(ScrnInfoPtr pScrn)
418 {
419         NVPtr pNv = NVPTR(pScrn);
420         static int have_object = FALSE;
421
422         if (!have_object) {
423                 if (!NVDmaCreateContextObject(pNv, Nv2D, 0x502d))
424                                 return FALSE;
425                 have_object = TRUE;
426         }
427
428         NVDmaSetObjectOnSubchannel(pNv, NvSub2D, Nv2D);
429
430         NVDmaStart(pNv, NvSub2D, 0x180, 3);
431         NVDmaNext (pNv, NvDmaNotifier0);
432         NVDmaNext (pNv, NvDmaFB);
433         NVDmaNext (pNv, NvDmaFB);
434
435         /* Magics from nv, no clue what they do, but at least some
436          * of them are needed to avoid crashes.
437          */
438         NVDmaStart(pNv, NvSub2D, 0x260, 1);
439         NVDmaNext (pNv, 1);
440         NVDmaStart(pNv, NvSub2D, 0x290, 1);
441         NVDmaNext (pNv, 1);
442         NVDmaStart(pNv, NvSub2D, 0x29c, 1);
443         NVDmaNext (pNv, 0);
444         NVDmaStart(pNv, NvSub2D, 0x58c, 1);
445         NVDmaNext (pNv, 0x111);
446
447         pNv->currentRop = 0xfffffffa;
448         return TRUE;
449 }
450
451 #define INIT_CONTEXT_OBJECT(name) do {                                        \
452         ret = NVAccelInit##name(pScrn);                                       \
453         if (!ret) {                                                           \
454                 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,                         \
455                            "Failed to initialise context object: "#name       \
456                            " (%d)\n", ret);                                   \
457                 return FALSE;                                                 \
458         }                                                                     \
459 } while(0)
460
461 Bool
462 NVAccelCommonInit(ScrnInfoPtr pScrn)
463 {
464         NVPtr pNv = NVPTR(pScrn);
465         Bool ret;
466
467         INIT_CONTEXT_OBJECT(NullObject);
468         INIT_CONTEXT_OBJECT(DmaNotifier0);
469
470         /* 2D engine */
471         if (pNv->Architecture < NV_ARCH_50) {
472                 INIT_CONTEXT_OBJECT(ContextSurfaces);
473                 INIT_CONTEXT_OBJECT(ImagePattern);
474                 INIT_CONTEXT_OBJECT(RasterOp);
475                 INIT_CONTEXT_OBJECT(Rectangle);
476                 INIT_CONTEXT_OBJECT(ImageBlit);
477                 INIT_CONTEXT_OBJECT(ScaledImage);
478                 INIT_CONTEXT_OBJECT(ClipRectangle);
479                 INIT_CONTEXT_OBJECT(SolidLine);
480         } else {
481                 INIT_CONTEXT_OBJECT(2D_NV50);
482         }
483         INIT_CONTEXT_OBJECT(MemFormat);
484
485         /* 3D engine */
486         switch (pNv->Architecture) {
487         case NV_ARCH_40:
488                 INIT_CONTEXT_OBJECT(NV40TCL);
489                 break;
490         default:
491                 INIT_CONTEXT_OBJECT(Null3D);
492                 break;
493         }
494
495         return TRUE;
496 }
497