summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Skeggs <skeggsb@gmail.com>2007-07-01 18:19:44 +1000
committerBen Skeggs <skeggsb@gmail.com>2007-07-01 18:21:23 +1000
commit2e0e7e3856573fbbcb5fe5c96cadcde4d33db68f (patch)
tree6284acb88f58fc12dd76b02d498ff51aa824ca2a
parentba0d3fbba7c1a83ddc509414772199862a4a1d03 (diff)
downloadxorg-driver-xf86-video-nouveau-2e0e7e3856573fbbcb5fe5c96cadcde4d33db68f.tar.gz
Always provide DFS, use memcpy fallback if no GART.
-rw-r--r--src/nv_exa.c134
1 files changed, 91 insertions, 43 deletions
diff --git a/src/nv_exa.c b/src/nv_exa.c
index 995e531..50306ee 100644
--- a/src/nv_exa.c
+++ b/src/nv_exa.c
@@ -260,61 +260,108 @@ static void NVExaCopy(PixmapPtr pDstPixmap,
static void NVExaDoneCopy (PixmapPtr pDstPixmap) {}
-static Bool NVDownloadFromScreen(PixmapPtr pSrc,
- int x, int y,
- int w, int h,
- char *dst, int dst_pitch)
+Bool NVAccelMemcpyRect(char *dst, const char *src, int height,
+ int dst_pitch, int src_pitch, int line_len)
{
- ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum];
- NVPtr pNv = NVPTR(pScrn);
- CARD32 offset_in, pitch_in, max_lines, line_length;
- Bool ret = TRUE;
+ if ((src_pitch == line_len) && (src_pitch == dst_pitch)) {
+ memcpy(dst, src, line_len*height);
+ } else {
+ while (height--) {
+ memcpy(dst, src, line_len);
+ src += src_pitch;
+ dst += dst_pitch;
+ }
+ }
- pitch_in = exaGetPixmapPitch(pSrc);
- offset_in = NVAccelGetPixmapOffset(pSrc);
- offset_in += y*pitch_in;
- offset_in += x * (pSrc->drawable.bitsPerPixel >> 3);
- max_lines = 65536/dst_pitch + 1;
- line_length = w * (pSrc->drawable.bitsPerPixel >> 3);
+ return TRUE;
+}
+
+Bool
+NVAccelDownloadM2MF(ScrnInfoPtr pScrn, char *dst, uint64_t src_offset,
+ int dst_pitch, int src_pitch,
+ int line_len, int line_count)
+{
+ NVPtr pNv = NVPTR(pScrn);
setM2MFDirection(pScrn, 0);
- NVDEBUG("NVDownloadFromScreen: x=%d, y=%d, w=%d, h=%d\n", x, y, w, h);
- NVDEBUG(" pitch_in=%x dst_pitch=%x offset_in=%x",
- pitch_in, dst_pitch, offset_in);
- while (h > 0) {
- int nlines = h > max_lines ? max_lines : h;
- NVDEBUG(" max_lines=%d, h=%d\n", max_lines, h);
+ while (line_count) {
+ char *src = pNv->AGPScratch->map;
+ int lc, i;
+
+ if (line_count * line_len <= pNv->AGPScratch->size) {
+ lc = line_count;
+ } else {
+ lc = pNv->AGPScratch->size / line_len;
+ if (lc > line_count)
+ lc = line_count;
+ }
+ /*XXX: and hw limitations? */
- /* reset the notification object */
NVNotifierReset(pScrn, pNv->Notifier0);
- NVDmaStart(pNv, NvSubMemFormat, MEMFORMAT_NOTIFY, 1);
+ NVDmaStart(pNv, NvSubMemFormat,
+ NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1);
NVDmaNext (pNv, 0);
- NVDmaStart(pNv, NvSubMemFormat, MEMFORMAT_OFFSET_IN, 8);
- NVDmaNext (pNv, offset_in);
+ NVDmaStart(pNv, NvSubMemFormat,
+ NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
+ NVDmaNext (pNv, (uint32_t)src_offset);
NVDmaNext (pNv, (uint32_t)pNv->AGPScratch->offset);
- NVDmaNext (pNv, pitch_in);
- NVDmaNext (pNv, dst_pitch);
- NVDmaNext (pNv, line_length);
- NVDmaNext (pNv, nlines);
- NVDmaNext (pNv, 0x101);
+ NVDmaNext (pNv, src_pitch);
+ NVDmaNext (pNv, line_len);
+ NVDmaNext (pNv, line_len);
+ NVDmaNext (pNv, lc);
+ NVDmaNext (pNv, (1<<8)|1);
NVDmaNext (pNv, 0);
NVDmaKickoff(pNv);
- if (!NVNotifierWaitStatus(pScrn, pNv->Notifier0, 0, 2000)) {
- ret = FALSE;
- goto error;
+ if (!NVNotifierWaitStatus(pScrn, pNv->Notifier0, 0, 0))
+ return FALSE;
+
+ if (dst_pitch == line_len) {
+ memcpy(dst, src, dst_pitch * lc);
+ dst += dst_pitch * lc;
+ } else {
+ for (i = 0; i < lc; i++) {
+ memcpy(dst, src, line_len);
+ src += line_len;
+ dst += dst_pitch;
+ }
}
- memcpy(dst, pNv->AGPScratch->map, nlines*dst_pitch);
- h -= nlines;
- offset_in += nlines*pitch_in;
- dst += nlines*dst_pitch;
+ line_count -= lc;
}
-error:
- return ret;
+ return TRUE;
+}
+
+static Bool NVDownloadFromScreen(PixmapPtr pSrc,
+ int x, int y,
+ int w, int h,
+ char *dst, int dst_pitch)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum];
+ NVPtr pNv = NVPTR(pScrn);
+ int src_pitch, cpp, offset;
+ const char *src;
+
+ src_pitch = exaGetPixmapPitch(pSrc);
+ cpp = pSrc->drawable.bitsPerPixel >> 3;
+ offset = (y * src_pitch) + (x * cpp);
+
+ if (pNv->AGPScratch) {
+ if (NVAccelDownloadM2MF(pScrn, dst,
+ NVAccelGetPixmapOffset(pSrc) + offset,
+ dst_pitch, src_pitch, w * cpp, h))
+ return TRUE;
+ }
+
+ src = pSrc->devPrivate.ptr + offset;
+ exaWaitSync(pSrc->drawable.pScreen);
+ if (NVAccelMemcpyRect(dst, src, h, dst_pitch, src_pitch, w*cpp))
+ return TRUE;
+
+ return FALSE;
}
Bool
@@ -343,6 +390,7 @@ NVAccelUploadM2MF(ScrnInfoPtr pScrn, uint64_t dst_offset, const char *src,
/* Upload to GART */
if (src_pitch == line_len) {
memcpy(dst, src, src_pitch * lc);
+ src += src_pitch * lc;
} else {
for (i = 0; i < lc; i++) {
memcpy(dst, src, line_len);
@@ -383,18 +431,18 @@ static Bool NVUploadToScreen(PixmapPtr pDst,
char *src, int src_pitch)
{
ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
- int dst_offset, dst_pitch, bpp;
+ int dst_offset, dst_pitch, cpp;
Bool ret;
dst_offset = NVAccelGetPixmapOffset(pDst);
dst_pitch = exaGetPixmapPitch(pDst);
- bpp = pDst->drawable.bitsPerPixel >> 3;
+ cpp = pDst->drawable.bitsPerPixel >> 3;
if (1) {
- dst_offset += (y * dst_pitch) + (x * bpp);
+ dst_offset += (y * dst_pitch) + (x * cpp);
ret = NVAccelUploadM2MF(pScrn, dst_offset, src,
dst_pitch, src_pitch,
- w * bpp, h);
+ w * cpp, h);
}
return ret;
}
@@ -550,8 +598,8 @@ Bool NVExaInit(ScreenPtr pScreen)
pNv->EXADriverPtr->WaitMarker = NVExaWaitMarker;
/* Install default hooks */
+ pNv->EXADriverPtr->DownloadFromScreen = NVDownloadFromScreen;
if (pNv->AGPScratch) {
- pNv->EXADriverPtr->DownloadFromScreen = NVDownloadFromScreen;
pNv->EXADriverPtr->UploadToScreen = NVUploadToScreen;
}