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;
427 static Bool NVDownloadFromScreen(PixmapPtr pSrc,
430 char *dst, int dst_pitch)
432 ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum];
433 NVPtr pNv = NVPTR(pScrn);
434 int src_offset, src_pitch, cpp, offset;
437 src_offset = NVAccelGetPixmapOffset(pSrc);
438 src_pitch = exaGetPixmapPitch(pSrc);
439 cpp = pSrc->drawable.bitsPerPixel >> 3;
440 offset = (y * src_pitch) + (x * cpp);
442 if (pNv->GARTScratch) {
443 if (NVAccelDownloadM2MF(pScrn, dst,
445 dst_pitch, src_pitch, w * cpp, h))
449 src = (char *) src_offset + offset;
450 exaWaitSync(pSrc->drawable.pScreen);
451 if (NVAccelMemcpyRect(dst, src, h, dst_pitch, src_pitch, w*cpp))
458 NVAccelUploadIFC(ScrnInfoPtr pScrn, const char *src, int src_pitch,
459 PixmapPtr pDst, int fmt, int x, int y, int w, int h, int cpp)
461 NVPtr pNv = NVPTR(pScrn);
462 int line_len = w * cpp;
465 if (pNv->Architecture >= NV_ARCH_50)
472 case 2: ifc_fmt = 1; break;
473 case 4: ifc_fmt = 4; break;
478 NVAccelSetCtxSurf2D(pDst, pDst, fmt);
480 /* Pad out input width to cover both COLORA() and COLORB() */
481 iw = (line_len + 7) & ~7;
482 id = iw / 4; /* line push size */
485 /* Don't support lines longer than max push size yet.. */
489 BEGIN_RING(NvClipRectangle, NV01_CONTEXT_CLIP_RECTANGLE_POINT, 2);
491 OUT_RING (0x7FFF7FFF);
493 BEGIN_RING(NvImageFromCpu, NV01_IMAGE_FROM_CPU_OPERATION, 2);
494 OUT_RING (NV01_IMAGE_FROM_CPU_OPERATION_SRCCOPY);
496 BEGIN_RING(NvImageFromCpu, NV01_IMAGE_FROM_CPU_POINT, 3);
497 OUT_RING ((y << 16) | x); /* dst point */
498 OUT_RING ((h << 16) | w); /* width/height out */
499 OUT_RING ((h << 16) | iw); /* width/height in */
504 BEGIN_RING(NvImageFromCpu, NV01_IMAGE_FROM_CPU_COLOR(0), id);
505 dst = (char *)pNv->dmaBase + (pNv->dmaCurrent << 2);
506 memcpy(dst, src, line_len);
507 pNv->dmaCurrent += id;
516 NVAccelUploadM2MF(ScrnInfoPtr pScrn, uint64_t dst_offset, const char *src,
517 int dst_pitch, int src_pitch,
518 int line_len, int line_count)
520 NVPtr pNv = NVPTR(pScrn);
522 setM2MFDirection(pScrn, 1);
525 char *dst = pNv->GARTScratch->map;
528 /* Determine max amount of data we can DMA at once */
529 if (line_count * line_len <= pNv->GARTScratch->size) {
532 lc = pNv->GARTScratch->size / line_len;
542 if (src_pitch == line_len) {
543 memcpy(dst, src, src_pitch * lc);
544 src += src_pitch * lc;
546 for (i = 0; i < lc; i++) {
547 memcpy(dst, src, line_len);
553 if (pNv->Architecture >= NV_ARCH_50) {
554 BEGIN_RING(NvMemFormat, 0x200, 1);
556 BEGIN_RING(NvMemFormat, 0x21c, 1);
558 /* probably high-order bits of address */
559 BEGIN_RING(NvMemFormat, 0x238, 2);
565 BEGIN_RING(NvMemFormat,
566 NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
567 OUT_RING ((uint32_t)pNv->GARTScratch->offset);
568 OUT_RING ((uint32_t)dst_offset);
570 OUT_RING (dst_pitch);
576 NVNotifierReset(pScrn, pNv->Notifier0);
577 BEGIN_RING(NvMemFormat, NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1);
579 BEGIN_RING(NvMemFormat, 0x100, 1);
582 if (!NVNotifierWaitStatus(pScrn, pNv->Notifier0, 0, 2000))
585 dst_offset += lc * dst_pitch;
592 static Bool NVUploadToScreen(PixmapPtr pDst,
593 int x, int y, int w, int h,
594 char *src, int src_pitch)
596 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
597 NVPtr pNv = NVPTR(pScrn);
598 int dst_offset, dst_pitch, cpp;
601 dst_offset = NVAccelGetPixmapOffset(pDst);
602 dst_pitch = exaGetPixmapPitch(pDst);
603 cpp = pDst->drawable.bitsPerPixel >> 3;
605 /* try hostdata transfer */
606 if (pNv->Architecture < NV_ARCH_50 && w*h*cpp<16*1024) /* heuristic */
610 if (NVAccelGetCtxSurf2DFormatFromPixmap(pDst, &fmt)) {
611 if (NVAccelUploadIFC(pScrn, src, src_pitch, pDst, fmt,
613 exaMarkSync(pDst->drawable.pScreen);
619 /* try gart-based transfer */
620 if (pNv->GARTScratch) {
621 dst_offset += (y * dst_pitch) + (x * cpp);
622 if (NVAccelUploadM2MF(pScrn, dst_offset, src, dst_pitch,
623 src_pitch, w * cpp, h))
627 /* fallback to memcpy-based transfer */
628 dst = (char *) dst_offset + (y * dst_pitch) + (x * cpp);
629 exaWaitSync(pDst->drawable.pScreen);
630 if (NVAccelMemcpyRect(dst, src, h, dst_pitch, src_pitch, w*cpp))
637 NVExaInit(ScreenPtr pScreen)
639 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
640 NVPtr pNv = NVPTR(pScrn);
642 if(!(pNv->EXADriverPtr = (ExaDriverPtr) xnfcalloc(sizeof(ExaDriverRec), 1))) {
647 pNv->EXADriverPtr->exa_major = EXA_VERSION_MAJOR;
648 pNv->EXADriverPtr->exa_minor = EXA_VERSION_MINOR;
650 pNv->EXADriverPtr->memoryBase = pNv->FB->map;
651 pNv->EXADriverPtr->offScreenBase =
652 pScrn->virtualX * pScrn->virtualY*(pScrn->bitsPerPixel/8);
653 pNv->EXADriverPtr->memorySize = pNv->FB->size;
654 pNv->EXADriverPtr->pixmapOffsetAlign = 256;
655 pNv->EXADriverPtr->pixmapPitchAlign = 64;
656 pNv->EXADriverPtr->flags = EXA_OFFSCREEN_PIXMAPS;
657 pNv->EXADriverPtr->maxX = 32768;
658 pNv->EXADriverPtr->maxY = 32768;
660 pNv->EXADriverPtr->WaitMarker = NVExaWaitMarker;
662 /* Install default hooks */
663 pNv->EXADriverPtr->DownloadFromScreen = NVDownloadFromScreen;
664 pNv->EXADriverPtr->UploadToScreen = NVUploadToScreen;
666 if (pNv->Architecture < NV_ARCH_50) {
667 pNv->EXADriverPtr->PrepareCopy = NVExaPrepareCopy;
668 pNv->EXADriverPtr->Copy = NVExaCopy;
669 pNv->EXADriverPtr->DoneCopy = NVExaDoneCopy;
671 pNv->EXADriverPtr->PrepareSolid = NVExaPrepareSolid;
672 pNv->EXADriverPtr->Solid = NVExaSolid;
673 pNv->EXADriverPtr->DoneSolid = NVExaDoneSolid;
675 pNv->EXADriverPtr->PrepareCopy = NV50EXAPrepareCopy;
676 pNv->EXADriverPtr->Copy = NV50EXACopy;
677 pNv->EXADriverPtr->DoneCopy = NV50EXADoneCopy;
679 pNv->EXADriverPtr->PrepareSolid = NV50EXAPrepareSolid;
680 pNv->EXADriverPtr->Solid = NV50EXASolid;
681 pNv->EXADriverPtr->DoneSolid = NV50EXADoneSolid;
684 switch (pNv->Architecture) {
687 //case NV_ARCH_20: waiting for confirmation from pq
688 pNv->EXADriverPtr->CheckComposite = NV10CheckComposite;
689 pNv->EXADriverPtr->PrepareComposite = NV10PrepareComposite;
690 pNv->EXADriverPtr->Composite = NV10Composite;
691 pNv->EXADriverPtr->DoneComposite = NV10DoneComposite;
694 #if (X_BYTE_ORDER == X_LITTLE_ENDIAN) && defined(ENABLE_NV30EXA)
696 pNv->EXADriverPtr->CheckComposite = NV30EXACheckComposite;
697 pNv->EXADriverPtr->PrepareComposite = NV30EXAPrepareComposite;
698 pNv->EXADriverPtr->Composite = NV30EXAComposite;
699 pNv->EXADriverPtr->DoneComposite = NV30EXADoneComposite;
702 pNv->EXADriverPtr->CheckComposite = NV40EXACheckComposite;
703 pNv->EXADriverPtr->PrepareComposite = NV40EXAPrepareComposite;
704 pNv->EXADriverPtr->Composite = NV40EXAComposite;
705 pNv->EXADriverPtr->DoneComposite = NV40EXADoneComposite;
714 return exaDriverInit(pScreen, pNv->EXADriverPtr);