summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Skeggs <skeggsb@gmail.com>2007-06-24 17:34:10 +1000
committerBen Skeggs <skeggsb@gmail.com>2007-06-24 17:34:10 +1000
commit2e2e95fc3b650ca633294bf4c11c9ba28f45b743 (patch)
tree70a23d96ea900e3ecf40378838ce08d9a3d81bb1
parent35806975047aa8c0dbc059709bb823f475ee7368 (diff)
downloadxorg-driver-xf86-video-nouveau-2e2e95fc3b650ca633294bf4c11c9ba28f45b743.tar.gz
Slightly saner UploadToScreen implementation
-rw-r--r--src/nv_exa.c104
1 files changed, 62 insertions, 42 deletions
diff --git a/src/nv_exa.c b/src/nv_exa.c
index 39585e4..3096e29 100644
--- a/src/nv_exa.c
+++ b/src/nv_exa.c
@@ -318,65 +318,85 @@ error:
return ret;
}
-static Bool NVUploadToScreen(PixmapPtr pDst,
- int x, int y, int w, int h,
- char *src, int src_pitch)
+Bool
+NVAccelUploadM2MF(ScrnInfoPtr pScrn, uint64_t dst_offset, const char *src,
+ int dst_pitch, int src_pitch,
+ int line_len, int line_count)
{
- ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
NVPtr pNv = NVPTR(pScrn);
- CARD32 offset_out, pitch_out, max_lines, line_length;
- Bool ret = TRUE;
-#if 0
- x = 0;
- y = 0;
- w = pDst->drawable.width;
- h = pDst->drawable.height;
-#endif
- pitch_out = exaGetPixmapPitch(pDst);
- offset_out = NVAccelGetPixmapOffset(pDst);
- offset_out += y*pitch_out;
- offset_out += x * (pDst->drawable.bitsPerPixel >> 3);
+ setM2MFDirection(pScrn, 1);
- max_lines = 65536/src_pitch + 1;
- line_length = w * (pDst->drawable.bitsPerPixel >> 3);
+ while (line_count) {
+ char *dst = pNv->AGPScratch->map;
+ int lc, i;
- setM2MFDirection(pScrn, 1);
+ /* Determine max amount of data we can DMA at once */
+ 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? */
- NVDEBUG("NVUploadToScreen: x=%d, y=%d, w=%d, h=%d\n", x, y, w, h);
- while (h > 0) {
- NVDEBUG(" max_lines=%d, h=%d\n", max_lines, h);
- int nlines = h > max_lines ? max_lines : h;
+ /* Upload to GART */
+ if (src_pitch == line_len) {
+ memcpy(dst, src, src_pitch * lc);
+ } else {
+ for (i = 0; i < lc; i++) {
+ memcpy(dst, src, line_len);
+ src += src_pitch;
+ dst += line_len;
+ }
+ }
- /* reset the notification object */
+ /* DMA to VRAM */
NVNotifierReset(pScrn, pNv->Notifier0);
-
- memcpy(pNv->AGPScratch->map, src, nlines*src_pitch);
- 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);
+ NVDmaStart(pNv, NvSubMemFormat,
+ NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
NVDmaNext (pNv, (uint32_t)pNv->AGPScratch->offset);
- NVDmaNext (pNv, offset_out);
- NVDmaNext (pNv, src_pitch);
- NVDmaNext (pNv, pitch_out);
- NVDmaNext (pNv, line_length);
- NVDmaNext (pNv, nlines);
- NVDmaNext (pNv, 0x101);
+ NVDmaNext (pNv, (uint32_t)dst_offset);
+ NVDmaNext (pNv, line_len);
+ NVDmaNext (pNv, dst_pitch);
+ 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;
- h -= nlines;
- offset_out += nlines*pitch_out;
- src += nlines*src_pitch;
+ line_count -= lc;
}
-error:
+ return TRUE;
+}
+
+static Bool NVUploadToScreen(PixmapPtr pDst,
+ int x, int y, int w, int h,
+ char *src, int src_pitch)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
+ int dst_offset, dst_pitch, bpp;
+ Bool ret;
+
+ dst_offset = NVAccelGetPixmapOffset(pDst);
+ dst_pitch = exaGetPixmapPitch(pDst);
+ bpp = pDst->drawable.bitsPerPixel >> 3;
+
+ if (1) {
+ dst_offset += (y * dst_pitch) + (x * bpp);
+ ret = NVAccelUploadM2MF(pScrn, dst_offset, src,
+ dst_pitch, src_pitch,
+ w * bpp, h);
+ }
exaMarkSync(pDst->drawable.pScreen);
return ret;
}