[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