diff options
author | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 16:48:55 +0000 |
---|---|---|
committer | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 16:48:55 +0000 |
commit | 696e90e916d6f0db4057826115d74c5d968eb5e7 (patch) | |
tree | fe862c5efc82e1ee284f74571788c742cc66e58d /src/apm_dga.c | |
parent | 4a50a1da2ff5601a5721d1a06a23c7f75db958c4 (diff) |
Initial revisionXORG-STABLE
Diffstat (limited to 'src/apm_dga.c')
-rw-r--r-- | src/apm_dga.c | 434 |
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; +} |