summaryrefslogtreecommitdiff
path: root/src/smi_shadow.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/smi_shadow.c')
-rw-r--r--src/smi_shadow.c162
1 files changed, 161 insertions, 1 deletions
diff --git a/src/smi_shadow.c b/src/smi_shadow.c
index 5ef9ba5..ffc488f 100644
--- a/src/smi_shadow.c
+++ b/src/smi_shadow.c
@@ -26,7 +26,11 @@ Silicon Motion shall not be used in advertising or otherwise to promote the
sale, use or other dealings in this Software without prior written
authorization from the XFree86 Project and Silicon Motion.
*/
-/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/siliconmotion/smi_shadow.c,v 1.2 2000/12/05 21:18:37 dawes Exp $ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/siliconmotion/smi_shadow.c,v 1.1 2000/11/28 20:59:20 dawes Exp $ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
#include "xf86.h"
#include "xf86_OSproc.h"
@@ -181,6 +185,162 @@ void SMI_RefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
LEAVE_PROC("SMI_RefreshArea");
}
+/* Custom version for the 730 series (Cougar3DR).
+ This chipset has problems with large rotate-blts. */
+
+void SMI_RefreshArea730(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+ int width, height, srcX, srcY, destX, destY;
+ int maxPixels, tempWidth;
+
+ ENTER_PROC("SMI_RefreshArea730");
+
+ /* #671 */
+ if (pSmi->polyLines)
+ {
+ pSmi->polyLines = FALSE;
+ return;
+ }
+
+ if (pSmi->rotate)
+ {
+ /* IF we need to do rotation, setup the hardware here. */
+ WaitIdleEmpty();
+ WRITE_DPR(pSmi, 0x10, pSmi->ShadowPitch);
+ WRITE_DPR(pSmi, 0x3C, pSmi->ShadowPitch);
+ WRITE_DPR(pSmi, 0x44, pSmi->FBOffset >> 3);
+ }
+
+ /* #672 */
+ if (pSmi->ClipTurnedOn)
+ {
+ WaitQueue(1);
+ WRITE_DPR(pSmi, 0x2C, pSmi->ScissorsLeft);
+ pSmi->ClipTurnedOn = FALSE;
+ }
+
+ /* SM731 cannot rotate-blt more than a certain number of pixels
+ (based on a calculation from the Windows driver source */
+ maxPixels = 1280 / pScrn->bitsPerPixel;
+
+ while (num--)
+ {
+ /* Get coordinates of the box to refresh. */
+ srcX = pbox->x1;
+ srcY = pbox->y1;
+ width = pbox->x2 - srcX;
+ height = pbox->y2 - srcY;
+
+ DEBUG((VERBLEV, "x=%d y=%d w=%d h=%d\n", srcX, srcY, width, height));
+
+ if ((width > 0) && (height > 0))
+ {
+ switch (pSmi->rotate)
+ {
+ case SMI_ROTATE_CW:
+ /* 90 degrees CW rotation. Calculate destination
+ coordinates:
+
+ *---+
+ | | +-----*
+ | | | | destX = shadowHeight - srcY - 1
+ | | --> | | destY = srcX
+ | | | |
+ | | +-----+
+ +---+
+ */
+ destX = pSmi->ShadowHeight - srcY - 1;
+ destY = srcX;
+
+ for (tempWidth=width; tempWidth>0;)
+ {
+ if (width>maxPixels)
+ width = maxPixels;
+ WaitQueue(4);
+ WRITE_DPR(pSmi, 0x00, (srcX << 16) + srcY);
+ WRITE_DPR(pSmi, 0x04, (destX << 16) + destY);
+ WRITE_DPR(pSmi, 0x08, (width << 16) + height);
+ WRITE_DPR(pSmi, 0x0C, 0xCC | SMI_ROTATE_BLT |
+ SMI_ROTATE_CW | SMI_START_ENGINE);
+ destY += maxPixels;
+ srcX += maxPixels;
+ tempWidth -= maxPixels;
+ width = tempWidth;
+ }
+
+ break;
+
+ case SMI_ROTATE_CCW:
+ /* 90 degrees CCW rotatation. Calculate destination
+ coordinates:
+
+ *---+
+ | | +-----+
+ | | | | destX = srcY
+ | | --> | | destY = shadowWidth - srcX - 1
+ | | | |
+ | | *-----+
+ +---+
+ */
+ destX = srcY;
+ destY = pSmi->ShadowWidth - srcX - 1;
+
+ for (tempWidth=width; tempWidth>0;)
+ {
+ if (width>maxPixels)
+ width = maxPixels;
+ WaitQueue(4);
+ WRITE_DPR(pSmi, 0x00, (srcX << 16) + srcY);
+ WRITE_DPR(pSmi, 0x04, (destX << 16) + destY);
+ WRITE_DPR(pSmi, 0x08, (width << 16) + height);
+ WRITE_DPR(pSmi, 0x0C, 0xCC | SMI_ROTATE_BLT |
+ SMI_ROTATE_CCW | SMI_START_ENGINE);
+ destY -= maxPixels;
+ srcX += maxPixels;
+ tempWidth -= maxPixels;
+ width = tempWidth;
+ }
+
+ break;
+
+ default:
+ /* No rotation, perform a normal copy. */
+ if (pScrn->bitsPerPixel == 24)
+ {
+ srcX *= 3;
+ width *= 3;
+
+ if (pSmi->Chipset == SMI_LYNX)
+ {
+ srcY *= 3;
+ }
+ }
+
+ WaitQueue(4);
+ WRITE_DPR(pSmi, 0x00, (srcX << 16) + srcY);
+ WRITE_DPR(pSmi, 0x04, (srcX << 16) + srcY);
+ WRITE_DPR(pSmi, 0x08, (width << 16) + height);
+ WRITE_DPR(pSmi, 0x0C, SMI_BITBLT + SMI_START_ENGINE + 0xCC);
+ break;
+ }
+ }
+
+ pbox++;
+ }
+
+ if (pSmi->rotate)
+ {
+ /* If we did a rotation, we need to restore the hardware state here. */
+ WaitIdleEmpty();
+ WRITE_DPR(pSmi, 0x10, (pSmi->Stride << 16) | pSmi->Stride);
+ WRITE_DPR(pSmi, 0x3C, (pSmi->Stride << 16) | pSmi->Stride);
+ WRITE_DPR(pSmi, 0x44, 0);
+ }
+
+ LEAVE_PROC("SMI_RefreshArea730");
+}
+
/******************************************************************************\
|* SMI_PointerMoved
|*=============================================================================