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

Signed-off-by: Wolfram Sang <[email protected]>
---

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

_______________________________________________
[email protected]: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: http://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to