randr12: fix comment typo
[nouveau] / src / nv_exa.c
1  /***************************************************************************\
2 |*                                                                           *|
3 |*       Copyright 2003 NVIDIA, Corporation.  All rights reserved.           *|
4 |*                                                                           *|
5 |*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
6 |*     international laws.  Users and possessors of this source code are     *|
7 |*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
8 |*     use this code in individual and commercial software.                  *|
9 |*                                                                           *|
10 |*     Any use of this source code must include,  in the user documenta-     *|
11 |*     tion and  internal comments to the code,  notices to the end user     *|
12 |*     as follows:                                                           *|
13 |*                                                                           *|
14 |*       Copyright 2003 NVIDIA, Corporation.  All rights reserved.           *|
15 |*                                                                           *|
16 |*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
17 |*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
18 |*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
19 |*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
20 |*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
21 |*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
22 |*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
23 |*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
24 |*     SULTING FROM LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION     *|
25 |*     OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  ARISING OUT OF     *|
26 |*     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.     *|
27 |*                                                                           *|
28 |*     U.S. Government  End  Users.   This source code  is a "commercial     *|
29 |*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
30 |*     consisting  of "commercial  computer  software"  and  "commercial     *|
31 |*     computer  software  documentation,"  as such  terms  are  used in     *|
32 |*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
33 |*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
34 |*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
35 |*     all U.S. Government End Users  acquire the source code  with only     *|
36 |*     those rights set forth herein.                                        *|
37 |*                                                                           *|
38  \***************************************************************************/
39
40 /*
41   Exa Modifications (c) Lars Knoll (lars@trolltech.com)
42  */
43
44 #include "nv_include.h"
45 #include "exa.h"
46
47 #include "nv_dma.h"
48 #include "nv_local.h"
49
50 #include <sys/time.h>
51
52 const int NVCopyROP[16] =
53 {
54    0x00,            /* GXclear */
55    0x88,            /* GXand */
56    0x44,            /* GXandReverse */
57    0xCC,            /* GXcopy */
58    0x22,            /* GXandInverted */
59    0xAA,            /* GXnoop */
60    0x66,            /* GXxor */
61    0xEE,            /* GXor */
62    0x11,            /* GXnor */
63    0x99,            /* GXequiv */
64    0x55,            /* GXinvert*/
65    0xDD,            /* GXorReverse */
66    0x33,            /* GXcopyInverted */
67    0xBB,            /* GXorInverted */
68    0x77,            /* GXnand */
69    0xFF             /* GXset */
70 };
71
72 static void 
73 NVSetPattern(ScrnInfoPtr pScrn, CARD32 clr0, CARD32 clr1,
74                                 CARD32 pat0, CARD32 pat1)
75 {
76         NVPtr pNv = NVPTR(pScrn);
77
78         BEGIN_RING(NvImagePattern, NV04_IMAGE_PATTERN_MONOCHROME_COLOR0, 4);
79         OUT_RING  (clr0);
80         OUT_RING  (clr1);
81         OUT_RING  (pat0);
82         OUT_RING  (pat1);
83 }
84
85 static void 
86 NVSetROP(ScrnInfoPtr pScrn, CARD32 alu, CARD32 planemask)
87 {
88         NVPtr pNv = NVPTR(pScrn);
89         int rop = NVCopyROP[alu] & 0xf0;
90
91         if (planemask != ~0) {
92                 NVSetPattern(pScrn, 0, planemask, ~0, ~0);
93                 if (pNv->currentRop != (alu + 32)) {
94                         BEGIN_RING(NvRop, NV03_CONTEXT_ROP_ROP, 1);
95                         OUT_RING  (rop | 0x0a);
96                         pNv->currentRop = alu + 32;
97                 }
98         } else
99         if (pNv->currentRop != alu) {
100                 if(pNv->currentRop >= 16)
101                         NVSetPattern(pScrn, ~0, ~0, ~0, ~0);
102                 BEGIN_RING(NvRop, NV03_CONTEXT_ROP_ROP, 1);
103                 OUT_RING  (rop | (rop >> 4));
104                 pNv->currentRop = alu;
105         }
106 }
107
108 static void setM2MFDirection(ScrnInfoPtr pScrn, int dir)
109 {
110         NVPtr pNv = NVPTR(pScrn);
111
112         if (pNv->M2MFDirection != dir) {
113
114                 BEGIN_RING(NvMemFormat,
115                            NV_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2);
116                 OUT_RING  (dir ? NvDmaTT : NvDmaFB);
117                 OUT_RING  (dir ? NvDmaFB : NvDmaTT);
118                 pNv->M2MFDirection = dir;
119         }
120 }
121
122 static CARD32 rectFormat(DrawablePtr pDrawable)
123 {
124         switch(pDrawable->bitsPerPixel) {
125         case 32:
126         case 24:
127                 return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
128                 break;
129         case 16:
130                 return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A16R5G6B5;
131                 break;
132         default:
133                 return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
134                 break;
135         }
136 }
137
138 /* EXA acceleration hooks */
139 static void NVExaWaitMarker(ScreenPtr pScreen, int marker)
140 {
141         NVSync(xf86Screens[pScreen->myNum]);
142 }
143
144 static Bool NVExaPrepareSolid(PixmapPtr pPixmap,
145                               int   alu,
146                               Pixel planemask,
147                               Pixel fg)
148 {
149         ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
150         NVPtr pNv = NVPTR(pScrn);
151         int fmt;
152
153         planemask |= ~0 << pPixmap->drawable.bitsPerPixel;
154         if (planemask != ~0 || alu != GXcopy) {
155                 if (pPixmap->drawable.bitsPerPixel == 32)
156                         return FALSE;
157                 BEGIN_RING(NvRectangle, NV04_GDI_RECTANGLE_TEXT_OPERATION, 1);
158                 OUT_RING  (1); /* ROP_AND */
159                 NVSetROP(pScrn, alu, planemask);
160         } else {
161                 BEGIN_RING(NvRectangle, NV04_GDI_RECTANGLE_TEXT_OPERATION, 1);
162                 OUT_RING  (3); /* SRCCOPY */
163         }
164
165         if (!NVAccelGetCtxSurf2DFormatFromPixmap(pPixmap, &fmt))
166                 return FALSE;
167
168         /* When SURFACE_FORMAT_A8R8G8B8 is used with GDI_RECTANGLE_TEXT, the 
169          * alpha channel gets forced to 0xFF for some reason.  We're using 
170          * SURFACE_FORMAT_Y32 as a workaround
171          */
172         if (fmt == NV04_CONTEXT_SURFACES_2D_FORMAT_A8R8G8B8)
173                 fmt = NV04_CONTEXT_SURFACES_2D_FORMAT_Y32;
174
175         if (!NVAccelSetCtxSurf2D(pPixmap, pPixmap, fmt))
176                 return FALSE;
177
178         BEGIN_RING(NvRectangle, NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT, 1);
179         OUT_RING  (rectFormat(&pPixmap->drawable));
180         BEGIN_RING(NvRectangle, NV04_GDI_RECTANGLE_TEXT_COLOR1_A, 1);
181         OUT_RING  (fg);
182
183         pNv->DMAKickoffCallback = NVDmaKickoffCallback;
184         return TRUE;
185 }
186
187 static void NVExaSolid (PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
188 {
189         ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
190         NVPtr pNv = NVPTR(pScrn);
191         int width = x2-x1;
192         int height = y2-y1;
193
194         BEGIN_RING(NvRectangle,
195                    NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT(0), 2);
196         OUT_RING  ((x1 << 16) | y1);
197         OUT_RING  ((width << 16) | height);
198
199         if((width * height) >= 512)
200                 FIRE_RING();
201 }
202
203 static void NVExaDoneSolid (PixmapPtr pPixmap)
204 {
205 }
206
207 static Bool NVExaPrepareCopy(PixmapPtr pSrcPixmap,
208                              PixmapPtr pDstPixmap,
209                              int       dx,
210                              int       dy,
211                              int       alu,
212                              Pixel     planemask)
213 {
214         ScrnInfoPtr pScrn = xf86Screens[pSrcPixmap->drawable.pScreen->myNum];
215         NVPtr pNv = NVPTR(pScrn);
216         int fmt;
217
218         if (pSrcPixmap->drawable.bitsPerPixel !=
219                         pDstPixmap->drawable.bitsPerPixel)
220                 return FALSE;
221
222         planemask |= ~0 << pDstPixmap->drawable.bitsPerPixel;
223         if (planemask != ~0 || alu != GXcopy) {
224                 if (pDstPixmap->drawable.bitsPerPixel == 32)
225                         return FALSE;
226                 BEGIN_RING(NvImageBlit, NV_IMAGE_BLIT_OPERATION, 1);
227                 OUT_RING  (1); /* ROP_AND */
228                 NVSetROP(pScrn, alu, planemask);
229         } else {
230                 BEGIN_RING(NvImageBlit, NV_IMAGE_BLIT_OPERATION, 1);
231                 OUT_RING  (3); /* SRCCOPY */
232         }
233
234         if (!NVAccelGetCtxSurf2DFormatFromPixmap(pDstPixmap, &fmt))
235                 return FALSE;
236         if (!NVAccelSetCtxSurf2D(pSrcPixmap, pDstPixmap, fmt))
237                 return FALSE;
238
239         pNv->DMAKickoffCallback = NVDmaKickoffCallback;
240         return TRUE;
241 }
242
243 static void NVExaCopy(PixmapPtr pDstPixmap,
244                       int       srcX,
245                       int       srcY,
246                       int       dstX,
247                       int       dstY,
248                       int       width,
249                       int       height)
250 {
251         ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
252         NVPtr pNv = NVPTR(pScrn);
253
254         /* We want to catch people who have this bug, to find a decent fix */
255 #if 0
256         /* Now check whether we have the same values for srcY and dstY and
257            whether the used chipset is buggy. Currently we flag all of G70
258            cards as buggy, which is probably much to broad. KoalaBR 
259            16 is an abritrary threshold. It should define the maximum number
260            of lines between dstY and srcY  If the number of lines is below
261            we guess, that the bug won't trigger...
262          */
263         if ( ((abs(srcY - dstY)< 16)||(abs(srcX-dstX)<16)) &&
264                 ((((pNv->Chipset & 0xfff0) == CHIPSET_G70) ||
265                  ((pNv->Chipset & 0xfff0) == CHIPSET_G71) ||
266                  ((pNv->Chipset & 0xfff0) == CHIPSET_G72) ||
267                  ((pNv->Chipset & 0xfff0) == CHIPSET_G73) ||
268                  ((pNv->Chipset & 0xfff0) == CHIPSET_C512))) )
269         {
270                 int dx=abs(srcX - dstX),dy=abs(srcY - dstY);
271                 // Ok, let's do it manually unless someone comes up with a better idea
272                 // 1. If dstY and srcY are really the same, do a copy rowwise
273                 if (dy<dx) {
274                         int i,xpos,inc;
275                         NVDEBUG("ExaCopy: Lines identical:\n");
276                         if (srcX>=dstX) {
277                                 xpos=0;
278                                 inc=1;
279                         } else {
280                                 xpos=width-1;
281                                 inc=-1;
282                         }
283                         for (i = 0; i < width; i++) {
284                                 BEGIN_RING(NvImageBlit,
285                                            NV_IMAGE_BLIT_POINT_IN, 3);
286                                 OUT_RING  ((srcY << 16) | (srcX+xpos));
287                                 OUT_RING  ((dstY << 16) | (dstX+xpos));
288                                 OUT_RING  ((height  << 16) | 1);
289                                 xpos+=inc;
290                         }
291                 } else {
292                         // 2. Otherwise we will try a line by line copy in the hope to avoid
293                         //    the card's bug.
294                         int i,ypos,inc;
295                         NVDEBUG("ExaCopy: Lines nearly the same srcY=%d, dstY=%d:\n", srcY, dstY);
296                         if (srcY>=dstY) {
297                                 ypos=0;
298                                 inc=1;
299                         } else {
300                                 ypos=height-1;
301                                 inc=-1;
302                         }
303                         for (i = 0; i < height; i++) {
304                                 BEGIN_RING(NvImageBlit,
305                                            NV_IMAGE_BLIT_POINT_IN, 3);
306                                 OUT_RING  (((srcY+ypos) << 16) | srcX);
307                                 OUT_RING  (((dstY+ypos) << 16) | dstX);
308                                 OUT_RING  ((1  << 16) | width);
309                                 ypos+=inc;
310                         }
311                 } 
312         } else {
313                 NVDEBUG("ExaCopy: Using default path\n");
314                 BEGIN_RING(NvImageBlit, NV_IMAGE_BLIT_POINT_IN, 3);
315                 OUT_RING  ((srcY << 16) | srcX);
316                 OUT_RING  ((dstY << 16) | dstX);
317                 OUT_RING  ((height  << 16) | width);
318         }
319 #endif /* 0 */
320
321         NVDEBUG("ExaCopy: Using default path\n");
322         BEGIN_RING(NvImageBlit, NV_IMAGE_BLIT_POINT_IN, 3);
323         OUT_RING  ((srcY << 16) | srcX);
324         OUT_RING  ((dstY << 16) | dstX);
325         OUT_RING  ((height  << 16) | width);
326
327         if((width * height) >= 512)
328                 FIRE_RING(); 
329 }
330
331 static void NVExaDoneCopy (PixmapPtr pDstPixmap) {}
332
333 static inline Bool NVAccelMemcpyRect(char *dst, const char *src, int height,
334                        int dst_pitch, int src_pitch, int line_len)
335 {
336         if ((src_pitch == line_len) && (src_pitch == dst_pitch)) {
337                 memcpy(dst, src, line_len*height);
338         } else {
339                 while (height--) {
340                         memcpy(dst, src, line_len);
341                         src += src_pitch;
342                         dst += dst_pitch;
343                 }
344         }
345
346         return TRUE;
347 }
348
349 static inline Bool
350 NVAccelDownloadM2MF(ScrnInfoPtr pScrn, char *dst, uint64_t src_offset,
351                                      int dst_pitch, int src_pitch,
352                                      int line_len, int line_count)
353 {
354         NVPtr pNv = NVPTR(pScrn);
355
356         setM2MFDirection(pScrn, 0);
357
358         while (line_count) {
359                 char *src = pNv->GARTScratch->map;
360                 int lc, i;
361
362                 if (line_count * line_len <= pNv->GARTScratch->size) {
363                         lc = line_count;
364                 } else {
365                         lc = pNv->GARTScratch->size / line_len;
366                         if (lc > line_count)
367                                 lc = line_count;
368                 }
369
370                 /* HW limitations */
371                 if (lc > 2047)
372                         lc = 2047;
373
374                 if (pNv->Architecture >= NV_ARCH_50) {
375                         BEGIN_RING(NvMemFormat, 0x200, 1);
376                         OUT_RING  (1);
377                         BEGIN_RING(NvMemFormat, 0x21c, 1);
378                         OUT_RING  (1);
379                         /* probably high-order bits of address */
380                         BEGIN_RING(NvMemFormat, 0x238, 2);
381                         OUT_RING  (0);
382                         OUT_RING  (0);
383                 }
384
385                 BEGIN_RING(NvMemFormat,
386                            NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
387                 OUT_RING  ((uint32_t)src_offset);
388                 OUT_RING  ((uint32_t)pNv->GARTScratch->offset);
389                 OUT_RING  (src_pitch);
390                 OUT_RING  (line_len);
391                 OUT_RING  (line_len);
392                 OUT_RING  (lc);
393                 OUT_RING  ((1<<8)|1);
394                 OUT_RING  (0);
395
396                 NVNotifierReset(pScrn, pNv->Notifier0);
397                 BEGIN_RING(NvMemFormat, NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1);
398                 OUT_RING  (0);
399                 BEGIN_RING(NvMemFormat, 0x100, 1);
400                 OUT_RING  (0);
401                 FIRE_RING();
402                 if (!NVNotifierWaitStatus(pScrn, pNv->Notifier0, 0, 2000))
403                         return FALSE;
404
405                 if (dst_pitch == line_len) {
406                         memcpy(dst, src, dst_pitch * lc);
407                         dst += dst_pitch * lc;
408                 } else {
409                         for (i = 0; i < lc; i++) {
410                                 memcpy(dst, src, line_len);
411                                 src += line_len;
412                                 dst += dst_pitch;
413                         }
414                 }
415
416                 line_count -= lc;
417                 src_offset += lc * src_pitch;
418         }
419
420         return TRUE;
421 }
422
423 static inline void *
424 NVExaPixmapMap(PixmapPtr pPix)
425 {
426         ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum];
427         NVPtr pNv = NVPTR(pScrn);
428         void *map;
429
430         map = pNv->FB->map + exaGetPixmapOffset(pPix);
431         return map;
432 }
433
434 static Bool NVDownloadFromScreen(PixmapPtr pSrc,
435                                  int x,  int y,
436                                  int w,  int h,
437                                  char *dst,  int dst_pitch)
438 {
439         ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum];
440         NVPtr pNv = NVPTR(pScrn);
441         int src_offset, src_pitch, cpp, offset;
442         const char *src;
443
444         src_offset = NVAccelGetPixmapOffset(pSrc);
445         src_pitch  = exaGetPixmapPitch(pSrc);
446         cpp = pSrc->drawable.bitsPerPixel >> 3;
447         offset = (y * src_pitch) + (x * cpp);
448
449         if (pNv->GARTScratch) {
450                 if (NVAccelDownloadM2MF(pScrn, dst,
451                                         src_offset + offset,
452                                         dst_pitch, src_pitch, w * cpp, h))
453                         return TRUE;
454         }
455
456         src = NVExaPixmapMap(pSrc) + offset;
457         exaWaitSync(pSrc->drawable.pScreen);
458         if (NVAccelMemcpyRect(dst, src, h, dst_pitch, src_pitch, w*cpp))
459                 return TRUE;
460
461         return FALSE;
462 }
463
464 static inline Bool
465 NVAccelUploadIFC(ScrnInfoPtr pScrn, const char *src, int src_pitch, 
466                  PixmapPtr pDst, int fmt, int x, int y, int w, int h, int cpp)
467 {
468         NVPtr pNv = NVPTR(pScrn);
469         int line_len = w * cpp;
470         int iw, id, ifc_fmt;
471
472         if (pNv->Architecture >= NV_ARCH_50)
473                 return FALSE;
474
475         if (h > 1024)
476                 return FALSE;
477
478         switch (cpp) {
479         case 2: ifc_fmt = 1; break;
480         case 4: ifc_fmt = 4; break;
481         default:
482                 return FALSE;
483         }
484
485         NVAccelSetCtxSurf2D(pDst, pDst, fmt);
486
487         /* Pad out input width to cover both COLORA() and COLORB() */
488         iw  = (line_len + 7) & ~7;
489         id  = iw / 4; /* line push size */
490         iw /= cpp;
491
492         /* Don't support lines longer than max push size yet.. */
493         if (id > 1792)
494                 return FALSE;
495
496         BEGIN_RING(NvClipRectangle, NV01_CONTEXT_CLIP_RECTANGLE_POINT, 2);
497         OUT_RING  (0x0); 
498         OUT_RING  (0x7FFF7FFF);
499
500         BEGIN_RING(NvImageFromCpu, NV01_IMAGE_FROM_CPU_OPERATION, 2);
501         OUT_RING  (NV01_IMAGE_FROM_CPU_OPERATION_SRCCOPY);
502         OUT_RING  (ifc_fmt);
503         BEGIN_RING(NvImageFromCpu, NV01_IMAGE_FROM_CPU_POINT, 3);
504         OUT_RING  ((y << 16) | x); /* dst point */
505         OUT_RING  ((h << 16) | w); /* width/height out */
506         OUT_RING  ((h << 16) | iw); /* width/height in */
507
508         while (h--) {
509                 char *dst;
510                 /* send a line */
511                 BEGIN_RING(NvImageFromCpu, NV01_IMAGE_FROM_CPU_COLOR(0), id);
512                 dst = (char *)pNv->dmaBase + (pNv->dmaCurrent << 2);
513                 memcpy(dst, src, line_len);
514                 pNv->dmaCurrent += id;
515
516                 src += src_pitch;
517         }
518
519         return TRUE;
520 }
521
522 static inline Bool
523 NVAccelUploadM2MF(ScrnInfoPtr pScrn, uint64_t dst_offset, const char *src,
524                                      int dst_pitch, int src_pitch,
525                                      int line_len, int line_count)
526 {
527         NVPtr pNv = NVPTR(pScrn);
528
529         setM2MFDirection(pScrn, 1);
530
531         while (line_count) {
532                 char *dst = pNv->GARTScratch->map;
533                 int lc, i;
534
535                 /* Determine max amount of data we can DMA at once */
536                 if (line_count * line_len <= pNv->GARTScratch->size) {
537                         lc = line_count;
538                 } else {
539                         lc = pNv->GARTScratch->size / line_len;
540                         if (lc > line_count)
541                                 lc = line_count;
542                 }
543
544                 /* HW limitations */
545                 if (lc > 2047)
546                         lc = 2047;
547
548                 /* Upload to GART */
549                 if (src_pitch == line_len) {
550                         memcpy(dst, src, src_pitch * lc);
551                         src += src_pitch * lc;
552                 } else {
553                         for (i = 0; i < lc; i++) {
554                                 memcpy(dst, src, line_len);
555                                 src += src_pitch;
556                                 dst += line_len;
557                         }
558                 }
559
560                 if (pNv->Architecture >= NV_ARCH_50) {
561                         BEGIN_RING(NvMemFormat, 0x200, 1);
562                         OUT_RING  (1);
563                         BEGIN_RING(NvMemFormat, 0x21c, 1);
564                         OUT_RING  (1);
565                         /* probably high-order bits of address */
566                         BEGIN_RING(NvMemFormat, 0x238, 2);
567                         OUT_RING  (0);
568                         OUT_RING  (0);
569                 }
570
571                 /* DMA to VRAM */
572                 BEGIN_RING(NvMemFormat,
573                            NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
574                 OUT_RING  ((uint32_t)pNv->GARTScratch->offset);
575                 OUT_RING  ((uint32_t)dst_offset);
576                 OUT_RING  (line_len);
577                 OUT_RING  (dst_pitch);
578                 OUT_RING  (line_len);
579                 OUT_RING  (lc);
580                 OUT_RING  ((1<<8)|1);
581                 OUT_RING  (0);
582
583                 NVNotifierReset(pScrn, pNv->Notifier0);
584                 BEGIN_RING(NvMemFormat, NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1);
585                 OUT_RING  (0);
586                 BEGIN_RING(NvMemFormat, 0x100, 1);
587                 OUT_RING  (0);
588                 FIRE_RING();
589                 if (!NVNotifierWaitStatus(pScrn, pNv->Notifier0, 0, 2000))
590                         return FALSE;
591
592                 dst_offset += lc * dst_pitch;
593                 line_count -= lc;
594         }
595
596         return TRUE;
597 }
598
599 static Bool NVUploadToScreen(PixmapPtr pDst,
600                              int x, int y, int w, int h,
601                              char *src, int src_pitch)
602 {
603         ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
604         NVPtr pNv = NVPTR(pScrn);
605         int dst_offset, dst_pitch, cpp;
606         char *dst;
607
608         dst_offset = NVAccelGetPixmapOffset(pDst);
609         dst_pitch  = exaGetPixmapPitch(pDst);
610         cpp = pDst->drawable.bitsPerPixel >> 3;
611
612         /* try hostdata transfer */
613         if (pNv->Architecture < NV_ARCH_50 && w*h*cpp<16*1024) /* heuristic */
614         {
615                 int fmt;
616
617                 if (NVAccelGetCtxSurf2DFormatFromPixmap(pDst, &fmt)) {
618                         if (NVAccelUploadIFC(pScrn, src, src_pitch, pDst, fmt,
619                                                     x, y, w, h, cpp)) {
620                                 exaMarkSync(pDst->drawable.pScreen);
621                                 return TRUE;
622                         }
623                 }
624         }
625
626         /* try gart-based transfer */
627         if (pNv->GARTScratch) {
628                 dst_offset += (y * dst_pitch) + (x * cpp);
629                 if (NVAccelUploadM2MF(pScrn, dst_offset, src, dst_pitch,
630                                         src_pitch, w * cpp, h))
631                         return TRUE;
632         }
633
634         /* fallback to memcpy-based transfer */
635         dst = NVExaPixmapMap(pDst) + (y * dst_pitch) + (x * cpp);
636         exaWaitSync(pDst->drawable.pScreen);
637         if (NVAccelMemcpyRect(dst, src, h, dst_pitch, src_pitch, w*cpp))
638                 return TRUE;
639
640         return FALSE;
641 }
642
643 Bool
644 NVExaInit(ScreenPtr pScreen) 
645 {
646         ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
647         NVPtr pNv = NVPTR(pScrn);
648
649         if(!(pNv->EXADriverPtr = (ExaDriverPtr) xnfcalloc(sizeof(ExaDriverRec), 1))) {
650                 pNv->NoAccel = TRUE;
651                 return FALSE;
652         }
653
654         pNv->EXADriverPtr->exa_major = EXA_VERSION_MAJOR;
655         pNv->EXADriverPtr->exa_minor = EXA_VERSION_MINOR;
656
657         pNv->EXADriverPtr->memoryBase           = pNv->FB->map;
658         pNv->EXADriverPtr->offScreenBase        =
659                 pScrn->virtualX * pScrn->virtualY*(pScrn->bitsPerPixel/8); 
660         pNv->EXADriverPtr->memorySize           = pNv->FB->size; 
661         pNv->EXADriverPtr->pixmapOffsetAlign    = 256; 
662         pNv->EXADriverPtr->pixmapPitchAlign     = 64; 
663         pNv->EXADriverPtr->flags                = EXA_OFFSCREEN_PIXMAPS;
664         pNv->EXADriverPtr->maxX                 = 32768;
665         pNv->EXADriverPtr->maxY                 = 32768;
666
667         pNv->EXADriverPtr->WaitMarker = NVExaWaitMarker;
668
669         /* Install default hooks */
670         pNv->EXADriverPtr->DownloadFromScreen = NVDownloadFromScreen; 
671         pNv->EXADriverPtr->UploadToScreen = NVUploadToScreen; 
672
673         if (pNv->Architecture < NV_ARCH_50) {
674                 pNv->EXADriverPtr->PrepareCopy = NVExaPrepareCopy;
675                 pNv->EXADriverPtr->Copy = NVExaCopy;
676                 pNv->EXADriverPtr->DoneCopy = NVExaDoneCopy;
677
678                 pNv->EXADriverPtr->PrepareSolid = NVExaPrepareSolid;
679                 pNv->EXADriverPtr->Solid = NVExaSolid;
680                 pNv->EXADriverPtr->DoneSolid = NVExaDoneSolid;
681         } else {
682                 pNv->EXADriverPtr->PrepareCopy = NV50EXAPrepareCopy;
683                 pNv->EXADriverPtr->Copy = NV50EXACopy;
684                 pNv->EXADriverPtr->DoneCopy = NV50EXADoneCopy;
685
686                 pNv->EXADriverPtr->PrepareSolid = NV50EXAPrepareSolid;
687                 pNv->EXADriverPtr->Solid = NV50EXASolid;
688                 pNv->EXADriverPtr->DoneSolid = NV50EXADoneSolid;
689         }
690
691         switch (pNv->Architecture) {
692         
693         case NV_ARCH_10:
694         //case NV_ARCH_20: waiting for confirmation from pq
695                 pNv->EXADriverPtr->CheckComposite   = NV10CheckComposite;
696                 pNv->EXADriverPtr->PrepareComposite = NV10PrepareComposite;
697                 pNv->EXADriverPtr->Composite        = NV10Composite;
698                 pNv->EXADriverPtr->DoneComposite    = NV10DoneComposite;
699                 break;
700         case NV_ARCH_30:
701                 pNv->EXADriverPtr->CheckComposite   = NV30EXACheckComposite;
702                 pNv->EXADriverPtr->PrepareComposite = NV30EXAPrepareComposite;
703                 pNv->EXADriverPtr->Composite        = NV30EXAComposite;
704                 pNv->EXADriverPtr->DoneComposite    = NV30EXADoneComposite;
705                 break;
706         case NV_ARCH_40:
707                 pNv->EXADriverPtr->CheckComposite   = NV40EXACheckComposite;
708                 pNv->EXADriverPtr->PrepareComposite = NV40EXAPrepareComposite;
709                 pNv->EXADriverPtr->Composite        = NV40EXAComposite;
710                 pNv->EXADriverPtr->DoneComposite    = NV40EXADoneComposite;
711                 break;
712         case NV_ARCH_50:
713                 break;
714         default:
715                 break;
716         }
717
718         return exaDriverInit(pScreen, pNv->EXADriverPtr);
719 }
720