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)
44 #include "nv_include.h"
52 const int NVCopyROP[16] =
56 0x44, /* GXandReverse */
58 0x22, /* GXandInverted */
65 0xDD, /* GXorReverse */
66 0x33, /* GXcopyInverted */
67 0xBB, /* GXorInverted */
73 NVSetPattern(ScrnInfoPtr pScrn, CARD32 clr0, CARD32 clr1,
74 CARD32 pat0, CARD32 pat1)
76 NVPtr pNv = NVPTR(pScrn);
78 BEGIN_RING(NvImagePattern, NV04_IMAGE_PATTERN_MONOCHROME_COLOR0, 4);
86 NVSetROP(ScrnInfoPtr pScrn, CARD32 alu, CARD32 planemask)
88 NVPtr pNv = NVPTR(pScrn);
89 int rop = NVCopyROP[alu] & 0xf0;
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;
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;
108 static void setM2MFDirection(ScrnInfoPtr pScrn, int dir)
110 NVPtr pNv = NVPTR(pScrn);
112 if (pNv->M2MFDirection != dir) {
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;
122 static CARD32 rectFormat(DrawablePtr pDrawable)
124 switch(pDrawable->bitsPerPixel) {
127 return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
130 return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A16R5G6B5;
133 return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
138 /* EXA acceleration hooks */
139 static void NVExaWaitMarker(ScreenPtr pScreen, int marker)
141 NVSync(xf86Screens[pScreen->myNum]);
144 static Bool NVExaPrepareSolid(PixmapPtr pPixmap,
149 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
150 NVPtr pNv = NVPTR(pScrn);
153 planemask |= ~0 << pPixmap->drawable.bitsPerPixel;
154 if (planemask != ~0 || alu != GXcopy) {
155 if (pPixmap->drawable.bitsPerPixel == 32)
157 BEGIN_RING(NvRectangle, NV04_GDI_RECTANGLE_TEXT_OPERATION, 1);
158 OUT_RING (1); /* ROP_AND */
159 NVSetROP(pScrn, alu, planemask);
161 BEGIN_RING(NvRectangle, NV04_GDI_RECTANGLE_TEXT_OPERATION, 1);
162 OUT_RING (3); /* SRCCOPY */
165 if (!NVAccelGetCtxSurf2DFormatFromPixmap(pPixmap, &fmt))
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
172 if (fmt == NV04_CONTEXT_SURFACES_2D_FORMAT_A8R8G8B8)
173 fmt = NV04_CONTEXT_SURFACES_2D_FORMAT_Y32;
175 if (!NVAccelSetCtxSurf2D(pPixmap, pPixmap, fmt))
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);
183 pNv->DMAKickoffCallback = NVDmaKickoffCallback;
187 static void NVExaSolid (PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
189 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
190 NVPtr pNv = NVPTR(pScrn);
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);
199 if((width * height) >= 512)
203 static void NVExaDoneSolid (PixmapPtr pPixmap)
207 static Bool NVExaPrepareCopy(PixmapPtr pSrcPixmap,
208 PixmapPtr pDstPixmap,
214 ScrnInfoPtr pScrn = xf86Screens[pSrcPixmap->drawable.pScreen->myNum];
215 NVPtr pNv = NVPTR(pScrn);
218 if (pSrcPixmap->drawable.bitsPerPixel !=
219 pDstPixmap->drawable.bitsPerPixel)
222 planemask |= ~0 << pDstPixmap->drawable.bitsPerPixel;
223 if (planemask != ~0 || alu != GXcopy) {
224 if (pDstPixmap->drawable.bitsPerPixel == 32)
226 BEGIN_RING(NvImageBlit, NV_IMAGE_BLIT_OPERATION, 1);
227 OUT_RING (1); /* ROP_AND */
228 NVSetROP(pScrn, alu, planemask);
230 BEGIN_RING(NvImageBlit, NV_IMAGE_BLIT_OPERATION, 1);
231 OUT_RING (3); /* SRCCOPY */
234 if (!NVAccelGetCtxSurf2DFormatFromPixmap(pDstPixmap, &fmt))
236 if (!NVAccelSetCtxSurf2D(pSrcPixmap, pDstPixmap, fmt))
239 pNv->DMAKickoffCallback = NVDmaKickoffCallback;
243 static void NVExaCopy(PixmapPtr pDstPixmap,
251 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
252 NVPtr pNv = NVPTR(pScrn);
254 /* We want to catch people who have this bug, to find a decent fix */
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...
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))) )
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
275 NVDEBUG("ExaCopy: Lines identical:\n");
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);
292 // 2. Otherwise we will try a line by line copy in the hope to avoid
295 NVDEBUG("ExaCopy: Lines nearly the same srcY=%d, dstY=%d:\n", srcY, dstY);
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);
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);
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);
327 if((width * height) >= 512)
331 static void NVExaDoneCopy (PixmapPtr pDstPixmap) {}
333 static inline Bool NVAccelMemcpyRect(char *dst, const char *src, int height,
334 int dst_pitch, int src_pitch, int line_len)
336 if ((src_pitch == line_len) && (src_pitch == dst_pitch)) {
337 memcpy(dst, src, line_len*height);
340 memcpy(dst, src, line_len);
350 NVAccelDownloadM2MF(ScrnInfoPtr pScrn, char *dst, uint64_t src_offset,
351 int dst_pitch, int src_pitch,
352 int line_len, int line_count)
354 NVPtr pNv = NVPTR(pScrn);
356 setM2MFDirection(pScrn, 0);
359 char *src = pNv->GARTScratch->map;
362 if (line_count * line_len <= pNv->GARTScratch->size) {
365 lc = pNv->GARTScratch->size / line_len;
374 if (pNv->Architecture >= NV_ARCH_50) {
375 BEGIN_RING(NvMemFormat, 0x200, 1);
377 BEGIN_RING(NvMemFormat, 0x21c, 1);
379 /* probably high-order bits of address */
380 BEGIN_RING(NvMemFormat, 0x238, 2);
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);
396 NVNotifierReset(pScrn, pNv->Notifier0);
397 BEGIN_RING(NvMemFormat, NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1);
399 BEGIN_RING(NvMemFormat, 0x100, 1);
402 if (!NVNotifierWaitStatus(pScrn, pNv->Notifier0, 0, 2000))
405 if (dst_pitch == line_len) {
406 memcpy(dst, src, dst_pitch * lc);
407 dst += dst_pitch * lc;
409 for (i = 0; i < lc; i++) {
410 memcpy(dst, src, line_len);
417 src_offset += lc * src_pitch;
424 NVExaPixmapMap(PixmapPtr pPix)
426 ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum];
427 NVPtr pNv = NVPTR(pScrn);
430 map = pNv->FB->map + exaGetPixmapOffset(pPix);
434 static Bool NVDownloadFromScreen(PixmapPtr pSrc,
437 char *dst, int dst_pitch)
439 ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum];
440 NVPtr pNv = NVPTR(pScrn);
441 int src_offset, src_pitch, cpp, offset;
444 src_offset = NVAccelGetPixmapOffset(pSrc);
445 src_pitch = exaGetPixmapPitch(pSrc);
446 cpp = pSrc->drawable.bitsPerPixel >> 3;
447 offset = (y * src_pitch) + (x * cpp);
449 if (pNv->GARTScratch) {
450 if (NVAccelDownloadM2MF(pScrn, dst,
452 dst_pitch, src_pitch, w * cpp, h))
456 src = NVExaPixmapMap(pSrc) + offset;
457 exaWaitSync(pSrc->drawable.pScreen);
458 if (NVAccelMemcpyRect(dst, src, h, dst_pitch, src_pitch, w*cpp))
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)
468 NVPtr pNv = NVPTR(pScrn);
469 int line_len = w * cpp;
472 if (pNv->Architecture >= NV_ARCH_50)
479 case 2: ifc_fmt = 1; break;
480 case 4: ifc_fmt = 4; break;
485 NVAccelSetCtxSurf2D(pDst, pDst, fmt);
487 /* Pad out input width to cover both COLORA() and COLORB() */
488 iw = (line_len + 7) & ~7;
489 id = iw / 4; /* line push size */
492 /* Don't support lines longer than max push size yet.. */
496 BEGIN_RING(NvClipRectangle, NV01_CONTEXT_CLIP_RECTANGLE_POINT, 2);
498 OUT_RING (0x7FFF7FFF);
500 BEGIN_RING(NvImageFromCpu, NV01_IMAGE_FROM_CPU_OPERATION, 2);
501 OUT_RING (NV01_IMAGE_FROM_CPU_OPERATION_SRCCOPY);
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 */
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;
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)
527 NVPtr pNv = NVPTR(pScrn);
529 setM2MFDirection(pScrn, 1);
532 char *dst = pNv->GARTScratch->map;
535 /* Determine max amount of data we can DMA at once */
536 if (line_count * line_len <= pNv->GARTScratch->size) {
539 lc = pNv->GARTScratch->size / line_len;
549 if (src_pitch == line_len) {
550 memcpy(dst, src, src_pitch * lc);
551 src += src_pitch * lc;
553 for (i = 0; i < lc; i++) {
554 memcpy(dst, src, line_len);
560 if (pNv->Architecture >= NV_ARCH_50) {
561 BEGIN_RING(NvMemFormat, 0x200, 1);
563 BEGIN_RING(NvMemFormat, 0x21c, 1);
565 /* probably high-order bits of address */
566 BEGIN_RING(NvMemFormat, 0x238, 2);
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);
577 OUT_RING (dst_pitch);
583 NVNotifierReset(pScrn, pNv->Notifier0);
584 BEGIN_RING(NvMemFormat, NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1);
586 BEGIN_RING(NvMemFormat, 0x100, 1);
589 if (!NVNotifierWaitStatus(pScrn, pNv->Notifier0, 0, 2000))
592 dst_offset += lc * dst_pitch;
599 static Bool NVUploadToScreen(PixmapPtr pDst,
600 int x, int y, int w, int h,
601 char *src, int src_pitch)
603 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
604 NVPtr pNv = NVPTR(pScrn);
605 int dst_offset, dst_pitch, cpp;
608 dst_offset = NVAccelGetPixmapOffset(pDst);
609 dst_pitch = exaGetPixmapPitch(pDst);
610 cpp = pDst->drawable.bitsPerPixel >> 3;
612 /* try hostdata transfer */
613 if (pNv->Architecture < NV_ARCH_50 && w*h*cpp<16*1024) /* heuristic */
617 if (NVAccelGetCtxSurf2DFormatFromPixmap(pDst, &fmt)) {
618 if (NVAccelUploadIFC(pScrn, src, src_pitch, pDst, fmt,
620 exaMarkSync(pDst->drawable.pScreen);
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))
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))
644 NVExaInit(ScreenPtr pScreen)
646 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
647 NVPtr pNv = NVPTR(pScrn);
649 if(!(pNv->EXADriverPtr = (ExaDriverPtr) xnfcalloc(sizeof(ExaDriverRec), 1))) {
654 pNv->EXADriverPtr->exa_major = EXA_VERSION_MAJOR;
655 pNv->EXADriverPtr->exa_minor = EXA_VERSION_MINOR;
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;
667 pNv->EXADriverPtr->WaitMarker = NVExaWaitMarker;
669 /* Install default hooks */
670 pNv->EXADriverPtr->DownloadFromScreen = NVDownloadFromScreen;
671 pNv->EXADriverPtr->UploadToScreen = NVUploadToScreen;
673 if (pNv->Architecture < NV_ARCH_50) {
674 pNv->EXADriverPtr->PrepareCopy = NVExaPrepareCopy;
675 pNv->EXADriverPtr->Copy = NVExaCopy;
676 pNv->EXADriverPtr->DoneCopy = NVExaDoneCopy;
678 pNv->EXADriverPtr->PrepareSolid = NVExaPrepareSolid;
679 pNv->EXADriverPtr->Solid = NVExaSolid;
680 pNv->EXADriverPtr->DoneSolid = NVExaDoneSolid;
682 pNv->EXADriverPtr->PrepareCopy = NV50EXAPrepareCopy;
683 pNv->EXADriverPtr->Copy = NV50EXACopy;
684 pNv->EXADriverPtr->DoneCopy = NV50EXADoneCopy;
686 pNv->EXADriverPtr->PrepareSolid = NV50EXAPrepareSolid;
687 pNv->EXADriverPtr->Solid = NV50EXASolid;
688 pNv->EXADriverPtr->DoneSolid = NV50EXADoneSolid;
691 switch (pNv->Architecture) {
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;
701 pNv->EXADriverPtr->CheckComposite = NV30EXACheckComposite;
702 pNv->EXADriverPtr->PrepareComposite = NV30EXAPrepareComposite;
703 pNv->EXADriverPtr->Composite = NV30EXAComposite;
704 pNv->EXADriverPtr->DoneComposite = NV30EXADoneComposite;
707 pNv->EXADriverPtr->CheckComposite = NV40EXACheckComposite;
708 pNv->EXADriverPtr->PrepareComposite = NV40EXAPrepareComposite;
709 pNv->EXADriverPtr->Composite = NV40EXAComposite;
710 pNv->EXADriverPtr->DoneComposite = NV40EXADoneComposite;
718 return exaDriverInit(pScreen, pNv->EXADriverPtr);