1 /***************************************************************************\
3 |* Copyright 2003 NVIDIA, Corporation. All rights reserved. *|
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. *|
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 *|
14 |* Copyright 2003 NVIDIA, Corporation. All rights reserved. *|
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. *|
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. *|
38 \***************************************************************************/
41 Exa Modifications (c) Lars Knoll (lars@trolltech.com)
48 #include "nv_include.h"
56 const int NVCopyROP[16] =
60 0x44, /* GXandReverse */
62 0x22, /* GXandInverted */
69 0xDD, /* GXorReverse */
70 0x33, /* GXcopyInverted */
71 0xBB, /* GXorInverted */
77 NVSetPattern(ScrnInfoPtr pScrn, CARD32 clr0, CARD32 clr1,
78 CARD32 pat0, CARD32 pat1)
80 NVPtr pNv = NVPTR(pScrn);
82 BEGIN_RING(NvImagePattern, NV04_IMAGE_PATTERN_MONOCHROME_COLOR0, 4);
90 NVSetROP(ScrnInfoPtr pScrn, CARD32 alu, CARD32 planemask)
92 NVPtr pNv = NVPTR(pScrn);
93 int rop = NVCopyROP[alu] & 0xf0;
95 if (planemask != ~0) {
96 NVSetPattern(pScrn, 0, planemask, ~0, ~0);
97 if (pNv->currentRop != (alu + 32)) {
98 BEGIN_RING(NvRop, NV03_CONTEXT_ROP_ROP, 1);
99 OUT_RING (rop | 0x0a);
100 pNv->currentRop = alu + 32;
103 if (pNv->currentRop != alu) {
104 if(pNv->currentRop >= 16)
105 NVSetPattern(pScrn, ~0, ~0, ~0, ~0);
106 BEGIN_RING(NvRop, NV03_CONTEXT_ROP_ROP, 1);
107 OUT_RING (rop | (rop >> 4));
108 pNv->currentRop = alu;
112 static void setM2MFDirection(ScrnInfoPtr pScrn, int dir)
114 NVPtr pNv = NVPTR(pScrn);
116 if (pNv->M2MFDirection != dir) {
118 BEGIN_RING(NvMemFormat,
119 NV_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2);
120 OUT_RING (dir ? NvDmaTT : NvDmaFB);
121 OUT_RING (dir ? NvDmaFB : NvDmaTT);
122 pNv->M2MFDirection = dir;
126 static CARD32 rectFormat(DrawablePtr pDrawable)
128 switch(pDrawable->bitsPerPixel) {
131 return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
134 return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A16R5G6B5;
137 return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
142 /* EXA acceleration hooks */
143 static void NVExaWaitMarker(ScreenPtr pScreen, int marker)
145 NVSync(xf86Screens[pScreen->myNum]);
148 static Bool NVExaPrepareSolid(PixmapPtr pPixmap,
153 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
154 NVPtr pNv = NVPTR(pScrn);
157 planemask |= ~0 << pPixmap->drawable.bitsPerPixel;
158 if (planemask != ~0 || alu != GXcopy) {
159 if (pPixmap->drawable.bitsPerPixel == 32)
161 BEGIN_RING(NvRectangle, NV04_GDI_RECTANGLE_TEXT_OPERATION, 1);
162 OUT_RING (1); /* ROP_AND */
163 NVSetROP(pScrn, alu, planemask);
165 BEGIN_RING(NvRectangle, NV04_GDI_RECTANGLE_TEXT_OPERATION, 1);
166 OUT_RING (3); /* SRCCOPY */
169 if (!NVAccelGetCtxSurf2DFormatFromPixmap(pPixmap, &fmt))
172 /* When SURFACE_FORMAT_A8R8G8B8 is used with GDI_RECTANGLE_TEXT, the
173 * alpha channel gets forced to 0xFF for some reason. We're using
174 * SURFACE_FORMAT_Y32 as a workaround
176 if (fmt == NV04_CONTEXT_SURFACES_2D_FORMAT_A8R8G8B8)
177 fmt = NV04_CONTEXT_SURFACES_2D_FORMAT_Y32;
179 if (!NVAccelSetCtxSurf2D(pPixmap, pPixmap, fmt))
182 BEGIN_RING(NvRectangle, NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT, 1);
183 OUT_RING (rectFormat(&pPixmap->drawable));
184 BEGIN_RING(NvRectangle, NV04_GDI_RECTANGLE_TEXT_COLOR1_A, 1);
187 pNv->DMAKickoffCallback = NVDmaKickoffCallback;
191 static void NVExaSolid (PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
193 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
194 NVPtr pNv = NVPTR(pScrn);
198 BEGIN_RING(NvRectangle,
199 NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT(0), 2);
200 OUT_RING ((x1 << 16) | y1);
201 OUT_RING ((width << 16) | height);
203 if((width * height) >= 512)
207 static void NVExaDoneSolid (PixmapPtr pPixmap)
211 static Bool NVExaPrepareCopy(PixmapPtr pSrcPixmap,
212 PixmapPtr pDstPixmap,
218 ScrnInfoPtr pScrn = xf86Screens[pSrcPixmap->drawable.pScreen->myNum];
219 NVPtr pNv = NVPTR(pScrn);
222 if (pSrcPixmap->drawable.bitsPerPixel !=
223 pDstPixmap->drawable.bitsPerPixel)
226 planemask |= ~0 << pDstPixmap->drawable.bitsPerPixel;
227 if (planemask != ~0 || alu != GXcopy) {
228 if (pDstPixmap->drawable.bitsPerPixel == 32)
230 BEGIN_RING(NvImageBlit, NV_IMAGE_BLIT_OPERATION, 1);
231 OUT_RING (1); /* ROP_AND */
232 NVSetROP(pScrn, alu, planemask);
234 BEGIN_RING(NvImageBlit, NV_IMAGE_BLIT_OPERATION, 1);
235 OUT_RING (3); /* SRCCOPY */
238 if (!NVAccelGetCtxSurf2DFormatFromPixmap(pDstPixmap, &fmt))
240 if (!NVAccelSetCtxSurf2D(pSrcPixmap, pDstPixmap, fmt))
243 pNv->DMAKickoffCallback = NVDmaKickoffCallback;
247 static void NVExaCopy(PixmapPtr pDstPixmap,
255 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
256 NVPtr pNv = NVPTR(pScrn);
258 /* We want to catch people who have this bug, to find a decent fix */
260 /* Now check whether we have the same values for srcY and dstY and
261 whether the used chipset is buggy. Currently we flag all of G70
262 cards as buggy, which is probably much to broad. KoalaBR
263 16 is an abritrary threshold. It should define the maximum number
264 of lines between dstY and srcY If the number of lines is below
265 we guess, that the bug won't trigger...
267 if ( ((abs(srcY - dstY)< 16)||(abs(srcX-dstX)<16)) &&
268 ((((pNv->Chipset & 0xfff0) == CHIPSET_G70) ||
269 ((pNv->Chipset & 0xfff0) == CHIPSET_G71) ||
270 ((pNv->Chipset & 0xfff0) == CHIPSET_G72) ||
271 ((pNv->Chipset & 0xfff0) == CHIPSET_G73) ||
272 ((pNv->Chipset & 0xfff0) == CHIPSET_C512))) )
274 int dx=abs(srcX - dstX),dy=abs(srcY - dstY);
275 // Ok, let's do it manually unless someone comes up with a better idea
276 // 1. If dstY and srcY are really the same, do a copy rowwise
279 NVDEBUG("ExaCopy: Lines identical:\n");
287 for (i = 0; i < width; i++) {
288 BEGIN_RING(NvImageBlit,
289 NV_IMAGE_BLIT_POINT_IN, 3);
290 OUT_RING ((srcY << 16) | (srcX+xpos));
291 OUT_RING ((dstY << 16) | (dstX+xpos));
292 OUT_RING ((height << 16) | 1);
296 // 2. Otherwise we will try a line by line copy in the hope to avoid
299 NVDEBUG("ExaCopy: Lines nearly the same srcY=%d, dstY=%d:\n", srcY, dstY);
307 for (i = 0; i < height; i++) {
308 BEGIN_RING(NvImageBlit,
309 NV_IMAGE_BLIT_POINT_IN, 3);
310 OUT_RING (((srcY+ypos) << 16) | srcX);
311 OUT_RING (((dstY+ypos) << 16) | dstX);
312 OUT_RING ((1 << 16) | width);
317 NVDEBUG("ExaCopy: Using default path\n");
318 BEGIN_RING(NvImageBlit, NV_IMAGE_BLIT_POINT_IN, 3);
319 OUT_RING ((srcY << 16) | srcX);
320 OUT_RING ((dstY << 16) | dstX);
321 OUT_RING ((height << 16) | width);
325 NVDEBUG("ExaCopy: Using default path\n");
326 BEGIN_RING(NvImageBlit, NV_IMAGE_BLIT_POINT_IN, 3);
327 OUT_RING ((srcY << 16) | srcX);
328 OUT_RING ((dstY << 16) | dstX);
329 OUT_RING ((height << 16) | width);
331 if((width * height) >= 512)
335 static void NVExaDoneCopy (PixmapPtr pDstPixmap) {}
337 static inline Bool NVAccelMemcpyRect(char *dst, const char *src, int height,
338 int dst_pitch, int src_pitch, int line_len)
340 if ((src_pitch == line_len) && (src_pitch == dst_pitch)) {
341 memcpy(dst, src, line_len*height);
344 memcpy(dst, src, line_len);
354 NVAccelDownloadM2MF(ScrnInfoPtr pScrn, char *dst, uint64_t src_offset,
355 int dst_pitch, int src_pitch,
356 int line_len, int line_count)
358 NVPtr pNv = NVPTR(pScrn);
360 setM2MFDirection(pScrn, 0);
363 char *src = pNv->GARTScratch->map;
366 if (line_count * line_len <= pNv->GARTScratch->size) {
369 lc = pNv->GARTScratch->size / line_len;
378 if (pNv->Architecture >= NV_ARCH_50) {
379 BEGIN_RING(NvMemFormat, 0x200, 1);
381 BEGIN_RING(NvMemFormat, 0x21c, 1);
383 /* probably high-order bits of address */
384 BEGIN_RING(NvMemFormat, 0x238, 2);
389 BEGIN_RING(NvMemFormat,
390 NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
391 OUT_RING ((uint32_t)src_offset);
392 OUT_RING ((uint32_t)pNv->GARTScratch->offset);
393 OUT_RING (src_pitch);
400 NVNotifierReset(pScrn, pNv->Notifier0);
401 BEGIN_RING(NvMemFormat, NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1);
403 BEGIN_RING(NvMemFormat, 0x100, 1);
406 if (!NVNotifierWaitStatus(pScrn, pNv->Notifier0, 0, 2000))
409 if (dst_pitch == line_len) {
410 memcpy(dst, src, dst_pitch * lc);
411 dst += dst_pitch * lc;
413 for (i = 0; i < lc; i++) {
414 memcpy(dst, src, line_len);
421 src_offset += lc * src_pitch;
428 NVExaPixmapMap(PixmapPtr pPix)
430 ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum];
431 NVPtr pNv = NVPTR(pScrn);
434 map = pNv->FB->map + exaGetPixmapOffset(pPix);
438 static Bool NVDownloadFromScreen(PixmapPtr pSrc,
441 char *dst, int dst_pitch)
443 ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum];
444 NVPtr pNv = NVPTR(pScrn);
445 int src_offset, src_pitch, cpp, offset;
448 src_offset = NVAccelGetPixmapOffset(pSrc);
449 src_pitch = exaGetPixmapPitch(pSrc);
450 cpp = pSrc->drawable.bitsPerPixel >> 3;
451 offset = (y * src_pitch) + (x * cpp);
453 if (pNv->GARTScratch) {
454 if (NVAccelDownloadM2MF(pScrn, dst,
456 dst_pitch, src_pitch, w * cpp, h))
460 src = NVExaPixmapMap(pSrc) + offset;
461 exaWaitSync(pSrc->drawable.pScreen);
462 if (NVAccelMemcpyRect(dst, src, h, dst_pitch, src_pitch, w*cpp))
469 NVAccelUploadIFC(ScrnInfoPtr pScrn, const char *src, int src_pitch,
470 PixmapPtr pDst, int fmt, int x, int y, int w, int h, int cpp)
472 NVPtr pNv = NVPTR(pScrn);
473 int line_len = w * cpp;
476 if (pNv->Architecture >= NV_ARCH_50)
483 case 2: ifc_fmt = 1; break;
484 case 4: ifc_fmt = 4; break;
489 NVAccelSetCtxSurf2D(pDst, pDst, fmt);
491 /* Pad out input width to cover both COLORA() and COLORB() */
492 iw = (line_len + 7) & ~7;
493 id = iw / 4; /* line push size */
496 /* Don't support lines longer than max push size yet.. */
500 BEGIN_RING(NvClipRectangle, NV01_CONTEXT_CLIP_RECTANGLE_POINT, 2);
502 OUT_RING (0x7FFF7FFF);
504 BEGIN_RING(NvImageFromCpu, NV01_IMAGE_FROM_CPU_OPERATION, 2);
505 OUT_RING (NV01_IMAGE_FROM_CPU_OPERATION_SRCCOPY);
507 BEGIN_RING(NvImageFromCpu, NV01_IMAGE_FROM_CPU_POINT, 3);
508 OUT_RING ((y << 16) | x); /* dst point */
509 OUT_RING ((h << 16) | w); /* width/height out */
510 OUT_RING ((h << 16) | iw); /* width/height in */
515 BEGIN_RING(NvImageFromCpu, NV01_IMAGE_FROM_CPU_COLOR(0), id);
516 dst = (char *)pNv->dmaBase + (pNv->dmaCurrent << 2);
517 memcpy(dst, src, line_len);
518 pNv->dmaCurrent += id;
527 NVAccelUploadM2MF(ScrnInfoPtr pScrn, uint64_t dst_offset, const char *src,
528 int dst_pitch, int src_pitch,
529 int line_len, int line_count)
531 NVPtr pNv = NVPTR(pScrn);
533 setM2MFDirection(pScrn, 1);
536 char *dst = pNv->GARTScratch->map;
539 /* Determine max amount of data we can DMA at once */
540 if (line_count * line_len <= pNv->GARTScratch->size) {
543 lc = pNv->GARTScratch->size / line_len;
553 if (src_pitch == line_len) {
554 memcpy(dst, src, src_pitch * lc);
555 src += src_pitch * lc;
557 for (i = 0; i < lc; i++) {
558 memcpy(dst, src, line_len);
564 if (pNv->Architecture >= NV_ARCH_50) {
565 BEGIN_RING(NvMemFormat, 0x200, 1);
567 BEGIN_RING(NvMemFormat, 0x21c, 1);
569 /* probably high-order bits of address */
570 BEGIN_RING(NvMemFormat, 0x238, 2);
576 BEGIN_RING(NvMemFormat,
577 NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
578 OUT_RING ((uint32_t)pNv->GARTScratch->offset);
579 OUT_RING ((uint32_t)dst_offset);
581 OUT_RING (dst_pitch);
587 NVNotifierReset(pScrn, pNv->Notifier0);
588 BEGIN_RING(NvMemFormat, NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1);
590 BEGIN_RING(NvMemFormat, 0x100, 1);
593 if (!NVNotifierWaitStatus(pScrn, pNv->Notifier0, 0, 2000))
596 dst_offset += lc * dst_pitch;
603 static Bool NVUploadToScreen(PixmapPtr pDst,
604 int x, int y, int w, int h,
605 char *src, int src_pitch)
607 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
608 NVPtr pNv = NVPTR(pScrn);
609 int dst_offset, dst_pitch, cpp;
612 dst_offset = NVAccelGetPixmapOffset(pDst);
613 dst_pitch = exaGetPixmapPitch(pDst);
614 cpp = pDst->drawable.bitsPerPixel >> 3;
616 /* try hostdata transfer */
617 if (pNv->Architecture < NV_ARCH_50 && w*h*cpp<16*1024) /* heuristic */
621 if (NVAccelGetCtxSurf2DFormatFromPixmap(pDst, &fmt)) {
622 if (NVAccelUploadIFC(pScrn, src, src_pitch, pDst, fmt,
624 exaMarkSync(pDst->drawable.pScreen);
630 /* try gart-based transfer */
631 if (pNv->GARTScratch) {
632 dst_offset += (y * dst_pitch) + (x * cpp);
633 if (NVAccelUploadM2MF(pScrn, dst_offset, src, dst_pitch,
634 src_pitch, w * cpp, h))
638 /* fallback to memcpy-based transfer */
639 dst = NVExaPixmapMap(pDst) + (y * dst_pitch) + (x * cpp);
640 exaWaitSync(pDst->drawable.pScreen);
641 if (NVAccelMemcpyRect(dst, src, h, dst_pitch, src_pitch, w*cpp))
648 NVExaInit(ScreenPtr pScreen)
650 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
651 NVPtr pNv = NVPTR(pScrn);
653 if(!(pNv->EXADriverPtr = (ExaDriverPtr) xnfcalloc(sizeof(ExaDriverRec), 1))) {
658 pNv->EXADriverPtr->exa_major = EXA_VERSION_MAJOR;
659 pNv->EXADriverPtr->exa_minor = EXA_VERSION_MINOR;
661 pNv->EXADriverPtr->memoryBase = pNv->FB->map;
662 pNv->EXADriverPtr->offScreenBase =
663 pScrn->virtualX * pScrn->virtualY*(pScrn->bitsPerPixel/8);
664 pNv->EXADriverPtr->memorySize = pNv->FB->size;
665 pNv->EXADriverPtr->pixmapOffsetAlign = 256;
666 pNv->EXADriverPtr->pixmapPitchAlign = 64;
667 pNv->EXADriverPtr->flags = EXA_OFFSCREEN_PIXMAPS;
668 pNv->EXADriverPtr->maxX = 32768;
669 pNv->EXADriverPtr->maxY = 32768;
671 pNv->EXADriverPtr->WaitMarker = NVExaWaitMarker;
673 /* Install default hooks */
674 pNv->EXADriverPtr->DownloadFromScreen = NVDownloadFromScreen;
675 pNv->EXADriverPtr->UploadToScreen = NVUploadToScreen;
677 if (pNv->Architecture < NV_ARCH_50) {
678 pNv->EXADriverPtr->PrepareCopy = NVExaPrepareCopy;
679 pNv->EXADriverPtr->Copy = NVExaCopy;
680 pNv->EXADriverPtr->DoneCopy = NVExaDoneCopy;
682 pNv->EXADriverPtr->PrepareSolid = NVExaPrepareSolid;
683 pNv->EXADriverPtr->Solid = NVExaSolid;
684 pNv->EXADriverPtr->DoneSolid = NVExaDoneSolid;
686 pNv->EXADriverPtr->PrepareCopy = NV50EXAPrepareCopy;
687 pNv->EXADriverPtr->Copy = NV50EXACopy;
688 pNv->EXADriverPtr->DoneCopy = NV50EXADoneCopy;
690 pNv->EXADriverPtr->PrepareSolid = NV50EXAPrepareSolid;
691 pNv->EXADriverPtr->Solid = NV50EXASolid;
692 pNv->EXADriverPtr->DoneSolid = NV50EXADoneSolid;
695 switch (pNv->Architecture) {
698 //case NV_ARCH_20: waiting for confirmation from pq
699 pNv->EXADriverPtr->CheckComposite = NV10CheckComposite;
700 pNv->EXADriverPtr->PrepareComposite = NV10PrepareComposite;
701 pNv->EXADriverPtr->Composite = NV10Composite;
702 pNv->EXADriverPtr->DoneComposite = NV10DoneComposite;
705 #if (X_BYTE_ORDER == X_LITTLE_ENDIAN) && defined(ENABLE_NV30EXA)
707 pNv->EXADriverPtr->CheckComposite = NV30EXACheckComposite;
708 pNv->EXADriverPtr->PrepareComposite = NV30EXAPrepareComposite;
709 pNv->EXADriverPtr->Composite = NV30EXAComposite;
710 pNv->EXADriverPtr->DoneComposite = NV30EXADoneComposite;
714 pNv->EXADriverPtr->CheckComposite = NV40EXACheckComposite;
715 pNv->EXADriverPtr->PrepareComposite = NV40EXAPrepareComposite;
716 pNv->EXADriverPtr->Composite = NV40EXAComposite;
717 pNv->EXADriverPtr->DoneComposite = NV40EXADoneComposite;
725 return exaDriverInit(pScreen, pNv->EXADriverPtr);