#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
};
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;
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;
modes = ApmSetupDGAMode (pScrn, modes, &num, 8, 8,
(pScrn->bitsPerPixel != 24),
(pScrn->bitsPerPixel != 8) ? 0 : pScrn->displayWidth,
0, 0, 0, PseudoColor);
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);
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);
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);
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) {
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);
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) {
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) {
while (APMVGAB(0x3DA) & 0x08);
while (!(APMVGAB(0x3DA) & 0x08));
}
else {
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;
*mem = (unsigned char*)(pApm->LinAddress +
0*((char *)pApm->FbBase - (char *)pApm->LinMap));
*size = pScrn->videoRam << 10;
*offset = 0;
*flags = DGA_NEED_ROOT;
return TRUE;
}