summaryrefslogtreecommitdiff
path: root/src/apm_dga.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/apm_dga.c')
-rw-r--r--src/apm_dga.c434
1 files changed, 434 insertions, 0 deletions
diff --git a/src/apm_dga.c b/src/apm_dga.c
new file mode 100644
index 0000000..3a5f362
--- /dev/null
+++ b/src/apm_dga.c
@@ -0,0 +1,434 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/apm/apm_dga.c,v 1.10 2002/01/25 21:55:54 tsi Exp $ */
+/*
+ * file: apm_dga.c
+ * ported from s3virge, ported from mga
+ *
+ */
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86_ansic.h"
+#include "xf86Pci.h"
+#include "xf86PciInfo.h"
+#include "xaa.h"
+#include "xaalocal.h"
+#include "apm.h"
+#include "dgaproc.h"
+
+
+static Bool ApmOpenFramebuffer(ScrnInfoPtr, char **, unsigned char **,
+ int *, int *, int *);
+static Bool ApmSetMode(ScrnInfoPtr, DGAModePtr);
+static int ApmGetViewport(ScrnInfoPtr);
+static void ApmSetViewport(ScrnInfoPtr, int, int, int);
+static void ApmFillRect(ScrnInfoPtr, int, int, int, int, unsigned long);
+static void ApmBlitRect(ScrnInfoPtr, int, int, int, int, int, int);
+static void ApmBlitTransRect(ScrnInfoPtr, int, int, int, int, int, int,
+ unsigned long);
+static void ApmSync(ScrnInfoPtr);
+
+static
+DGAFunctionRec ApmDGAFuncs = {
+ ApmOpenFramebuffer,
+ NULL,
+ ApmSetMode,
+ ApmSetViewport,
+ ApmGetViewport,
+ ApmSync,
+ ApmFillRect,
+ ApmBlitRect,
+ ApmBlitTransRect
+};
+
+/*
+ * Placeholder
+ */
+void
+ApmSync(ScrnInfoPtr pScrn)
+{
+}
+
+static __inline__ int FindSmallestPitch(ApmPtr pApm, int Bpp, int width)
+{
+ if (width <= 640)
+ return 640;
+ else if (width <= 800)
+ return 800;
+ else if (width <= 1024)
+ return 1024;
+ else if (width <= 1152)
+ return 1152;
+ else if (width <= 1280)
+ return 1280;
+ else if (width <= 1600)
+ return 1600;
+ return (width + 7) & ~7;
+}
+
+static DGAModePtr
+ApmSetupDGAMode(ScrnInfoPtr pScrn, DGAModePtr modes, int *num,
+ int bitsPerPixel, int depth, Bool pixmap, int secondPitch,
+ unsigned long red, unsigned long green, unsigned long blue,
+ short visualClass)
+{
+ DisplayModePtr firstMode, pMode;
+ APMDECL(pScrn);
+ DGAModePtr mode, newmodes;
+ int size, pitch, Bpp = bitsPerPixel >> 3;
+ Bool reduced_pitch = TRUE;
+
+SECOND_PASS:
+
+ firstMode = NULL;
+
+ for (pMode = pScrn->modes; pMode != firstMode; pMode = pMode->next) {
+
+ if (!firstMode)
+ firstMode = pMode;
+
+ if (reduced_pitch)
+ pitch = FindSmallestPitch(pApm, Bpp, pMode->HDisplay);
+ else
+ pitch = pMode->HDisplay;
+ if (!reduced_pitch && pitch == FindSmallestPitch(pApm, Bpp, pMode->HDisplay))
+ continue;
+
+ size = pitch * Bpp * pMode->VDisplay;
+
+ if((!secondPitch || (pitch != secondPitch)) &&
+ (size <= pScrn->videoRam * 1024 - pApm->OffscreenReserved)) {
+
+ if(secondPitch)
+ pitch = secondPitch;
+
+ if(!(newmodes = xrealloc(modes, (*num + 1) * sizeof(DGAModeRec))))
+ break;
+
+ modes = newmodes;
+ mode = modes + *num;
+
+ mode->mode = pMode;
+ mode->flags = DGA_CONCURRENT_ACCESS;
+
+ if(pixmap)
+ mode->flags |= DGA_PIXMAP_AVAILABLE;
+ if(!pApm->NoAccel) {
+ mode->flags |= DGA_FILL_RECT | DGA_BLIT_RECT;
+ if (Bpp != 3)
+ mode->flags |= DGA_BLIT_RECT_TRANS;
+ }
+ if(pMode->Flags & V_DBLSCAN)
+ mode->flags |= DGA_DOUBLESCAN;
+ if(pMode->Flags & V_INTERLACE)
+ mode->flags |= DGA_INTERLACED;
+ mode->byteOrder = pScrn->imageByteOrder;
+ mode->depth = depth;
+ mode->bitsPerPixel = bitsPerPixel;
+ mode->red_mask = red;
+ mode->green_mask = green;
+ mode->blue_mask = blue;
+ mode->visualClass = visualClass;
+ mode->viewportWidth = pMode->HDisplay;
+ mode->viewportHeight = pMode->VDisplay;
+ mode->xViewportStep = (bitsPerPixel == 24) ? 4 : 1;
+ mode->yViewportStep = 1;
+ mode->viewportFlags = DGA_FLIP_RETRACE;
+ mode->offset = 0;
+ mode->address = pApm->FbBase;
+ mode->bytesPerScanline = pitch * Bpp;
+ mode->imageWidth = pitch;
+ mode->imageHeight = (pScrn->videoRam * 1024 -
+ pApm->OffscreenReserved) / mode->bytesPerScanline;
+ mode->pixmapWidth = mode->imageWidth;
+ mode->pixmapHeight = mode->imageHeight;
+ mode->maxViewportX = mode->imageWidth - mode->viewportWidth;
+ /* this might need to get clamped to some maximum */
+ mode->maxViewportY = mode->imageHeight - mode->viewportHeight;
+
+ (*num)++;
+ }
+
+ }
+
+ if(secondPitch) {
+ secondPitch = 0;
+ goto SECOND_PASS;
+ }
+
+ if (reduced_pitch) {
+ reduced_pitch = FALSE;
+ goto SECOND_PASS;
+ }
+
+ return modes;
+}
+
+Bool
+ApmDGAInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ APMDECL(pScrn);
+ DGAModePtr modes = NULL;
+ int num = 0;
+
+ /* 8 */
+ modes = ApmSetupDGAMode (pScrn, modes, &num, 8, 8,
+ (pScrn->bitsPerPixel != 24),
+ (pScrn->bitsPerPixel != 8) ? 0 : pScrn->displayWidth,
+ 0, 0, 0, PseudoColor);
+
+ /* 15 */
+ modes = ApmSetupDGAMode (pScrn, modes, &num, 16, 15,
+ (pScrn->bitsPerPixel != 24),
+ (pScrn->depth != 15) ? 0 : pScrn->displayWidth,
+ 0x7C00, 0x03E0, 0x001F, TrueColor);
+
+ modes = ApmSetupDGAMode (pScrn, modes, &num, 16, 15,
+ (pScrn->bitsPerPixel != 24),
+ (pScrn->depth != 15) ? 0 : pScrn->displayWidth,
+ 0x7C00, 0x03E0, 0x001F, DirectColor);
+
+ /* 16 */
+ modes = ApmSetupDGAMode (pScrn, modes, &num, 16, 16,
+ (pScrn->bitsPerPixel != 24),
+ (pScrn->depth != 16) ? 0 : pScrn->displayWidth,
+ 0xF800, 0x07E0, 0x001F, TrueColor);
+
+ modes = ApmSetupDGAMode (pScrn, modes, &num, 16, 16,
+ (pScrn->bitsPerPixel != 24),
+ (pScrn->depth != 16) ? 0 : pScrn->displayWidth,
+ 0xF800, 0x07E0, 0x001F, DirectColor);
+
+ /* 24 */
+ modes = ApmSetupDGAMode (pScrn, modes, &num, 24, 24,
+ (pScrn->bitsPerPixel == 24),
+ (pScrn->bitsPerPixel != 24) ? 0 : pScrn->displayWidth,
+ 0xFF0000, 0x00FF00, 0x0000FF, TrueColor);
+
+ modes = ApmSetupDGAMode (pScrn, modes, &num, 24, 24,
+ (pScrn->bitsPerPixel == 24),
+ (pScrn->bitsPerPixel != 24) ? 0 : pScrn->displayWidth,
+ 0xFF0000, 0x00FF00, 0x0000FF, DirectColor);
+
+ /* 32 */
+ modes = ApmSetupDGAMode (pScrn, modes, &num, 32, 24,
+ (pScrn->bitsPerPixel != 24),
+ (pScrn->bitsPerPixel != 32) ? 0 : pScrn->displayWidth,
+ 0xFF0000, 0x00FF00, 0x0000FF, TrueColor);
+
+ modes = ApmSetupDGAMode (pScrn, modes, &num, 32, 24,
+ (pScrn->bitsPerPixel != 24),
+ (pScrn->bitsPerPixel != 32) ? 0 : pScrn->displayWidth,
+ 0xFF0000, 0x00FF00, 0x0000FF, DirectColor);
+
+ pApm->numDGAModes = num;
+ pApm->DGAModes = modes;
+
+ return DGAInit(pScreen, &ApmDGAFuncs, modes, num);
+}
+
+
+static Bool
+ApmSetMode(ScrnInfoPtr pScrn, DGAModePtr pMode)
+{
+ int index = pScrn->pScreen->myNum;
+ APMDECL(pScrn);
+
+ if (!pMode) { /* restore the original mode */
+ if (pApm->DGAactive) {
+ memcpy(&pApm->CurrentLayout, &pApm->SavedLayout,
+ sizeof pApm->CurrentLayout);
+ pApm->DGAactive = FALSE;
+ }
+
+ pScrn->currentMode = pApm->CurrentLayout.pMode;
+ ApmSwitchMode(index, pScrn->currentMode, 0);
+ ApmAdjustFrame(index, pScrn->frameX0, pScrn->frameY0, 0);
+#if 0
+ if (pApm->AccelInfoRec)
+ XAAInit(pScrn->pScreen, pApm->AccelInfoRec);
+#endif
+ }
+ else {
+ if (!pApm->DGAactive) {
+ memcpy(&pApm->SavedLayout, &pApm->CurrentLayout,
+ sizeof pApm->CurrentLayout);
+ pApm->DGAactive = TRUE;
+ }
+
+ pApm->CurrentLayout.displayWidth = pMode->imageWidth;
+ pApm->CurrentLayout.displayHeight = pMode->imageHeight;
+ pApm->CurrentLayout.Scanlines = pMode->imageHeight + 1;
+ pApm->CurrentLayout.depth = pMode->depth;
+ pApm->CurrentLayout.bitsPerPixel = pMode->bitsPerPixel;
+ pApm->CurrentLayout.bytesPerScanline = pMode->bytesPerScanline;
+ pApm->CurrentLayout.pMode = pMode->mode;
+ if (pMode->bitsPerPixel == 24)
+ pApm->CurrentLayout.mask32 = 3;
+ else
+ pApm->CurrentLayout.mask32 = 32 / pMode->bitsPerPixel - 1;
+
+ ApmSwitchMode(index, pMode->mode, 0);
+ ApmSetupXAAInfo(pApm, NULL);
+
+#if 0
+ if (pApm->DGAXAAInfo)
+ bzero(pApm->DGAXAAInfo, sizeof(*pApm->DGAXAAInfo));
+ else
+ pApm->DGAXAAInfo = XAACreateInfoRec();
+ ApmSetupXAAInfo(pApm, pApm->DGAXAAInfo);
+ /*
+ * Let's hope this won't fail, that is reinitialize XAA for this
+ * setup...
+ */
+ XAAInit(pScrn->pScreen, pApm->DGAXAAInfo);
+#endif
+ }
+
+ return TRUE;
+}
+
+
+
+static int
+ApmGetViewport(
+ ScrnInfoPtr pScrn
+)
+{
+ return 0;
+}
+
+static void
+ApmSetViewport(
+ ScrnInfoPtr pScrn,
+ int x, int y,
+ int flags
+)
+{
+ unsigned char tmp;
+
+ APMDECL(pScrn);
+
+ if (pApm->apmLock) {
+ /*
+ * This is just an attempt, because Daryll is tampering with MY
+ * registers.
+ */
+ if (!pApm->noLinear) {
+ tmp = (RDXB(0xDB) & 0xF4) | 0x0A;
+ WRXB(0xDB, tmp);
+ ApmWriteSeq(0x1B, 0x20);
+ ApmWriteSeq(0x1C, 0x2F);
+ }
+ else {
+ tmp = (RDXB_IOP(0xDB) & 0xF4) | 0x0A;
+ WRXB_IOP(0xDB, tmp);
+ wrinx(pApm->xport, 0x1B, 0x20);
+ wrinx(pApm->xport, 0x1C, 0x2F);
+ }
+ pApm->apmLock = FALSE;
+ }
+ pScrn->AdjustFrame(pScrn->pScreen->myNum, x, y, flags);
+ if (pApm->VGAMap) {
+ /* Wait until vertical retrace is in progress. */
+ while (APMVGAB(0x3DA) & 0x08);
+ while (!(APMVGAB(0x3DA) & 0x08));
+ }
+ else {
+ /* Wait until vertical retrace is in progress. */
+ while (inb(pApm->iobase + 0x3DA) & 0x08);
+ while (!(inb(pApm->iobase + 0x3DA) & 0x08));
+ }
+}
+
+static void
+ApmFillRect (
+ ScrnInfoPtr pScrn,
+ int x, int y, int w, int h,
+ unsigned long color
+)
+{
+ APMDECL(pScrn);
+
+ if(pApm->CurrentLayout.depth != 24) {
+ (*pApm->SetupForSolidFill)(pScrn, color, GXcopy, ~0);
+ (*pApm->SubsequentSolidFillRect)(pScrn, x, y, w, h);
+ }
+ else {
+ (*pApm->SetupForSolidFill24)(pScrn, color, GXcopy, ~0);
+ (*pApm->SubsequentSolidFillRect24)(pScrn, x, y, w, h);
+ }
+ SET_SYNC_FLAG(pApm->AccelInfoRec);
+}
+
+static void
+ApmBlitRect(
+ ScrnInfoPtr pScrn,
+ int srcx, int srcy,
+ int w, int h,
+ int dstx, int dsty
+)
+{
+ APMDECL(pScrn);
+ int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
+ int ydir = (srcy < dsty) ? -1 : 1;
+
+ if(pApm->CurrentLayout.depth != 24) {
+ (*pApm->SetupForScreenToScreenCopy)(
+ pScrn, xdir, ydir, GXcopy, ~0, -1);
+ (*pApm->SubsequentScreenToScreenCopy)(
+ pScrn, srcx, srcy, dstx, dsty, w, h);
+ }
+ else {
+ (*pApm->SetupForScreenToScreenCopy24)(
+ pScrn, xdir, ydir, GXcopy, ~0, -1);
+ (*pApm->SubsequentScreenToScreenCopy24)(
+ pScrn, srcx, srcy, dstx, dsty, w, h);
+ }
+ SET_SYNC_FLAG(pApm->AccelInfoRec);
+}
+
+static void
+ApmBlitTransRect(
+ ScrnInfoPtr pScrn,
+ int srcx, int srcy,
+ int w, int h,
+ int dstx, int dsty,
+ unsigned long color
+)
+{
+ APMDECL(pScrn);
+
+ if(pApm->AccelInfoRec) {
+ int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
+ int ydir = (srcy < dsty) ? -1 : 1;
+
+ (*pApm->AccelInfoRec->SetupForScreenToScreenCopy)(
+ pScrn, xdir, ydir, GXcopy, ~0, (int)color);
+ (*pApm->AccelInfoRec->SubsequentScreenToScreenCopy)(
+ pScrn, srcx, srcy, dstx, dsty, w, h);
+ SET_SYNC_FLAG(pApm->AccelInfoRec);
+ }
+}
+
+static Bool
+ApmOpenFramebuffer(
+ ScrnInfoPtr pScrn,
+ char **name,
+ unsigned char **mem,
+ int *size,
+ int *offset,
+ int *flags
+)
+{
+ APMDECL(pScrn);
+
+ *name = NULL; /* no special device */
+ *mem = (unsigned char*)(pApm->LinAddress +
+ 0*((char *)pApm->FbBase - (char *)pApm->LinMap));
+ *size = pScrn->videoRam << 10;
+ *offset = 0;
+ *flags = DGA_NEED_ROOT;
+
+ return TRUE;
+}