[PATCH] xf86-video-xgi: add support for Rotate using ShadowFB

Wolfram Sang w.sang at pengutronix.de
Tue Jan 4 07:16:11 PST 2011


Copied over from xf86-video-sis and adapted to xgi.

Signed-off-by: Wolfram Sang <w.sang at pengutronix.de>
---

Well, this patch works fine with v1.5.1 of this driver. Rebasing to 1.6.0 went
flawless and from looking through the code, I couldn't see why it should not
work with 1.6.0 as well. The drawback is that I don't have the time to update
the xserver on my target-device to actually test the latest driver :( My hope
is that someone else is able to test it. If not, then the code is at least out
in the wild in case someone needs it later.

 src/Makefile.am  |    1 +
 src/xgi.h        |    3 +-
 src/xgi_driver.c |   42 ++++++
 src/xgi_driver.h |   10 ++
 src/xgi_shadow.c |  392 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 447 insertions(+), 1 deletions(-)
 create mode 100644 src/xgi_shadow.c

diff --git a/src/Makefile.am b/src/Makefile.am
index 96e7018..4b4352d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -58,6 +58,7 @@ xgi_drv_la_SOURCES = \
 	xgi_pci.h \
 	xgi_regs.h \
 	xgi_setup.c \
+	xgi_shadow.c \
 	xgi_vb.c \
 	xgi_vb.h \
 	xgi_vga.c \
diff --git a/src/xgi.h b/src/xgi.h
index 715502f..f6db3d8 100755
--- a/src/xgi.h
+++ b/src/xgi.h
@@ -753,7 +753,8 @@ typedef struct {
 
     unsigned char 	*ImageWriteBufferAddr;
 
-    int 		Rotate;
+    int 		Rotate, Reflect;
+    void		(*PointerMoved)(int index, int x, int y);
 
     BOOLEAN		HaveCustomModes; /* Jong 07/27/2009; support customer modes */
 
diff --git a/src/xgi_driver.c b/src/xgi_driver.c
index c149caa..f1664de 100755
--- a/src/xgi_driver.c
+++ b/src/xgi_driver.c
@@ -5078,6 +5078,48 @@ XGIScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
         return FALSE;
     }
 */
+
+    /* Initialize Shadow framebuffer and screen rotation/reflection */
+    if(pXGI->ShadowFB) {
+       RefreshAreaFuncPtr refreshArea = XGIRefreshArea;
+
+       if(pXGI->Rotate) {
+	  if(!pXGI->PointerMoved) pXGI->PointerMoved = pScrn->PointerMoved;
+	  pScrn->PointerMoved = XGIPointerMoved;
+	  switch(pScrn->bitsPerPixel) {
+	     case 8:  refreshArea = XGIRefreshArea8;  break;
+	     case 16: refreshArea = XGIRefreshArea16; break;
+	     case 24: refreshArea = XGIRefreshArea24; break;
+	     case 32: refreshArea = XGIRefreshArea32; break;
+	  }
+#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(4,3,0,0,0)
+	  xf86DisableRandR();
+	  xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		"Driver rotation enabled, disabling RandR\n");
+#endif
+       } else if(pXGI->Reflect) {
+          switch(pScrn->bitsPerPixel) {
+	  case 8:
+	  case 16:
+	  case 32:
+             if(!pXGI->PointerMoved) pXGI->PointerMoved = pScrn->PointerMoved;
+	     pScrn->PointerMoved = XGIPointerMovedReflect;
+	     refreshArea = XGIRefreshAreaReflect;
+#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(4,3,0,0,0)
+	     xf86DisableRandR();
+	     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		  "Driver reflection enabled, disabling RandR\n");
+#endif
+	     break;
+	  default:
+	     xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		  "Reflection not supported at this framebuffer depth\n");
+	  }
+       }
+
+       ShadowFBInit(pScreen, refreshArea);
+    }
+
     xf86DPMSInit(pScreen, (DPMSSetProcPtr) XGIDisplayPowerManagementSet, 0);
 
     /* Init memPhysBase and fbOffset in pScrn */
diff --git a/src/xgi_driver.h b/src/xgi_driver.h
index 4004ccd..f6809d0 100755
--- a/src/xgi_driver.h
+++ b/src/xgi_driver.h
@@ -738,6 +738,16 @@ static Bool XGISwitchMode(int scrnIndex, DisplayModePtr mode, int flags);
 static void XGIAdjustFrame(int scrnIndex, int x, int y, int flags);
 static Bool XGISaveScreenDH(ScreenPtr pScreen, int mode);
 
+/* shadow */
+extern void 	XGIPointerMoved(int index, int x, int y);
+extern void 	XGIPointerMovedReflect(int index, int x, int y);
+extern void 	XGIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
+extern void 	XGIRefreshAreaReflect(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
+extern void 	XGIRefreshArea8(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
+extern void 	XGIRefreshArea16(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
+extern void 	XGIRefreshArea24(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
+extern void 	XGIRefreshArea32(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
+
 /* Optional functions */
 static void       XGIFreeScreen(int scrnIndex, int flags);
 
diff --git a/src/xgi_shadow.c b/src/xgi_shadow.c
new file mode 100644
index 0000000..cb1e261
--- /dev/null
+++ b/src/xgi_shadow.c
@@ -0,0 +1,392 @@
+/*
+ * Copyright (C) 1999-2004 by The XFree86 Project, Inc.
+ * based on code written by Mark Vojkovich
+ * Copyright (C) 2003-2005 Thomas Winischhofer
+ * Copyright (C) 2010 Wolfram Sang, Pengutronix e.K.
+ *
+ * based on sis_shadow.c from xf86-video-sis
+ *
+ * Licensed under the following terms:
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appears in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * and that the name of the copyright holder not be used in advertising
+ * or publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holder makes no representations
+ * about the suitability of this software for any purpose.  It is provided
+ * "as is" without expressed or implied warranty.
+ *
+ * THE COPYRIGHT HOLDER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ * This module doesn't use CurrentLayout, because it is never
+ * active when DGA is active and vice versa.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "xgi.h"
+#include "servermd.h"
+
+void XGIPointerMoved(int index, int x, int y);
+void XGIPointerMovedReflect(int index, int x, int y);
+void XGIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
+void XGIRefreshAreaReflect(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
+void XGIRefreshArea8(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
+void XGIRefreshArea16(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
+void XGIRefreshArea24(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
+void XGIRefreshArea32(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
+
+void
+XGIPointerMoved(int index, int x, int y)
+{
+    ScrnInfoPtr pScrn = xf86Screens[index];
+    XGIPtr pXGI = XGIPTR(pScrn);
+
+    if(pXGI->Rotate == 1) {
+       (*pXGI->PointerMoved)(index, pScrn->pScreen->height - y - 1, x);
+    } else {
+       (*pXGI->PointerMoved)(index, y, pScrn->pScreen->width - x - 1);
+    }
+}
+
+void
+XGIPointerMovedReflect(int index, int x, int y)
+{
+    ScrnInfoPtr pScrn = xf86Screens[index];
+    XGIPtr pXGI = XGIPTR(pScrn);
+
+    switch(pXGI->Reflect) {
+    case 1: /* x */
+       (*pXGI->PointerMoved)(index, pScrn->pScreen->width - x - 1, y);
+       break;
+    case 2: /* y */
+       (*pXGI->PointerMoved)(index, x, pScrn->pScreen->height - y - 1);
+       break;
+    case 3: /* x + y */
+       (*pXGI->PointerMoved)(index, pScrn->pScreen->width - x - 1, pScrn->pScreen->height - y - 1);
+    }
+}
+
+/* Refresh area (unreflected, unrotated) */
+
+void
+XGIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
+{
+    XGIPtr pXGI = XGIPTR(pScrn);
+    int    width, height, Bpp, FBPitch;
+    CARD8  *src, *dst;
+
+    Bpp = pScrn->bitsPerPixel >> 3;
+    FBPitch = BitmapBytePad(pScrn->displayWidth * pScrn->bitsPerPixel);
+
+    while(num--) {
+
+       width = (pbox->x2 - pbox->x1) * Bpp;
+       height = pbox->y2 - pbox->y1;
+       src = pXGI->ShadowPtr + (pbox->y1 * pXGI->ShadowPitch) +  (pbox->x1 * Bpp);
+       dst = pXGI->FbBase + (pbox->y1 * FBPitch) + (pbox->x1 * Bpp);
+
+       while(height--) {
+	  memcpy(dst, src, width);
+	  dst += FBPitch;
+	  src += pXGI->ShadowPitch;
+       }
+
+       pbox++;
+    }
+}
+
+/* RefreshArea for reflection */
+
+void
+XGIRefreshAreaReflect(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
+{
+    XGIPtr pXGI = XGIPTR(pScrn);
+    int    width, height, Bpp, FBPitch, twidth;
+    CARD8  *src, *dst, *tdst, *tsrc;
+    CARD16 *tdst16, *tsrc16;
+    CARD32 *tdst32, *tsrc32;
+
+    Bpp = pScrn->bitsPerPixel >> 3;
+    FBPitch = BitmapBytePad(pScrn->displayWidth * pScrn->bitsPerPixel);
+
+    while(num--) {
+       width = (pbox->x2 - pbox->x1) * Bpp;
+       height = pbox->y2 - pbox->y1;
+       src = pXGI->ShadowPtr + (pbox->y1 * pXGI->ShadowPitch) +  (pbox->x1 * Bpp);
+       dst = pXGI->FbBase;
+       switch(pXGI->Reflect) {
+       case 1:	/* x */
+	  dst += (pbox->y1 * FBPitch) + ((pScrn->displayWidth - pbox->x1 - 1) * Bpp);
+	  switch(Bpp) {
+	     case 1:
+		while(height--) {
+		   tdst = dst;
+		   tsrc = src;
+		   twidth = width;
+		   while(twidth--) *tdst-- = *tsrc++;
+		   dst += FBPitch;
+		   src += pXGI->ShadowPitch;
+		}
+		break;
+	     case 2:
+		width >>= 1;
+		while(height--) {
+		   tdst16 = (CARD16 *)dst;
+		   tsrc16 = (CARD16 *)src;
+		   twidth = width;
+		   while(twidth--) *tdst16-- = *tsrc16++;
+		   dst += FBPitch;
+		   src += pXGI->ShadowPitch;
+		}
+		break;
+	     case 4:
+		width >>= 2;
+		while(height--) {
+		   tdst32 = (CARD32 *)dst;
+		   tsrc32 = (CARD32 *)src;
+		   twidth = width;
+		   while(twidth--) *tdst32-- = *tsrc32++;
+		   dst += FBPitch;
+		   src += pXGI->ShadowPitch;
+		}
+	  }
+	  break;
+       case 2:	/* y */
+	  dst += ((pScrn->virtualY - pbox->y1 - 1) * FBPitch) + (pbox->x1 * Bpp);
+	  while(height--) {
+	     memcpy(dst, src, width);
+	     dst -= FBPitch;
+	     src += pXGI->ShadowPitch;
+	  }
+	  break;
+       case 3:	/* x + y */
+	  dst += ((pScrn->virtualY - pbox->y1 - 1) * FBPitch) + ((pScrn->displayWidth - pbox->x1 - 1) * Bpp);
+	  switch(Bpp) {
+	     case 1:
+		while(height--) {
+		   tdst = dst;
+		   tsrc = src;
+		   twidth = width;
+		   while(twidth--) *tdst-- = *tsrc++;
+		   dst -= FBPitch;
+		   src += pXGI->ShadowPitch;
+		}
+		break;
+	     case 2:
+	        width >>= 1;
+		while(height--) {
+		   tdst16 = (CARD16 *)dst;
+		   tsrc16 = (CARD16 *)src;
+		   twidth = width;
+		   while(twidth--) *tdst16-- = *tsrc16++;
+		   dst -= FBPitch;
+		   src += pXGI->ShadowPitch;
+		}
+		break;
+	     case 4:
+		width >>= 2;
+		while(height--) {
+		   tdst32 = (CARD32 *)dst;
+		   tsrc32 = (CARD32 *)src;
+		   twidth = width;
+		   while(twidth--) *tdst32-- = *tsrc32++;
+		   dst -= FBPitch;
+		   src += pXGI->ShadowPitch;
+		}
+		break;
+	  }
+       }
+       pbox++;
+    }
+}
+
+/* RefreshArea()s for rotation */
+
+void
+XGIRefreshArea8(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
+{
+    XGIPtr pXGI = XGIPTR(pScrn);
+    int    count, width, height, y1, y2, dstPitch, srcPitch;
+    CARD8  *dstPtr, *srcPtr, *src;
+    CARD32 *dst;
+
+    dstPitch = pScrn->displayWidth;
+    srcPitch = -pXGI->Rotate * pXGI->ShadowPitch;
+
+    while(num--) {
+       width = pbox->x2 - pbox->x1;
+       y1 = pbox->y1 & ~3;
+       y2 = (pbox->y2 + 3) & ~3;
+       height = (y2 - y1) >> 2;  /* in dwords */
+
+       if(pXGI->Rotate == 1) {
+	  dstPtr = pXGI->FbBase + (pbox->x1 * dstPitch) + pScrn->virtualX - y2;
+	  srcPtr = pXGI->ShadowPtr + ((1 - y2) * srcPitch) + pbox->x1;
+       } else {
+	  dstPtr = pXGI->FbBase +  ((pScrn->virtualY - pbox->x2) * dstPitch) + y1;
+	  srcPtr = pXGI->ShadowPtr + (y1 * srcPitch) + pbox->x2 - 1;
+       }
+
+       while(width--) {
+	  src = srcPtr;
+	  dst = (CARD32 *)dstPtr;
+	  count = height;
+	  while(count--) {
+	     *(dst++) = src[0]                    |
+		        (src[srcPitch]     <<  8) |
+		        (src[srcPitch * 2] << 16) |
+			(src[srcPitch * 3] << 24);
+	     src += (srcPitch * 4);
+	  }
+	  srcPtr += pXGI->Rotate;
+	  dstPtr += dstPitch;
+       }
+
+       pbox++;
+    }
+}
+
+void
+XGIRefreshArea16(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
+{
+    XGIPtr pXGI = XGIPTR(pScrn);
+    int count, width, height, y1, y2, dstPitch, srcPitch;
+    CARD16 *dstPtr, *srcPtr, *src;
+    CARD32 *dst;
+
+    dstPitch = pScrn->displayWidth;
+    srcPitch = -pXGI->Rotate * pXGI->ShadowPitch >> 1;
+
+    while(num--) {
+       width = pbox->x2 - pbox->x1;
+       y1 = pbox->y1 & ~1;
+       y2 = (pbox->y2 + 1) & ~1;
+       height = (y2 - y1) >> 1;  /* in dwords */
+
+       if(pXGI->Rotate == 1) {
+	  dstPtr = (CARD16 *)pXGI->FbBase + (pbox->x1 * dstPitch) + pScrn->virtualX - y2;
+	  srcPtr = (CARD16 *)pXGI->ShadowPtr + ((1 - y2) * srcPitch) + pbox->x1;
+       } else {
+	  dstPtr = (CARD16 *)pXGI->FbBase + ((pScrn->virtualY - pbox->x2) * dstPitch) + y1;
+	  srcPtr = (CARD16 *)pXGI->ShadowPtr + (y1 * srcPitch) + pbox->x2 - 1;
+       }
+
+       while(width--) {
+	  src = srcPtr;
+	  dst = (CARD32 *)dstPtr;
+	  count = height;
+	  while(count--) {
+	     *(dst++) = src[0] | (src[srcPitch] << 16);
+	     src += (srcPitch * 2);
+	  }
+	  srcPtr += pXGI->Rotate;
+	  dstPtr += dstPitch;
+       }
+
+       pbox++;
+    }
+}
+
+/* this one could be faster */
+void
+XGIRefreshArea24(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
+{
+    XGIPtr pXGI = XGIPTR(pScrn);
+    int    count, width, height, y1, y2, dstPitch, srcPitch;
+    CARD8  *dstPtr, *srcPtr, *src;
+    CARD32 *dst;
+
+    dstPitch = BitmapBytePad(pScrn->displayWidth * 24);
+    srcPitch = -pXGI->Rotate * pXGI->ShadowPitch;
+
+    while(num--) {
+       width = pbox->x2 - pbox->x1;
+       y1 = pbox->y1 & ~3;
+       y2 = (pbox->y2 + 3) & ~3;
+       height = (y2 - y1) >> 2;  /* blocks of 3 dwords */
+
+       if(pXGI->Rotate == 1) {
+	  dstPtr = pXGI->FbBase + (pbox->x1 * dstPitch) + ((pScrn->virtualX - y2) * 3);
+	  srcPtr = pXGI->ShadowPtr + ((1 - y2) * srcPitch) + (pbox->x1 * 3);
+       } else {
+	  dstPtr = pXGI->FbBase + ((pScrn->virtualY - pbox->x2) * dstPitch) + (y1 * 3);
+	  srcPtr = pXGI->ShadowPtr + (y1 * srcPitch) + (pbox->x2 * 3) - 3;
+       }
+
+       while(width--) {
+	  src = srcPtr;
+	  dst = (CARD32 *)dstPtr;
+	  count = height;
+	  while(count--) {
+	     dst[0] = src[0]         |
+		      (src[1] << 8)  |
+		      (src[2] << 16) |
+		      (src[srcPitch] << 24);
+	     dst[1] = src[srcPitch + 1]         |
+		      (src[srcPitch + 2] << 8)  |
+		      (src[srcPitch * 2] << 16) |
+		      (src[(srcPitch * 2) + 1] << 24);
+	     dst[2] = src[(srcPitch * 2) + 2]         |
+		      (src[srcPitch * 3] << 8)        |
+		      (src[(srcPitch * 3) + 1] << 16) |
+		      (src[(srcPitch * 3) + 2] << 24);
+	     dst += 3;
+	     src += (srcPitch << 2);
+	  }
+	  srcPtr += pXGI->Rotate * 3;
+	  dstPtr += dstPitch;
+       }
+
+       pbox++;
+    }
+}
+
+void
+XGIRefreshArea32(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
+{
+    XGIPtr pXGI = XGIPTR(pScrn);
+    int    count, width, height, dstPitch, srcPitch;
+    CARD32 *dstPtr, *srcPtr, *src, *dst;
+
+    dstPitch = pScrn->displayWidth;
+    srcPitch = -pXGI->Rotate * pXGI->ShadowPitch >> 2;
+
+    while(num--) {
+       width = pbox->x2 - pbox->x1;
+       height = pbox->y2 - pbox->y1;
+
+       if(pXGI->Rotate == 1) {
+	  dstPtr = (CARD32 *)pXGI->FbBase + (pbox->x1 * dstPitch) + pScrn->virtualX - pbox->y2;
+	  srcPtr = (CARD32 *)pXGI->ShadowPtr + ((1 - pbox->y2) * srcPitch) + pbox->x1;
+       } else {
+	  dstPtr = (CARD32 *)pXGI->FbBase + ((pScrn->virtualY - pbox->x2) * dstPitch) + pbox->y1;
+	  srcPtr = (CARD32 *)pXGI->ShadowPtr + (pbox->y1 * srcPitch) + pbox->x2 - 1;
+       }
+
+       while(width--) {
+	  src = srcPtr;
+	  dst = dstPtr;
+	  count = height;
+	  while(count--) {
+	     *(dst++) = *src;
+	     src += srcPitch;
+	  }
+	  srcPtr += pXGI->Rotate;
+	  dstPtr += dstPitch;
+       }
+
+       pbox++;
+    }
+}
-- 
1.7.2.3



More information about the xorg-devel mailing list