[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

xserver-xorg-video-nouveau: Changes to 'upstream-experimental'



 src/Makefile.am          |   12 
 src/drmmode_display.c    |  129 ++
 src/drmmode_display.h    |    4 
 src/nouveau_xv.c         | 2190 +++++++++++++++++++++++++++++++++++++++++++++++
 src/nv04_video_blitter.c |  268 -----
 src/nv04_video_overlay.c |  201 ----
 src/nv04_xv_blit.c       |  241 +++++
 src/nv04_xv_ovl.c        |  201 ++++
 src/nv10_video_overlay.c |  302 ------
 src/nv10_xv_ovl.c        |  301 ++++++
 src/nv30_video_texture.c |  457 ---------
 src/nv30_xv_tex.c        |  431 +++++++++
 src/nv40_video_texture.c |  441 ---------
 src/nv40_xv_tex.c        |  415 ++++++++
 src/nv50_randr.c         |   95 +-
 src/nv50_randr.h         |    1 
 src/nv_driver.c          |   63 +
 src/nv_exa.c             |   28 
 src/nv_proto.h           |   41 
 src/nv_type.h            |    3 
 src/nv_video.c           | 2173 ----------------------------------------------
 21 files changed, 4102 insertions(+), 3895 deletions(-)

New commits:
commit b1f316977e2c79fdf5c83092e953bdfc988299e1
Author: Ben Skeggs <skeggsb@gmail.com>
Date:   Mon Jul 7 01:03:02 2008 +1000

    xv: remove some disturbing abuses of buffer related things
    
    Also brings to attention a point about the overlay when we use a real
    memory manager.  We'll need to find a way for the overlay to signal it's
    finished with a buffer, or just resort to pinning pPriv->video_mem..

diff --git a/src/nouveau_xv.c b/src/nouveau_xv.c
index 486da87..973cde2 100644
--- a/src/nouveau_xv.c
+++ b/src/nouveau_xv.c
@@ -1007,7 +1007,6 @@ NV_set_action_flags(ScrnInfoPtr pScrn, DrawablePtr pDraw, NVPortPrivPtr pPriv,
  * @param data pointer to port
  * @param pDraw drawable pointer
  */
-/*FIXME: need to honor the Sync*/
 static int
 NVPutImage(ScrnInfoPtr pScrn, short src_x, short src_y, short drw_x,
 	   short drw_y, short src_w, short src_h, short drw_w, short drw_h,
@@ -1079,9 +1078,9 @@ NVPutImage(ScrnInfoPtr pScrn, short src_x, short src_y, short drw_x,
 				    &pPriv->video_mem);
 	if (ret)
 		return BadAlloc;
-	offset = pPriv->video_mem->offset;
 
 	/* The overlay supports hardware double buffering. We handle this here*/
+	offset = 0;
 	if (pPriv->doubleBuffer) {
 		int mask = 1 << (pPriv->currentBuffer << 2);
 
@@ -1231,9 +1230,10 @@ NVPutImage(ScrnInfoPtr pScrn, short src_x, short src_y, short drw_x,
 
 			BEGIN_RING(NvMemFormat,
 				   NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
-			OUT_RING  ((uint32_t)destination_buffer->offset +
-					     line_len * nlines);
-			OUT_RING  ((uint32_t)offset + dstPitch * nlines);
+			OUT_RELOCl(destination_buffer, line_len * nlines,
+				   NOUVEAU_BO_GART | NOUVEAU_BO_RD);
+			OUT_RELOCl(pPriv->video_mem, offset + dstPitch * nlines,
+				   NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
 			OUT_RING  (line_len);
 			OUT_RING  (dstPitch);
 			OUT_RING  (line_len);
@@ -1245,8 +1245,10 @@ NVPutImage(ScrnInfoPtr pScrn, short src_x, short src_y, short drw_x,
 
 		BEGIN_RING(NvMemFormat,
 			   NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
-		OUT_RING  ((uint32_t)destination_buffer->offset);
-		OUT_RING  ((uint32_t)offset);
+		OUT_RELOCl(destination_buffer, 0,
+			   NOUVEAU_BO_GART | NOUVEAU_BO_RD);
+		OUT_RELOCl(pPriv->video_mem, offset,
+			   NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
 		OUT_RING  (line_len);
 		OUT_RING  (dstPitch);
 		OUT_RING  (line_len);
@@ -1287,8 +1289,7 @@ NVPutImage(ScrnInfoPtr pScrn, short src_x, short src_y, short drw_x,
 
 	} else {
 CPU_copy:
-		map = pPriv->video_mem->map +
-		      (offset - pPriv->video_mem->offset);
+		map = pPriv->video_mem->map + offset;
 
 		if (action_flags & IS_YV12) {
 			if (action_flags & CONVERT_TO_YUY2) {
@@ -1389,9 +1390,9 @@ CPU_copy:
 
 	if (action_flags & USE_OVERLAY) {
 		if (pNv->Architecture == NV_ARCH_04) {
-			NV04PutOverlayImage(pScrn, offset, id, dstPitch,
-					    &dstBox, 0, 0, xb, yb,
-					    npixels, nlines,
+			NV04PutOverlayImage(pScrn, pPriv->video_mem, offset,
+					    id, dstPitch, &dstBox, 0, 0,
+					    xb, yb, npixels, nlines,
 					    src_w, src_h, drw_w, drw_h,
 					    clipBoxes);
 		} else {
@@ -1400,8 +1401,9 @@ CPU_copy:
 			if (action_flags & (IS_YUY2 | CONVERT_TO_YUY2))
 				uvoffset = offset + nlines * dstPitch;
 
-			NV10PutOverlayImage(pScrn, offset, uvoffset, id,
-					    dstPitch, &dstBox, 0, 0, xb, yb,
+			NV10PutOverlayImage(pScrn, pPriv->video_mem, offset,
+					    uvoffset, id, dstPitch, &dstBox,
+					    0, 0, xb, yb,
 					    npixels, nlines, src_w, src_h,
 					    drw_w, drw_h, clipBoxes);
 		}
@@ -1412,7 +1414,8 @@ CPU_copy:
 		int ret = BadImplementation;
 
 		if (pNv->Architecture == NV_ARCH_30) {
-			ret = NV30PutTextureImage(pScrn, offset,
+			ret = NV30PutTextureImage(pScrn, pPriv->video_mem,
+						  offset,
 						  offset + nlines * dstPitch,
 						  id, dstPitch, &dstBox, 0, 0,
 						  xb, yb, npixels, nlines,
@@ -1420,7 +1423,8 @@ CPU_copy:
 						  clipBoxes, ppix, pPriv);
 		} else
 		if (pNv->Architecture == NV_ARCH_40) {
-			ret = NV40PutTextureImage(pScrn, offset,
+			ret = NV40PutTextureImage(pScrn, pPriv->video_mem, 
+						  offset,
 						  offset + nlines * dstPitch,
 						  id, dstPitch, &dstBox, 0, 0,
 						  xb, yb, npixels, nlines,
@@ -1431,8 +1435,8 @@ CPU_copy:
 		if (ret != Success)
 			return ret;
 	} else {
-		NVPutBlitImage(pScrn, offset, id, dstPitch, &dstBox,
-			       0, 0, xb, yb, npixels, nlines,
+		NVPutBlitImage(pScrn, pPriv->video_mem, offset, id, dstPitch,
+			       &dstBox, 0, 0, xb, yb, npixels, nlines,
 			       src_w, src_h, drw_w, drw_h, clipBoxes, ppix);
 	}
 
@@ -1545,7 +1549,6 @@ NVAllocSurface(ScrnInfoPtr pScrn, int id,
 				    &pPriv->video_mem);
 	if (ret)
 		return BadAlloc;
-
 	pPriv->offset = 0;
 
 	surface->width = w;
@@ -1655,10 +1658,10 @@ NVDisplaySurface(XF86SurfacePtr surface,
 
 	pPriv->currentBuffer = 0;
 
-	NV10PutOverlayImage(pScrn, surface->offsets[0], 0, surface->id,
-			  surface->pitches[0], &dstBox, xa, ya, xb, yb,
-			  surface->width, surface->height, src_w, src_h,
-			  drw_w, drw_h, clipBoxes);
+	NV10PutOverlayImage(pScrn, pPriv->video_mem, surface->offsets[0],
+			    0, surface->id, surface->pitches[0], &dstBox,
+			    xa, ya, xb, yb, surface->width, surface->height,
+			    src_w, src_h, drw_w, drw_h, clipBoxes);
 
 	return Success;
 }
diff --git a/src/nv04_xv_blit.c b/src/nv04_xv_blit.c
index 84476eb..73c98ce 100644
--- a/src/nv04_xv_blit.c
+++ b/src/nv04_xv_blit.c
@@ -60,8 +60,8 @@ extern Atom xvSetDefaults, xvSyncToVBlank;
  * @param pDraw
  */
 void
-NVPutBlitImage(ScrnInfoPtr pScrn, int src_offset, int id,
-               int src_pitch, BoxPtr dstBox,
+NVPutBlitImage(ScrnInfoPtr pScrn, struct nouveau_bo *src, int src_offset,
+	       int id, int src_pitch, BoxPtr dstBox,
                int x1, int y1, int x2, int y2,
                short width, short height,
                short src_w, short src_h,
@@ -155,7 +155,7 @@ NVPutBlitImage(ScrnInfoPtr pScrn, int src_offset, int id,
                                 NV04_SCALED_IMAGE_FROM_MEMORY_SIZE, 4);
                 OUT_RING  ((height << 16) | width);
                 OUT_RING  (src_pitch);
-                OUT_RING  (src_offset);
+		OUT_RELOCl(src, src_offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
                 OUT_RING  (src_point);
                 pbox++;
         }
diff --git a/src/nv04_xv_ovl.c b/src/nv04_xv_ovl.c
index ff36be4..04bf28a 100644
--- a/src/nv04_xv_ovl.c
+++ b/src/nv04_xv_ovl.c
@@ -37,13 +37,11 @@
 extern Atom xvBrightness, xvColorKey, xvAutopaintColorKey, xvSetDefaults;
 
 void
-NV04PutOverlayImage(ScrnInfoPtr pScrn, int offset, int id,
-                  int dstPitch, BoxPtr dstBox,
-                  int x1, int y1, int x2, int y2,
-                  short width, short height,
-                  short src_w, short src_h,
-                  short drw_w, short drw_h,
-                  RegionPtr clipBoxes)
+NV04PutOverlayImage(ScrnInfoPtr pScrn, struct nouveau_bo *src, int offset,
+		    int id, int dstPitch, BoxPtr dstBox, int x1, int y1,
+		    int x2, int y2, short width, short height,
+		    short src_w, short src_h, short drw_w, short drw_h,
+		    RegionPtr clipBoxes)
 {                       
 	NVPtr         pNv    = NVPTR(pScrn);
 	NVPortPrivPtr pPriv  = GET_OVERLAY_PRIVATE(pNv);
@@ -80,8 +78,10 @@ NV04PutOverlayImage(ScrnInfoPtr pScrn, int offset, int id,
         nvWriteVIDEO(pNv, NV_PVIDEO_SU_STATE, 0);
         nvWriteVIDEO(pNv, NV_PVIDEO_RM_STATE, 0);
 
-        nvWriteVIDEO(pNv, NV_PVIDEO_BUFF0_START_ADDRESS, offset);
-        nvWriteVIDEO(pNv, NV_PVIDEO_BUFF0_START_ADDRESS + 4, offset);
+        nvWriteVIDEO(pNv, NV_PVIDEO_BUFF0_START_ADDRESS,
+			  src->offset + offset);
+        nvWriteVIDEO(pNv, NV_PVIDEO_BUFF0_START_ADDRESS + 4,
+			  src->offset + offset);
         nvWriteVIDEO(pNv, NV_PVIDEO_BUFF0_PITCH_LENGTH, dstPitch);
         nvWriteVIDEO(pNv, NV_PVIDEO_BUFF0_PITCH_LENGTH + 4, dstPitch);
         nvWriteVIDEO(pNv, NV_PVIDEO_BUFF0_OFFSET, 0);
diff --git a/src/nv10_xv_ovl.c b/src/nv10_xv_ovl.c
index deb09a9..2384c38 100644
--- a/src/nv10_xv_ovl.c
+++ b/src/nv10_xv_ovl.c
@@ -34,9 +34,9 @@
 #include "nv_include.h"
 #include "nv_dma.h"
 
-extern Atom xvBrightness, xvContrast, xvColorKey, xvSaturation,       
-          xvHue, xvAutopaintColorKey, xvSetDefaults, xvDoubleBuffer,
-	       xvITURBT709, xvSyncToVBlank, xvOnCRTCNb;
+extern Atom xvBrightness, xvContrast, xvColorKey, xvSaturation;
+extern Atom xvHue, xvAutopaintColorKey, xvSetDefaults, xvDoubleBuffer;
+extern Atom xvITURBT709, xvSyncToVBlank, xvOnCRTCNb;
 
 /**
  * NV10PutOverlayImage
@@ -60,13 +60,11 @@ extern Atom xvBrightness, xvContrast, xvColorKey, xvSaturation,
  * @param clipBoxes ???
  */
 void
-NV10PutOverlayImage(ScrnInfoPtr pScrn, int offset, int uvoffset, int id,
-                  int dstPitch, BoxPtr dstBox,
-                  int x1, int y1, int x2, int y2,
-                  short width, short height,
-                  short src_w, short src_h,
-                  short drw_w, short drw_h,
-                  RegionPtr clipBoxes)
+NV10PutOverlayImage(ScrnInfoPtr pScrn,
+		    struct nouveau_bo *src, int offset, int uvoffset, int id,
+		    int dstPitch, BoxPtr dstBox, int x1, int y1, int x2, int y2,
+		    short width, short height, short src_w, short src_h,
+		    short drw_w, short drw_h, RegionPtr clipBoxes)
 {
 	NVPtr         pNv    = NVPTR(pScrn);
 	NVPortPrivPtr pPriv  = GET_OVERLAY_PRIVATE(pNv);
@@ -103,7 +101,8 @@ NV10PutOverlayImage(ScrnInfoPtr pScrn, int offset, int uvoffset, int id,
 	//16,y1>>16, (src_w << 20) / drw_w, (src_h << 20) / drw_h,  (dstBox->x1),(dstBox->y1), (dstBox->y2 - dstBox->y1), (dstBox->x2 - dstBox->x1));
 
         nvWriteVIDEO(pNv, NV_PVIDEO_BASE(buffer)     , 0);
-        nvWriteVIDEO(pNv, NV_PVIDEO_OFFSET_BUFF(buffer)     , offset);
+        nvWriteVIDEO(pNv, NV_PVIDEO_OFFSET_BUFF(buffer),
+			  src->offset + offset);
         nvWriteVIDEO(pNv, NV_PVIDEO_SIZE_IN(buffer)  , (height << 16) | width);
         nvWriteVIDEO(pNv, NV_PVIDEO_POINT_IN(buffer) ,
                           ((y1 << 4) & 0xffff0000) | (x1 >> 12));
@@ -125,11 +124,11 @@ NV10PutOverlayImage(ScrnInfoPtr pScrn, int offset, int uvoffset, int id,
                 dstPitch |= NV_PVIDEO_FORMAT_PLANAR;
 
         /* Those are important only for planar formats (NV12) */
-        if ( uvoffset )
-                {
+        if (uvoffset) {
                 nvWriteVIDEO(pNv, NV_PVIDEO_UVPLANE_BASE(buffer), 0);
-                nvWriteVIDEO(pNv, NV_PVIDEO_UVPLANE_OFFSET_BUFF(buffer), uvoffset);
-                }
+                nvWriteVIDEO(pNv, NV_PVIDEO_UVPLANE_OFFSET_BUFF(buffer),
+				  src->offset + uvoffset);
+	}
 
         nvWriteVIDEO(pNv, NV_PVIDEO_FORMAT(buffer), dstPitch);
         nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 0);
diff --git a/src/nv30_xv_tex.c b/src/nv30_xv_tex.c
index f8176e1..5d71471 100644
--- a/src/nv30_xv_tex.c
+++ b/src/nv30_xv_tex.c
@@ -86,28 +86,29 @@ static void compute_filter_table(int8_t *t) {
 	}
 }
 
-static uint64_t NV30_LoadFilterTable(ScrnInfoPtr pScrn)
+static struct nouveau_bo *table_mem = NULL;
+static void
+NV30_LoadFilterTable(ScrnInfoPtr pScrn)
 {
 	NVPtr pNv = NVPTR(pScrn);
-	static struct nouveau_bo *table_mem = NULL;
 
 	if (!table_mem) {
 		if (nouveau_bo_new(pNv->dev, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART,
 				0, TABLE_SIZE*sizeof(float)*4, &table_mem)) {
 			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 				"Couldn't alloc filter table!\n");
-			return 0;
+			return;
 		}
 
 		if (nouveau_bo_map(table_mem, NOUVEAU_BO_RDWR)) {
 			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 				   "Couldn't map filter table!\n");
+			return;
 		}
 
 		int8_t *t=table_mem->map;
 		compute_filter_table(t);
 	}
-	return table_mem->offset;
 }
 
 #define SWIZZLE(ts0x,ts0y,ts0z,ts0w,ts1x,ts1y,ts1z,ts1w)			\
@@ -124,7 +125,8 @@ static uint64_t NV30_LoadFilterTable(ScrnInfoPtr pScrn)
  * Texture 2 : UV data
  */
 static Bool
-NV30VideoTexture(ScrnInfoPtr pScrn, int offset, uint16_t width, uint16_t height, uint16_t src_pitch, int unit)
+NV30VideoTexture(ScrnInfoPtr pScrn, struct nouveau_bo *src, int offset,
+		 uint16_t width, uint16_t height, uint16_t src_pitch, int unit)
 {
 	NVPtr pNv = NVPTR(pScrn);
 
@@ -151,8 +153,7 @@ NV30VideoTexture(ScrnInfoPtr pScrn, int offset, uint16_t width, uint16_t height,
 	}
 
 	BEGIN_RING(Nv3D, NV34TCL_TX_OFFSET(unit), 8);
-	/* We get an absolute offset, which needs to be corrected. */
-	OUT_RELOCl(pNv->FB, (uint32_t)(offset - pNv->FB->offset), NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
+	OUT_RELOCl(src, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
 	if (unit==0) {
 		OUT_RELOCd(pNv->FB, NV34TCL_TX_FORMAT_DIMS_1D |
 				(card_fmt) | 
@@ -236,16 +237,16 @@ NV30StopTexturedVideo(ScrnInfoPtr pScrn, pointer data, Bool Exit)
  	OUT_RING  (((dy)<<16)|(dx));                                           \
 } while(0)
 
-int NV30PutTextureImage(ScrnInfoPtr pScrn, int src_offset,
-		int src_offset2, int id,
-		int src_pitch, BoxPtr dstBox,
-		int x1, int y1, int x2, int y2,
-		uint16_t width, uint16_t height,
-		uint16_t src_w, uint16_t src_h,
-		uint16_t drw_w, uint16_t drw_h,
-		RegionPtr clipBoxes,
-		PixmapPtr ppix,
-		NVPortPrivPtr pPriv)
+int
+NV30PutTextureImage(ScrnInfoPtr pScrn, struct nouveau_bo *src, int src_offset,
+		    int src_offset2, int id, int src_pitch, BoxPtr dstBox,
+		    int x1, int y1, int x2, int y2,
+		    uint16_t width, uint16_t height,
+		    uint16_t src_w, uint16_t src_h,
+		    uint16_t drw_w, uint16_t drw_h,
+		    RegionPtr clipBoxes,
+		    PixmapPtr ppix,
+		    NVPortPrivPtr pPriv)
 {
 	NVPtr pNv = NVPTR(pScrn);
 	Bool redirected = FALSE;
@@ -253,7 +254,6 @@ int NV30PutTextureImage(ScrnInfoPtr pScrn, int src_offset,
 	BoxPtr pbox;
 	int nbox;
 	int dst_format = 0;
-	uint64_t filter_table_offset=0;
 
 	if (drw_w > 4096 || drw_h > 4096) {
 		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
@@ -301,16 +301,16 @@ int NV30PutTextureImage(ScrnInfoPtr pScrn, int src_offset,
 		OUT_RING((y<<16)|x);
 	}
 
-	filter_table_offset=NV30_LoadFilterTable(pScrn);
+	NV30_LoadFilterTable(pScrn);
 
 	BEGIN_RING(Nv3D, NV34TCL_TX_UNITS_ENABLE, 1);
 	OUT_RING  (NV34TCL_TX_UNITS_ENABLE_TX0 |
 			NV34TCL_TX_UNITS_ENABLE_TX1);
 
-	NV30VideoTexture(pScrn, filter_table_offset, TABLE_SIZE, 1, 0 , 0);
-	NV30VideoTexture(pScrn, src_offset, src_w, src_h, src_pitch, 1);
+	NV30VideoTexture(pScrn, table_mem, 0, TABLE_SIZE, 1, 0 , 0);
+	NV30VideoTexture(pScrn, src, src_offset, src_w, src_h, src_pitch, 1);
 	/* We've got NV12 format, which means half width and half height texture of chroma channels. */
-	NV30VideoTexture(pScrn, src_offset2, src_w/2, src_h/2, src_pitch, 2);
+	NV30VideoTexture(pScrn, src, src_offset2, src_w/2, src_h/2, src_pitch, 2);
 
 	BEGIN_RING(Nv3D, NV34TCL_TX_ENABLE(3), 1);
 	OUT_RING  (0x0);
diff --git a/src/nv40_xv_tex.c b/src/nv40_xv_tex.c
index 98635c2..7fe1af2 100644
--- a/src/nv40_xv_tex.c
+++ b/src/nv40_xv_tex.c
@@ -88,28 +88,29 @@ static void compute_filter_table(int8_t *t) {
 	}
 }
 
-static uint64_t NV40_LoadFilterTable(ScrnInfoPtr pScrn)
+static struct nouveau_bo *table_mem = NULL;
+static void
+NV40_LoadFilterTable(ScrnInfoPtr pScrn)
 {
 	NVPtr pNv = NVPTR(pScrn);
-	static struct nouveau_bo *table_mem = NULL;
 
 	if (!table_mem) {
 		if (nouveau_bo_new(pNv->dev, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART,
 				0, TABLE_SIZE*sizeof(float)*4, &table_mem)) {
 			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 				"Couldn't alloc filter table!\n");
-			return 0;
+			return;
 		}
 
 		if (nouveau_bo_map(table_mem, NOUVEAU_BO_RDWR)) {
 			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 				   "Couldn't map filter table!\n");
+			return;
 		}
 
 		int8_t *t=table_mem->map;
 		compute_filter_table(t);
 	}
-	return table_mem->offset;
 }
 
 #define SWIZZLE(ts0x,ts0y,ts0z,ts0w,ts1x,ts1y,ts1z,ts1w)				\
@@ -126,7 +127,8 @@ static uint64_t NV40_LoadFilterTable(ScrnInfoPtr pScrn)
  * Texture 2 : UV data
  */
 static Bool
-NV40VideoTexture(ScrnInfoPtr pScrn, int offset, uint16_t width, uint16_t height, uint16_t src_pitch, int unit)
+NV40VideoTexture(ScrnInfoPtr pScrn, struct nouveau_bo *src, int offset,
+		 uint16_t width, uint16_t height, uint16_t src_pitch, int unit)
 {
 	NVPtr pNv = NVPTR(pScrn);
 
@@ -134,15 +136,15 @@ NV40VideoTexture(ScrnInfoPtr pScrn, int offset, uint16_t width, uint16_t height,
 	uint32_t card_swz = 0;
 
 	switch(unit) {
-		case 0:
+	case 0:
 		card_fmt = NV40TCL_TEX_FORMAT_FORMAT_A8R8G8B8;
 		card_swz = SWIZZLE(S1, S1, S1, S1, X, Y, Z, W);
 		break;
-		case 1:
+	case 1:
 		card_fmt = NV40TCL_TEX_FORMAT_FORMAT_L8;
 		card_swz = SWIZZLE(S1, S1, S1, S1, X, X, X, X);
 		break;
-		case 2:
+	case 2:
 		card_fmt = NV40TCL_TEX_FORMAT_FORMAT_A8L8;
 #if X_BYTE_ORDER == X_BIG_ENDIAN
 		card_swz = SWIZZLE(S1, S1, S1, S1, Z, W, X, Y); /* x = V, y = U */
@@ -153,8 +155,7 @@ NV40VideoTexture(ScrnInfoPtr pScrn, int offset, uint16_t width, uint16_t height,
 	}
 
 	BEGIN_RING(Nv3D, NV40TCL_TEX_OFFSET(unit), 8);
-	/* We get an absolute offset, which needs to be corrected. */
-	OUT_RELOCl(pNv->FB, (uint32_t)(offset - pNv->FB->offset), NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
+	OUT_RELOCl(src, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
 	if (unit==0) {
 		OUT_RELOCd(pNv->FB, card_fmt | 
 				NV40TCL_TEX_FORMAT_DIMS_1D | NV40TCL_TEX_FORMAT_NO_BORDER |
@@ -235,7 +236,8 @@ NV40StopTexturedVideo(ScrnInfoPtr pScrn, pointer data, Bool Exit)
 } while(0)
 
 int
-NV40PutTextureImage(ScrnInfoPtr pScrn, int src_offset, int src_offset2,
+NV40PutTextureImage(ScrnInfoPtr pScrn,
+		    struct nouveau_bo *src, int src_offset, int src_offset2,
 		    int id, int src_pitch, BoxPtr dstBox,
 		    int x1, int y1, int x2, int y2,
 		    uint16_t width, uint16_t height,
@@ -250,7 +252,6 @@ NV40PutTextureImage(ScrnInfoPtr pScrn, int src_offset, int src_offset2,
 	BoxPtr pbox;
 	int nbox;
 	int dst_format = 0;
-	uint64_t filter_table_offset=0;
 
 	if (drw_w > 4096 || drw_h > 4096) {
 		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
@@ -282,12 +283,12 @@ NV40PutTextureImage(ScrnInfoPtr pScrn, int src_offset, int src_offset2,
 	OUT_RING  (exaGetPixmapPitch(ppix));
 	OUT_PIXMAPl(ppix, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
 
-	filter_table_offset=NV40_LoadFilterTable(pScrn);
+	NV40_LoadFilterTable(pScrn);
 
-	NV40VideoTexture(pScrn, filter_table_offset, TABLE_SIZE, 1, 0 , 0);
-	NV40VideoTexture(pScrn, src_offset, src_w, src_h, src_pitch, 1);
+	NV40VideoTexture(pScrn, table_mem, 0, TABLE_SIZE, 1, 0 , 0);
+	NV40VideoTexture(pScrn, src, src_offset, src_w, src_h, src_pitch, 1);
 	/* We've got NV12 format, which means half width and half height texture of chroma channels. */
-	NV40VideoTexture(pScrn, src_offset2, src_w/2, src_h/2, src_pitch, 2);
+	NV40VideoTexture(pScrn, src, src_offset2, src_w/2, src_h/2, src_pitch, 2);
 
 	NV40_LoadVtxProg(pScrn, &nv40_vp_video);
 	if (pPriv->bicubic)
diff --git a/src/nv_proto.h b/src/nv_proto.h
index 2cac7d9..1bb8265 100644
--- a/src/nv_proto.h
+++ b/src/nv_proto.h
@@ -145,19 +145,17 @@ void nv_save_restore_vga_fonts(ScrnInfoPtr pScrn, bool save);
 Bool NV_I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg, char *name);
 
 /* in nv04_video_overlay.c */
-void NV04PutOverlayImage(ScrnInfoPtr, int, int, int, BoxPtr,
-		int, int, int, int, short, short, short, short,
-		short, short, RegionPtr clipBoxes);
+void NV04PutOverlayImage(ScrnInfoPtr, struct nouveau_bo *, int, int, int,
+			 BoxPtr, int, int, int, int, short, short, short,
+			 short, short, short, RegionPtr clipBoxes);
 int NV04SetOverlayPortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
 int NV04GetOverlayPortAttribute(ScrnInfoPtr, Atom, INT32 *, pointer);
 void NV04StopOverlay(ScrnInfoPtr);
 
 /* in nv04_video_blitter.c */
-void NVPutBlitImage(ScrnInfoPtr, int, int, int, BoxPtr,
-		int, int, int, int,
-		short, short, short,
-		short, short, short,
-		RegionPtr, PixmapPtr);
+void NVPutBlitImage(ScrnInfoPtr, struct nouveau_bo *, int, int, int, BoxPtr,
+		    int, int, int, int, short, short, short, short, short,
+		    short, RegionPtr, PixmapPtr);
 int NVSetBlitPortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
 int NVGetBlitPortAttribute(ScrnInfoPtr, Atom, INT32 *, pointer);
 void NVStopBlitVideo(ScrnInfoPtr, pointer, Bool);
@@ -171,9 +169,9 @@ void NV10Composite(PixmapPtr, int, int, int, int, int, int, int, int);
 void NV10DoneComposite(PixmapPtr);
 
 /* in nv10_video_overlay.c */
-void NV10PutOverlayImage(ScrnInfoPtr, int, int, int, int, BoxPtr,
-		int, int, int, int, short, short, short, short, 
-		short, short, RegionPtr clipBoxes);
+void NV10PutOverlayImage(ScrnInfoPtr, struct nouveau_bo *, int, int, int, int,
+			 BoxPtr, int, int, int, int, short, short, short,
+			 short, short, short, RegionPtr clipBoxes);
 int NV10SetOverlayPortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
 int NV10GetOverlayPortAttribute(ScrnInfoPtr, Atom, INT32 *, pointer);
 void NV10StopOverlay(ScrnInfoPtr);
@@ -188,10 +186,10 @@ void NV30EXAComposite(PixmapPtr, int, int, int, int, int, int, int, int);
 void NV30EXADoneComposite(PixmapPtr);
 
 /* in nv30_video_texture.c */
-int NV30PutTextureImage(ScrnInfoPtr, int, int, int, int, BoxPtr,
-		int, int, int, int, uint16_t, uint16_t,
-		uint16_t, uint16_t, uint16_t, uint16_t,
-		RegionPtr, PixmapPtr, NVPortPrivPtr);
+int NV30PutTextureImage(ScrnInfoPtr, struct nouveau_bo *, int, int, int, int,
+			BoxPtr, int, int, int, int, uint16_t, uint16_t,
+			uint16_t, uint16_t, uint16_t, uint16_t,
+			RegionPtr, PixmapPtr, NVPortPrivPtr);
 void NV30StopTexturedVideo(ScrnInfoPtr, pointer, Bool);
 int NV30GetTexturePortAttribute(ScrnInfoPtr, Atom, INT32 *, pointer);
 int NV30SetTexturePortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
@@ -205,10 +203,10 @@ void NV40EXAComposite(PixmapPtr, int, int, int, int, int, int, int, int);
 void NV40EXADoneComposite(PixmapPtr);
 
 /* in nv40_video_texture.c */
-int NV40PutTextureImage(ScrnInfoPtr, int, int, int, int, BoxPtr,
-		int, int, int, int, uint16_t, uint16_t,
-		uint16_t, uint16_t, uint16_t, uint16_t,
-		RegionPtr, PixmapPtr, NVPortPrivPtr);
+int NV40PutTextureImage(ScrnInfoPtr, struct nouveau_bo *, int, int, int, int,
+			BoxPtr, int, int, int, int, uint16_t, uint16_t,
+			uint16_t, uint16_t, uint16_t, uint16_t,
+			RegionPtr, PixmapPtr, NVPortPrivPtr);
 void NV40StopTexturedVideo(ScrnInfoPtr, pointer, Bool);
 int NV40GetTexturePortAttribute(ScrnInfoPtr, Atom, INT32 *, pointer);
 int NV40SetTexturePortAttribute(ScrnInfoPtr, Atom, INT32, pointer);

commit 0ce028b6aaa6c20a1578148add2a96b2d37d9108
Author: Maarten Maathuis <madman2003@gmail.com>
Date:   Sun Jul 6 13:45:32 2008 +0200

    EXA: add a pixmapIsOffscreen hook.

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index b3c37ac..3807a05 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -324,6 +324,9 @@ drmmode_shadow_allocate (xf86CrtcPtr crtc, int width, int height)
 	if (ret)
 		return NULL;
 
+	/* for easy acces by exa */
+	pNv->shadow[drmmode_crtc->index] = drmmode_crtc->shadow;
+
 	return drmmode_crtc->shadow->map;
 }
 
@@ -362,6 +365,7 @@ drmmode_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
 	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 	drmmode_ptr drmmode = drmmode_crtc->drmmode;
 	ScrnInfoPtr pScrn = crtc->scrn;
+	NVPtr pNv = NVPTR(pScrn);
 	ScreenPtr pScreen = pScrn->pScreen;
 
 	ErrorF("drmmode_shadow_destroy\n");
@@ -378,6 +382,9 @@ drmmode_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
 		nouveau_bo_del(&drmmode_crtc->shadow);
 
 	drmmode_crtc->shadow = NULL;
+
+	/* for easy acces by exa */
+	pNv->shadow[drmmode_crtc->index] = NULL;
 }
 
 static void
diff --git a/src/nv50_randr.c b/src/nv50_randr.c
index e4de78a..67c11bc 100644
--- a/src/nv50_randr.c
+++ b/src/nv50_randr.c
@@ -228,6 +228,8 @@ nv50_crtc_shadow_allocate (xf86CrtcPtr crtc, int width, int height)
 		return NULL;
 	}
 
+	pNv->shadow[nv_crtc->crtc->index] = nv_crtc->shadow;
+
 	return nv_crtc->shadow->map;
 }
 
@@ -265,6 +267,7 @@ nv50_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
 {
 	ScrnInfoPtr pScrn = crtc->scrn;
 	NV50CrtcPrivatePtr nv_crtc = crtc->driver_private;
+	NVPtr pNv = NVPTR(pScrn);
 	ScreenPtr pScreen = pScrn->pScreen;
 
 	ErrorF("nv50_crtc_shadow_destroy\n");
@@ -276,6 +279,8 @@ nv50_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
 		nouveau_bo_del(&nv_crtc->shadow);
 
 	nv_crtc->shadow = NULL;
+	/* for easy acces by exa */
+	pNv->shadow[nv_crtc->crtc->index] = NULL;
 }
 
 static void
diff --git a/src/nv_exa.c b/src/nv_exa.c
index 51ac51c..43797d6 100644
--- a/src/nv_exa.c
+++ b/src/nv_exa.c
@@ -654,7 +654,7 @@ static Bool NVUploadToScreen(PixmapPtr pDst,
 	return FALSE;
 }
 
-#ifdef NOUVEAU_EXA_PIXMAPS
+#if NOUVEAU_EXA_PIXMAPS
 static Bool
 NVExaPrepareAccess(PixmapPtr pPix, int index)
 {
@@ -775,6 +775,27 @@ NVExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, int depth,
 }
 #endif
 
+#if !NOUVEAU_EXA_PIXMAPS
+static Bool
+nouveau_exa_pixmap_is_offscreen(PixmapPtr pPixmap)
+{
+	ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
+	NVPtr pNv = NVPTR(pScrn);
+	void *addr = (void *)pPixmap->devPrivate.ptr;
+
+	if (addr >= pNv->FB->map && addr < (pNv->FB->map + pNv->FB->size))
+		return TRUE;
+
+	if (pNv->shadow[0] && (addr >= pNv->shadow[0]->map && addr < (pNv->shadow[0]->map + pNv->shadow[0]->size)))
+		return TRUE;
+
+	if (pNv->shadow[1] && (addr >= pNv->shadow[1]->map && addr < (pNv->shadow[1]->map + pNv->shadow[1]->size)))
+		return TRUE;
+
+	return FALSE;
+}
+#endif /* !NOUVEAU_EXA_PIXMAPS */
+
 Bool
 NVExaPixmapIsOnscreen(PixmapPtr pPixmap)
 {
@@ -812,7 +833,7 @@ NVExaInit(ScreenPtr pScreen)
 	pNv->EXADriverPtr->exa_major = EXA_VERSION_MAJOR;
 	pNv->EXADriverPtr->exa_minor = EXA_VERSION_MINOR;
 
-#ifdef NOUVEAU_EXA_PIXMAPS
+#if NOUVEAU_EXA_PIXMAPS
 	if (NOUVEAU_EXA_PIXMAPS) {
 		pNv->EXADriverPtr->flags = EXA_OFFSCREEN_PIXMAPS |
 					   EXA_HANDLES_PIXMAPS;
@@ -831,6 +852,9 @@ NVExaInit(ScreenPtr pScreen)
 			NOUVEAU_ALIGN(pScrn->virtualX, 64) * NOUVEAU_ALIGN(pScrn->virtualY,64) * 
 			(pScrn->bitsPerPixel / 8); 
 		pNv->EXADriverPtr->memorySize		= pNv->FB->size; 
+#if EXA_VERSION_MINOR >= 2
+		pNv->EXADriverPtr->PixmapIsOffscreen = nouveau_exa_pixmap_is_offscreen;
+#endif
 	}
 	pNv->EXADriverPtr->pixmapOffsetAlign	= 256; 
 	pNv->EXADriverPtr->pixmapPitchAlign	= 64; 
diff --git a/src/nv_type.h b/src/nv_type.h
index bc0e8bf..ec31fc3 100644
--- a/src/nv_type.h
+++ b/src/nv_type.h
@@ -385,7 +385,8 @@ typedef struct _NVRec {
 
     /* Various pinned memory regions */
     struct nouveau_bo * FB;
-    struct nouveau_bo * FB_old; /* for KMS */
+    //struct nouveau_bo * FB_old; /* for KMS */
+    struct nouveau_bo * shadow[2]; /* for easy acces by exa */
     struct nouveau_bo * Cursor;
     struct nouveau_bo * Cursor2;
     struct nouveau_bo * CLUT0;	/* NV50 only */

commit 86c70df254e63ebc5c405803d6faa9ae33df4995
Author: Maarten Maathuis <madman2003@gmail.com>
Date:   Sun Jul 6 12:52:16 2008 +0200

    NV50_KMS: support gamma changes

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 87caa4f..b3c37ac 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -380,6 +380,21 @@ drmmode_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
 	drmmode_crtc->shadow = NULL;
 }
 
+static void
+drmmode_gamma_set(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue, int size)
+{
+	ScrnInfoPtr pScrn = crtc->scrn;
+	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+	drmmode_ptr drmmode = drmmode_crtc->drmmode;
+	int ret;
+
+	ErrorF("drmmode_gamma_set\n");
+
+	ret = drmModeCrtcSetGamma(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, size, (uint16_t *)red, (uint16_t *)green, (uint16_t *)blue);
+	if (ret)
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "drmModeCrtcSetGamma failed\n");
+}
+
 static const xf86CrtcFuncsRec drmmode_crtc_funcs = {
 	.dpms = drmmode_crtc_dpms,
 	.set_mode_major = drmmode_set_mode_major,
@@ -391,6 +406,7 @@ static const xf86CrtcFuncsRec drmmode_crtc_funcs = {
 	.shadow_create = drmmode_shadow_create,
 	.shadow_allocate = drmmode_shadow_allocate,
 	.shadow_destroy = drmmode_shadow_destroy,
+	.gamma_set = drmmode_gamma_set,
 	.destroy = NULL, /* XXX */
 };
 
diff --git a/src/nv_driver.c b/src/nv_driver.c
index 5292051..38c2908 100644
--- a/src/nv_driver.c
+++ b/src/nv_driver.c
@@ -2546,16 +2546,14 @@ NVScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
 	 * Initialize colormap layer.
 	 * Must follow initialization of the default colormap 
 	 */
-	if (!pNv->kms_enable) {
-		if (!pNv->randr12_enable) {
-			if(!xf86HandleColormaps(pScreen, 256, 8, NVDACLoadPalette,
-					NULL, CMAP_RELOAD_ON_MODE_SWITCH | CMAP_PALETTED_TRUECOLOR))
+	if (!pNv->randr12_enable && !pNv->kms_enable) {
+		if(!xf86HandleColormaps(pScreen, 256, 8, NVDACLoadPalette,
+				NULL, CMAP_RELOAD_ON_MODE_SWITCH | CMAP_PALETTED_TRUECOLOR))
+			return FALSE;
+	} else {
+		if (!xf86HandleColormaps(pScreen, 256, 8, NVLoadPalette,
+				NULL, CMAP_PALETTED_TRUECOLOR))
 			return FALSE;
-		} else {
-			if (!xf86HandleColormaps(pScreen, 256, 8, NVLoadPalette,
-					NULL, CMAP_PALETTED_TRUECOLOR))
-				return FALSE;
-		}
 	}
 
 	if(pNv->ShadowFB) {

commit 6de89c8cb219cc82b46e0d0d723fa9d1cefe4ac8
Author: Maarten Maathuis <madman2003@gmail.com>
Date:   Sun Jul 6 12:29:13 2008 +0200

    NV50: Unaccelerated rotation support.
    
    - This will need a PixmapIsOffscreen hook before it will be considered for acceleration.

diff --git a/src/nv50_randr.c b/src/nv50_randr.c
index 91e8804..e4de78a 100644
--- a/src/nv50_randr.c
+++ b/src/nv50_randr.c
@@ -95,8 +95,13 @@ nv50_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, DisplayModePtr adjuste
 	NVPtr pNv = NVPTR(pScrn);
 
 	/* Maybe move this elsewhere? */
-	nv_crtc->crtc->SetFB(nv_crtc->crtc, pNv->FB);
-	nv_crtc->crtc->SetFBOffset(nv_crtc->crtc, x, y);
+	if (crtc->rotatedData) {
+		nv_crtc->crtc->SetFB(nv_crtc->crtc, nv_crtc->shadow);
+		nv_crtc->crtc->SetFBOffset(nv_crtc->crtc, 0, 0);
+	} else {
+		nv_crtc->crtc->SetFB(nv_crtc->crtc, pNv->FB);
+		nv_crtc->crtc->SetFBOffset(nv_crtc->crtc, x, y);
+	}
 	nv_crtc->crtc->ModeSet(nv_crtc->crtc, mode);
 }
 
@@ -197,6 +202,82 @@ nv50_crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *src)
 	nv_crtc->crtc->LoadCursor(nv_crtc->crtc, TRUE, (uint32_t *) src);
 }
 
+/* This stuff isn't ready for NOUVEAU_EXA_PIXMAPS, but can be easily ported. */
+static void *
+nv50_crtc_shadow_allocate (xf86CrtcPtr crtc, int width, int height)
+{
+	ScrnInfoPtr pScrn = crtc->scrn;
+	NV50CrtcPrivatePtr nv_crtc = crtc->driver_private;
+	NVPtr pNv = NVPTR(pScrn);
+	int size, pitch;
+
+	ErrorF("nv50_crtc_shadow_allocate\n");
+
+	pitch = pScrn->displayWidth * (pScrn->bitsPerPixel/8);
+	size = pitch * height;
+
+	if (nouveau_bo_new(pNv->dev, NOUVEAU_BO_VRAM | NOUVEAU_BO_PIN,
+			64, size, &nv_crtc->shadow)) {
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate memory for shadow buffer!\n");
+		return NULL;
+	}
+
+	if (nv_crtc->shadow && nouveau_bo_map(nv_crtc->shadow, NOUVEAU_BO_RDWR)) {
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+				"Failed to map shadow buffer.\n");
+		return NULL;
+	}
+
+	return nv_crtc->shadow->map;
+}
+
+static PixmapPtr
+nv50_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
+{
+	ScrnInfoPtr pScrn = crtc->scrn;
+	uint32_t pitch;
+	PixmapPtr rotate_pixmap;
+
+	ErrorF("nv50_crtc_shadow_create\n");
+
+	if (!data)
+		data = crtc->funcs->shadow_allocate (crtc, width, height);
+
+	pitch = pScrn->displayWidth * (pScrn->bitsPerPixel/8);
+
+	rotate_pixmap = GetScratchPixmapHeader(pScrn->pScreen,
+						width, height,
+						pScrn->depth,
+						pScrn->bitsPerPixel,
+						pitch,
+						data);
+
+	if (rotate_pixmap == NULL) {
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+			"Couldn't allocate shadow pixmap for rotated CRTC\n");
+	}
+
+	return rotate_pixmap;
+}
+
+static void
+nv50_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
+{
+	ScrnInfoPtr pScrn = crtc->scrn;
+	NV50CrtcPrivatePtr nv_crtc = crtc->driver_private;
+	ScreenPtr pScreen = pScrn->pScreen;
+
+	ErrorF("nv50_crtc_shadow_destroy\n");
+
+	if (rotate_pixmap)
+		pScreen->DestroyPixmap(rotate_pixmap);
+
+	if (nv_crtc->shadow)
+		nouveau_bo_del(&nv_crtc->shadow);
+
+	nv_crtc->shadow = NULL;
+}
+
 static void
 nv50_crtc_destroy(xf86CrtcPtr crtc)
 {
@@ -214,8 +295,9 @@ static const xf86CrtcFuncsRec nv50_crtc_funcs = {
 	.mode_set = nv50_crtc_mode_set,
 	.gamma_set = nv50_crtc_gamma_set,
 	.commit = nv50_crtc_commit,
-	.shadow_create = NULL,
-	.shadow_destroy = NULL,
+	.shadow_create = nv50_crtc_shadow_create,
+	.shadow_allocate = nv50_crtc_shadow_allocate,
+	.shadow_destroy = nv50_crtc_shadow_destroy,
 	.set_cursor_position = nv50_crtc_set_cursor_position,
 	.show_cursor = nv50_crtc_show_cursor,
 	.hide_cursor = nv50_crtc_hide_cursor,
diff --git a/src/nv50_randr.h b/src/nv50_randr.h
index 6b4875c..d71087a 100644
--- a/src/nv50_randr.h
+++ b/src/nv50_randr.h
@@ -31,6 +31,7 @@
 typedef struct NV50CrtcPrivate {
 	int head;
 	nouveauCrtcPtr crtc;
+	struct nouveau_bo *shadow;
 } NV50CrtcPrivateRec, *NV50CrtcPrivatePtr;
 
 typedef struct NV50OutputPrivate {

commit 788fefa2e78a4abf7bd5c396ab9639bc6ff78451
Author: Maarten Maathuis <madman2003@gmail.com>
Date:   Sun Jul 6 01:03:44 2008 +0200

    NV50_KMS: Unaccelerated rotation support.
    
    - This will need a PixmapIsOffscreen hook for it to be ever considered for acceleration.

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 5b7773d..87caa4f 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -212,7 +212,10 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
 
 	drmmode_ConvertToKMode(crtc->scrn, &kmode, mode);
 
-	fb_id = drmmode->fb_id;
+	if (drmmode_crtc->shadow_id && crtc->rotatedData)
+		fb_id = drmmode_crtc->shadow_id;
+	else
+		fb_id = drmmode->fb_id;
 	ErrorF("fb id is %d\n", fb_id);
 	drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
 			fb_id, x, y, output_ids, output_count, &kmode);
@@ -290,6 +293,93 @@ drmmode_show_cursor (xf86CrtcPtr crtc)
 	drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, handle, 64, 64);
 }
 
+/* This stuff isn't ready for NOUVEAU_EXA_PIXMAPS, but can be easily ported. */
+static void *
+drmmode_shadow_allocate (xf86CrtcPtr crtc, int width, int height)
+{
+	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+	drmmode_ptr drmmode = drmmode_crtc->drmmode;
+	ScrnInfoPtr pScrn = crtc->scrn;
+	NVPtr pNv = NVPTR(pScrn);
+	int size, pitch, ret;
+
+	ErrorF("drmmode_shadow_allocate\n");
+
+	pitch = width * (pScrn->bitsPerPixel/8);
+	size = pitch * height;
+
+	if (nouveau_bo_new(pNv->dev, NOUVEAU_BO_VRAM | NOUVEAU_BO_PIN,
+			64, size, &drmmode_crtc->shadow)) {
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate memory for shadow buffer!\n");
+		return NULL;
+	}
+
+	if (drmmode_crtc->shadow && nouveau_bo_map(drmmode_crtc->shadow, NOUVEAU_BO_RDWR)) {
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+				"Failed to map shadow buffer.\n");
+		return NULL;
+	}
+
+	ret = drmModeAddFB(drmmode->fd, width, height, pScrn->depth, pScrn->bitsPerPixel, pitch, drmmode_crtc->shadow->map_handle, &drmmode_crtc->shadow_id);
+	if (ret)


Reply to: