diff --git a/src/nouveau_exa.c b/src/nouveau_exa.c
index 93fc3c5..2e5738b 100644
--- a/src/nouveau_exa.c
+++ b/src/nouveau_exa.c
@@ -351,17 +351,16 @@ nouveau_exa_modify_pixmap_header(PixmapPtr ppix, int width, int height,
 
 	if (!nvpix->bo && nvpix->size) {
 		uint32_t cpp = ppix->drawable.bitsPerPixel >> 3;
-		/* At some point we should just keep 1bpp pixmaps in sysram */
 		uint32_t flags = NOUVEAU_BO_VRAM;
 		int ret;
 
 		if (pNv->Architecture >= NV_ARCH_50 && cpp) {
-			uint32_t aw = (width + 7) & ~7;
-			uint32_t ah = (height + 7) & ~7;
+			uint32_t ah = (height + 3) & ~3;
 
 			flags |= NOUVEAU_BO_TILED;
 
-			devkind = ((aw * cpp) + 63) & ~63;
+			/* This alligment is very important. */
+			devkind = (width * cpp + 63) & ~63;
 			nvpix->size = devkind * ah;
 		}
 
@@ -390,8 +389,11 @@ nouveau_exa_pixmap_is_tiled(PixmapPtr ppix)
 	NVPtr pNv = NVPTR(pScrn);
 
 	if (pNv->exa_driver_pixmaps) {
-		if (!nouveau_pixmap_bo(ppix)->tiled)
+		if (!nouveau_pixmap_bo(ppix))
 			return false;
+		if (nouveau_pixmap_bo(ppix)->tiled == 0)
+			return false;
+		return true;
 	} else
 	if (pNv->Architecture < NV_ARCH_50 ||
 	    exaGetPixmapOffset(ppix) < pNv->EXADriverPtr->offScreenBase)
@@ -406,7 +408,7 @@ nouveau_exa_pixmap_map(PixmapPtr ppix)
 	struct nouveau_bo *bo = nouveau_pixmap_bo(ppix);
 	unsigned delta = nouveau_pixmap_offset(ppix);
 
-	if (bo->tiled) {
+	if (0 && bo->tiled) {
 		struct nouveau_pixmap *nvpix = nouveau_pixmap(ppix);
 
 		nvpix->linear = xcalloc(1, ppix->devKind * ppix->drawable.height);
@@ -428,7 +430,7 @@ nouveau_exa_pixmap_unmap(PixmapPtr ppix)
 {
 	struct nouveau_bo *bo = nouveau_pixmap_bo(ppix);
 
-	if (bo->tiled) {
+	if (0 && bo->tiled) {
 		struct nouveau_pixmap *nvpix = nouveau_pixmap(ppix);
 
 		NVAccelUploadM2MF(ppix, 0, 0, ppix->drawable.width,
@@ -674,3 +676,196 @@ nouveau_exa_init(ScreenPtr pScreen)
 	pNv->EXADriverPtr = exa;
 	return TRUE;
 }
+
+/* WFB functions. */
+
+static FbBits
+nouveau_exa_wfb_read_memory_linear(const void *src, int size)
+{
+	FbBits bits = 0;
+
+	memcpy(&bits, src, size);
+
+	return bits;
+}
+
+static void
+nouveau_exa_wfb_write_memory_linear(void *dst, FbBits value, int size)
+{
+	memcpy(dst, &value, size);
+}
+
+#define TILE_PITCH 32
+#define TILE_HEIGHT 4
+#define SUBTILE_PITCH 8
+#define SUBTILE_HEIGHT 2
+
+#define TILE_WIDTH (TILE_PITCH/cpp)
+#define SUBTILE_WIDTH (SUBTILE_PITCH/cpp)
+
+#define LINEAR_PITCH (pPixmap->devKind)
+#define NUM_TILES_WIDTH (LINEAR_PITCH/TILE_PITCH)
+
+static ScrnInfoPtr last_wfb_scrn = NULL;
+
+/* Note, we can only expose one read and write function, the linear versions are for internal consumption. */
+static FbBits
+nouveau_exa_wfb_read_memory(const void *src, int size)
+{
+	int i, cpp, line_x, line_y;
+	unsigned long offset = (unsigned long) src, subpixel_offset;
+	NVPtr pNv;
+	PixmapPtr pPixmap = NULL;
+	FbBits bits = 0;
+	void *new_src;
+
+	if (!last_wfb_scrn)
+		return nouveau_exa_wfb_read_memory_linear(src, size);
+
+	pNv = NVPTR(last_wfb_scrn);
+
+	/* Find the right pixmap. */
+	for (i = 0; i < 10; i++)
+		if (offset >= pNv->wfb_pixmaps[i].start && offset < pNv->wfb_pixmaps[i].end) {
+			pPixmap = pNv->wfb_pixmaps[i].ppix;
+			break;
+		}
+
+	if (!pPixmap || !pNv->wfb_pixmaps[i].tiled)
+		return nouveau_exa_wfb_read_memory_linear(src, size);
+
+	/* Now comes the decoding. */
+	offset -= (unsigned long) pPixmap->devPrivate.ptr;
+	cpp = pPixmap->drawable.bitsPerPixel >> 3;
+	subpixel_offset = offset % cpp;
+	offset -= subpixel_offset;
+
+	/* Determine the coordinate first. */
+	line_x = (offset % LINEAR_PITCH)/cpp;
+	line_y = offset/LINEAR_PITCH;
+
+	new_src = pPixmap->devPrivate.ptr +
+		((((line_y/TILE_HEIGHT) * NUM_TILES_WIDTH) + (line_x/TILE_WIDTH)) * (TILE_HEIGHT * TILE_PITCH)) +
+		((((((line_y % TILE_HEIGHT)/SUBTILE_HEIGHT) * (TILE_WIDTH/SUBTILE_WIDTH)) + ((line_x % TILE_WIDTH)/SUBTILE_WIDTH)) * (SUBTILE_HEIGHT * SUBTILE_PITCH))) +
+		((line_y % SUBTILE_HEIGHT) * SUBTILE_PITCH + (line_x % SUBTILE_WIDTH) * cpp) +
+		subpixel_offset;
+
+	memcpy(&bits, new_src, size);
+
+	return bits;
+}
+
+static void
+nouveau_exa_wfb_write_memory(void *dst, FbBits value, int size)
+{
+	int i, cpp, line_x, line_y;
+	unsigned long offset = (unsigned long) dst, subpixel_offset;
+	NVPtr pNv;
+	PixmapPtr pPixmap = NULL;
+	void *new_dst;
+
+	if (!last_wfb_scrn) {
+		nouveau_exa_wfb_write_memory_linear(dst, value, size);
+		return;
+	}
+
+	pNv = NVPTR(last_wfb_scrn);
+
+	/* Find the right pixmap. */
+	for (i = 0; i < 10; i++)
+		if (offset >= pNv->wfb_pixmaps[i].start && offset < pNv->wfb_pixmaps[i].end) {
+			pPixmap = pNv->wfb_pixmaps[i].ppix;
+			break;
+		}
+
+	if (!pPixmap || !pNv->wfb_pixmaps[i].tiled) {
+		nouveau_exa_wfb_write_memory_linear(dst, value, size);
+		return;
+	}
+
+	/* Now comes the decoding. */
+	offset -= (unsigned long) pPixmap->devPrivate.ptr;
+	cpp = pPixmap->drawable.bitsPerPixel >> 3;
+	subpixel_offset = offset % cpp;
+	offset -= subpixel_offset;
+
+	/* Determine the coordinate first. */
+	line_x = (offset % LINEAR_PITCH)/cpp;
+	line_y = offset/LINEAR_PITCH;
+
+	new_dst = pPixmap->devPrivate.ptr +
+		((((line_y/TILE_HEIGHT) * NUM_TILES_WIDTH) + (line_x/TILE_WIDTH)) * (TILE_HEIGHT * TILE_PITCH)) +
+		((((((line_y % TILE_HEIGHT)/SUBTILE_HEIGHT) * (TILE_WIDTH/SUBTILE_WIDTH)) + ((line_x % TILE_WIDTH)/SUBTILE_WIDTH)) * (SUBTILE_HEIGHT * SUBTILE_PITCH))) +
+		((line_y % SUBTILE_HEIGHT) * SUBTILE_PITCH + (line_x % SUBTILE_WIDTH) * cpp) +
+		subpixel_offset;
+
+	memcpy(new_dst, &value, size);
+}
+
+void
+nouveau_exa_wfb_setup_wrap(ReadMemoryProcPtr *pRead,
+				WriteMemoryProcPtr *pWrite,
+				DrawablePtr pDraw)
+{
+	ScrnInfoPtr pScrn = xf86Screens[pDraw->pScreen->myNum];
+	NVPtr pNv = NVPTR(pScrn);
+	PixmapPtr pPixmap;
+
+	if (!pRead || !pWrite)
+		return;
+
+	pPixmap = NVGetDrawablePixmap(pDraw);
+	if (!pPixmap)
+		return;
+
+	int i;
+	for (i = 0; i < 10; i++)
+		if (!pNv->wfb_pixmaps[i].used)
+			break;
+
+	if (i == 10) {
+		ErrorF("More than 10 wraps are setup, what the hell is going on?\n");
+		*pRead = NULL;
+		*pWrite = NULL;
+		return;
+	}
+
+	/* We will get a pointer, somewhere in the range of this pixmap. */
+	/* Based on linear representation ofcource. */
+	pNv->wfb_pixmaps[i].ppix = pPixmap;
+	pNv->wfb_pixmaps[i].start = (unsigned long) pPixmap->devPrivate.ptr;
+	pNv->wfb_pixmaps[i].end = pNv->wfb_pixmaps[i].start + exaGetPixmapPitch(pPixmap) * ((pPixmap->drawable.height + 3) & ~3);
+	pNv->wfb_pixmaps[i].used = true;
+	if (nouveau_exa_pixmap_is_tiled(pPixmap))
+		pNv->wfb_pixmaps[i].tiled = true;
+	else
+		pNv->wfb_pixmaps[i].tiled = false;
+
+	*pRead = nouveau_exa_wfb_read_memory;
+	*pWrite = nouveau_exa_wfb_write_memory;
+
+	last_wfb_scrn = pScrn;
+}
+
+void
+nouveau_exa_wfb_finish_wrap(DrawablePtr pDraw)
+{
+	ScrnInfoPtr pScrn = xf86Screens[pDraw->pScreen->myNum];
+	NVPtr pNv = NVPTR(pScrn);
+	PixmapPtr pPixmap;
+	int i;
+
+	pPixmap = NVGetDrawablePixmap(pDraw);
+	if (!pPixmap)
+		return;
+
+	for (i = 0; i < 10; i++)
+		if (pNv->wfb_pixmaps[i].ppix == pPixmap) {
+			pNv->wfb_pixmaps[i].ppix = NULL;
+			pNv->wfb_pixmaps[i].start = 0;
+			pNv->wfb_pixmaps[i].end = 0;
+			pNv->wfb_pixmaps[i].used = false;
+			pNv->wfb_pixmaps[i].tiled = false;
+			break;
+		}
+}
diff --git a/src/nv_driver.c b/src/nv_driver.c
index d7e8025..bdea2b6 100644
--- a/src/nv_driver.c
+++ b/src/nv_driver.c
@@ -1510,7 +1510,7 @@ NVPreInit(ScrnInfoPtr pScrn, int flags)
 	 * section.
 	 */
 
-	if (xf86LoadSubModule(pScrn, "fb") == NULL)
+	if (xf86LoadSubModule(pScrn, "wfb") == NULL)
 		NVPreInitFail("\n");
 
 	xf86LoaderReqSymLists(fbSymbols, NULL);
@@ -2154,9 +2154,10 @@ NVScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
 	switch (pScrn->bitsPerPixel) {
 		case 16:
 		case 32:
-			ret = fbScreenInit(pScreen, FBStart, pScrn->virtualX, pScrn->virtualY,
+			ret = wfbScreenInit(pScreen, FBStart, pScrn->virtualX, pScrn->virtualY,
 				pScrn->xDpi, pScrn->yDpi,
-				displayWidth, pScrn->bitsPerPixel);
+				displayWidth, pScrn->bitsPerPixel,
+				nouveau_exa_wfb_setup_wrap, nouveau_exa_wfb_finish_wrap);
 			break;
 		default:
 			xf86DrvMsg(scrnIndex, X_ERROR,
@@ -2181,7 +2182,7 @@ NVScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
 		}
 	}
 
-	fbPictureInit (pScreen, 0, 0);
+	wfbPictureInit (pScreen, 0, 0);
 
 	xf86SetBlackWhitePixels(pScreen);
 
diff --git a/src/nv_include.h b/src/nv_include.h
index be004ef..f78cda0 100644
--- a/src/nv_include.h
+++ b/src/nv_include.h
@@ -47,6 +47,7 @@
 #include "dixstruct.h"
 #include "scrnintstr.h"
 
+#define FB_ACCESS_WRAPPER 1
 #include "fb.h"
 
 #include "xf86cmap.h"
diff --git a/src/nv_proto.h b/src/nv_proto.h
index 28605a8..5933ddd 100644
--- a/src/nv_proto.h
+++ b/src/nv_proto.h
@@ -65,6 +65,10 @@ void  NVTakedownDma(ScrnInfoPtr pScrn);
 Bool nouveau_exa_init(ScreenPtr pScreen);
 Bool nouveau_exa_pixmap_is_onscreen(PixmapPtr pPixmap);
 bool nouveau_exa_pixmap_is_tiled(PixmapPtr ppix);
+void nouveau_exa_wfb_setup_wrap(ReadMemoryProcPtr *pRead,
+				WriteMemoryProcPtr *pWrite,
+				DrawablePtr pDraw);
+void nouveau_exa_wfb_finish_wrap(DrawablePtr pDraw);
 
 /* in nv_hw.c */
 void NVCalcStateExt(ScrnInfoPtr,struct _riva_hw_state *,int,int,int,int,int,int);
diff --git a/src/nv_type.h b/src/nv_type.h
index 78a7802..1309d67 100644
--- a/src/nv_type.h
+++ b/src/nv_type.h
@@ -404,6 +404,15 @@ typedef struct _NVRec {
 	unsigned point_x, point_y;
 	unsigned width_in, width_out;
 	unsigned height_in, height_out;
+
+	/* Wfb related data. */
+	struct {
+		PixmapPtr ppix;
+		bool used;
+		bool tiled;
+		unsigned long start;
+		unsigned long end;
+	} wfb_pixmaps[10];
 } NVRec;
 
 #define NVPTR(p) ((NVPtr)((p)->driverPrivate))
