diff options
Diffstat (limited to 'hw/kdrive/src/kdrive.c')
-rw-r--r-- | hw/kdrive/src/kdrive.c | 872 |
1 files changed, 872 insertions, 0 deletions
diff --git a/hw/kdrive/src/kdrive.c b/hw/kdrive/src/kdrive.c new file mode 100644 index 000000000..b17fb0fc4 --- /dev/null +++ b/hw/kdrive/src/kdrive.c @@ -0,0 +1,872 @@ +/* + * $Id$ + * + * Copyright © 1999 Keith Packard + * + * 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 appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD 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. + */ +/* $XFree86: $ */ + +#include "kdrive.h" +#include <mivalidate.h> +#include <dixstruct.h> + +CARD8 kdBpp[] = { 1, 4, 8, 16, 24, 32 }; + +#define NUM_KD_BPP (sizeof (kdBpp) / sizeof (kdBpp[0])) + +int kdScreenPrivateIndex; +unsigned long kdGeneration; + +Bool kdVideoTest; +unsigned long kdVideoTestTime; +Bool kdEmulateMiddleButton; +Bool kdDisableZaphod; +Bool kdEnabled; +Bool kdSwitchPending; + +void (*restoreHardware)(void); + +/* + * Carry arguments from InitOutput through driver initialization + * to KdScreenInit + */ + +KdOsFuncs *kdOsFuncs; +extern WindowPtr *WindowTable; + +void +KdSetRootClip (ScreenPtr pScreen, BOOL enable) +{ + WindowPtr pWin = WindowTable[pScreen->myNum]; + WindowPtr pChild; + Bool WasViewable = (Bool)(pWin->viewable); + Bool anyMarked; + RegionPtr pOldClip, bsExposed; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + BoxRec box; + + if (WasViewable) + { + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) + { + (void) (*pScreen->MarkOverlappedWindows)(pChild, + pChild, + &pLayerWin); + } + (*pScreen->MarkWindow) (pWin); + anyMarked = TRUE; + if (pWin->valdata) + { + if (HasBorder (pWin)) + { + RegionPtr borderVisible; + + borderVisible = REGION_CREATE(pScreen, NullBox, 1); + REGION_SUBTRACT(pScreen, borderVisible, + &pWin->borderClip, &pWin->winSize); + pWin->valdata->before.borderVisible = borderVisible; + } + pWin->valdata->before.resized = TRUE; + } + } + + if (enable) + { + box.x1 = 0; + box.y1 = 0; + box.x2 = pScreen->width; + box.y2 = pScreen->height; + REGION_RESET(pScreen, &pWin->borderClip, &box); + REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList); + } + else + { + REGION_EMPTY(pScreen, &pWin->borderClip); + REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList); + } + + ResizeChildrenWinSize (pWin, 0, 0, 0, 0); + + if (WasViewable) + { + if (pWin->backStorage) + { + pOldClip = REGION_CREATE(pScreen, NullBox, 1); + REGION_COPY(pScreen, pOldClip, &pWin->clipList); + } + + if (pWin->firstChild) + { + anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin->firstChild, + pWin->firstChild, + (WindowPtr *)NULL); + } + else + { + (*pScreen->MarkWindow) (pWin); + anyMarked = TRUE; + } + +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pLayerWin); + } +#endif /* DO_SAVE_UNDERS */ + + if (anyMarked) + (*pScreen->ValidateTree)(pWin, NullWindow, VTOther); + } + + if (pWin->backStorage && + ((pWin->backingStore == Always) || WasViewable)) + { + if (!WasViewable) + pOldClip = &pWin->clipList; /* a convenient empty region */ + bsExposed = (*pScreen->TranslateBackingStore) + (pWin, 0, 0, pOldClip, + pWin->drawable.x, pWin->drawable.y); + if (WasViewable) + REGION_DESTROY(pScreen, pOldClip); + if (bsExposed) + { + RegionPtr valExposed = NullRegion; + + if (pWin->valdata) + valExposed = &pWin->valdata->after.exposed; + (*pScreen->WindowExposures) (pWin, valExposed, bsExposed); + if (valExposed) + REGION_EMPTY(pScreen, valExposed); + REGION_DESTROY(pScreen, bsExposed); + } + } + if (WasViewable) + { + if (anyMarked) + (*pScreen->HandleExposures)(pWin); +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, pLayerWin); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pWin, NullWindow, VTOther); + } + if (pWin->realized) + WindowsRestructured (); +} + +void +KdDisableScreen (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + + if (!pScreenPriv->enabled) + return; + KdSetRootClip (pScreen, FALSE); + KdDisableColormap (pScreen); + if (!pScreenPriv->screen->dumb) + (*pScreenPriv->card->cfuncs->disableAccel) (pScreen); + if (!pScreenPriv->screen->softCursor) + (*pScreenPriv->card->cfuncs->disableCursor) (pScreen); + if (pScreenPriv->card->cfuncs->dpms) + (*pScreenPriv->card->cfuncs->dpms) (pScreen, KD_DPMS_NORMAL); + pScreenPriv->enabled = FALSE; + (*pScreenPriv->card->cfuncs->disable) (pScreen); +} + +void +KdDisableScreens (void) +{ + KdCardInfo *card; + KdScreenInfo *screen; + + if (kdEnabled) + { + kdEnabled = FALSE; + for (card = kdCardInfo; card; card = card->next) + { + for (screen = card->screenList; screen; screen = screen->next) + if (screen->mynum == card->selected && screen->pScreen) + KdDisableScreen (screen->pScreen); + if (card->driver) + (*card->cfuncs->restore) (card); + } + (*kdOsFuncs->Disable) (); + KdDisableInput (); + } +} + +void +KdEnableScreen (ScreenPtr pScreen) +{ + KdScreenPriv (pScreen); + + if (pScreenPriv->enabled) + return; + (*pScreenPriv->card->cfuncs->enable) (pScreen); + pScreenPriv->enabled = TRUE; + pScreenPriv->card->selected = pScreenPriv->screen->mynum; + if (!pScreenPriv->screen->softCursor) + (*pScreenPriv->card->cfuncs->enableCursor) (pScreen); + if (!pScreenPriv->screen->dumb) + (*pScreenPriv->card->cfuncs->enableAccel) (pScreen); + KdEnableColormap (pScreen); + KdSetRootClip (pScreen, TRUE); + if (pScreenPriv->card->cfuncs->dpms) + (*pScreenPriv->card->cfuncs->dpms) (pScreen, pScreenPriv->dpmsState); +} + +void +KdEnableScreens (void) +{ + KdCardInfo *card; + KdScreenInfo *screen; + + if (!kdEnabled) + { + kdEnabled = TRUE; + (*kdOsFuncs->Enable) (); + for (card = kdCardInfo; card; card = card->next) + { + (*card->cfuncs->preserve) (card); + for (screen = card->screenList; screen; screen = screen->next) + if (screen->mynum == card->selected && screen->pScreen) + KdEnableScreen (screen->pScreen); + } + KdEnableInput (); + } +} + +void +KdProcessSwitch (void) +{ + if (kdEnabled) + KdDisableScreens (); + else + { + KdReleaseAllKeys (); + KdEnableScreens (); + } +} + +void +AbortDDX(void) +{ + KdDisableScreens (); + if (kdOsFuncs) + { + if (kdEnabled) + (*kdOsFuncs->Disable) (); + (*kdOsFuncs->Fini) (); + } +} + +void +ddxUseMsg() +{ +} + +void +ddxGiveUp () +{ + AbortDDX (); +} + +void +KdParseScreen (KdScreenInfo *screen, + char *arg) +{ + screen->width = 0; + screen->height = 0; + screen->depth = 0; + screen->rate = 0; + if (!arg) + return; + + screen->width = atoi(arg); + arg = strchr (arg, 'x'); + if (!arg) + return; + arg++; + + screen->height = atoi(arg); + arg = strchr (arg, 'x'); + if (!arg) + return; + arg++; + + screen->depth = atoi(arg); + arg = strchr (arg, 'x'); + if (!arg) + return; + arg++; + + screen->rate = atoi(arg); + arg = strchr (arg, 'x'); + if (!arg) + return; + arg++; +} + +Bool kdDumbDriver; +Bool kdSoftCursor; + +int +ddxProcessArgument (int argc, char **argv, int i) +{ + KdCardInfo *card; + KdScreenInfo *screen; + + if (!strcmp (argv[i], "-card")) + { + if ((i+1) < argc) + InitCard (argv[i+1]); + else + UseMsg (); + return 2; + } + if (!strcmp (argv[i], "-screen")) + { + if ((i+1) < argc) + { + card = KdCardInfoLast (); + if (!card) + { + InitCard (0); + card = KdCardInfoLast (); + } + screen = KdScreenInfoAdd (card); + KdParseScreen (screen, argv[i+1]); + screen->dumb = kdDumbDriver; + screen->softCursor = kdSoftCursor; + kdDumbDriver = FALSE; + kdSoftCursor = FALSE; + } + else + UseMsg (); + return 2; + } + if (!strcmp (argv[i], "-zaphod")) + { + kdDisableZaphod = TRUE; + return 1; + } + if (!strcmp (argv[i], "-3button")) + { + kdEmulateMiddleButton = FALSE; + return 1; + } + if (!strcmp (argv[i], "-2button")) + { + kdEmulateMiddleButton = TRUE; + return 1; + } + if (!strcmp (argv[i], "-dumb")) + { + kdDumbDriver = TRUE; + return 1; + } + if (!strcmp (argv[i], "-softCursor")) + { + kdSoftCursor = TRUE; + return 1; + } + if (!strcmp (argv[i], "-videoTest")) + { + kdVideoTest = TRUE; + return 1; + } + if (!strcmp (argv[i], "-standalone")) + return 1; + return 0; +} + +/* + * These are getting tossed in here until I can think of where + * they really belong + */ + +void +KdOsInit (KdOsFuncs *pOsFuncs) +{ + kdOsFuncs = pOsFuncs; + if (pOsFuncs) + { + if (serverGeneration == 1) + (*pOsFuncs->Init) (); + } +} + +Bool +KdAllocatePrivates (ScreenPtr pScreen) +{ + KdPrivScreenPtr pScreenPriv; + + if (kdGeneration != serverGeneration) + { + kdScreenPrivateIndex = AllocateScreenPrivateIndex(); + kdGeneration = serverGeneration; + } + pScreenPriv = (KdPrivScreenPtr) xalloc(sizeof (*pScreenPriv)); + memset (pScreenPriv, '\0', sizeof (KdPrivScreenRec)); + if (!pScreenPriv) + return FALSE; + KdSetScreenPriv (pScreen, pScreenPriv); + return TRUE; +} + +Bool +KdCloseScreen (int index, ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + KdCardInfo *card = pScreenPriv->card; + Bool ret; + + pScreen->CloseScreen = pScreenPriv->CloseScreen; + ret = (*pScreen->CloseScreen) (index, pScreen); + + if (pScreenPriv->dpmsState != KD_DPMS_NORMAL) + (*card->cfuncs->dpms) (pScreen, KD_DPMS_NORMAL); + + if (screen->mynum == card->selected) + KdDisableScreen (pScreen); + + /* + * Restore video hardware when last screen is closed + */ + if (screen == card->screenList) + (*card->cfuncs->restore) (card); + + if (!pScreenPriv->screen->dumb) + (*card->cfuncs->finiAccel) (pScreen); + + if (!pScreenPriv->screen->softCursor) + (*card->cfuncs->finiCursor) (pScreen); + + (*card->cfuncs->scrfini) (screen); + + /* + * Clean up card when last screen is closed, DIX closes them in + * reverse order, thus we check for when the first in the list is closed + */ + if (screen == card->screenList) + { + (*card->cfuncs->cardfini) (card); + /* + * Clean up OS when last card is closed + */ + if (card == kdCardInfo) + { + if (kdEnabled) + { + kdEnabled = FALSE; + (*kdOsFuncs->Disable) (); + } + } + } + + pScreenPriv->screen->pScreen = 0; + + xfree ((pointer) pScreenPriv); + return ret; +} + +Bool +KdSaveScreen (ScreenPtr pScreen, int on) +{ + KdScreenPriv(pScreen); + int dpmsState; + + if (!pScreenPriv->card->cfuncs->dpms) + return FALSE; + + dpmsState = pScreenPriv->dpmsState; + switch (on) { + case SCREEN_SAVER_OFF: + dpmsState = KD_DPMS_NORMAL; + break; + case SCREEN_SAVER_ON: + if (dpmsState == KD_DPMS_NORMAL) + dpmsState = KD_DPMS_NORMAL+1; + break; + case SCREEN_SAVER_CYCLE: + if (dpmsState < KD_DPMS_MAX) + dpmsState++; + break; + case SCREEN_SAVER_FORCER: + break; + } + if (dpmsState != pScreenPriv->dpmsState) + { + if (pScreenPriv->enabled) + (*pScreenPriv->card->cfuncs->dpms) (pScreen, dpmsState); + pScreenPriv->dpmsState = dpmsState; + } + return TRUE; +} + +Bool +KdCreateWindow (WindowPtr pWin) +{ + if (!pWin->parent) + { + KdScreenPriv(pWin->drawable.pScreen); + + if (!pScreenPriv->enabled) + { + REGION_EMPTY (pWin->drawable.pScreen, &pWin->borderClip); + REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList); + } + } + return TRUE; +} + +/* Pass through AddScreen, which doesn't take any closure */ +static KdScreenInfo *kdCurrentScreen; + +Bool +KdScreenInit(int index, ScreenPtr pScreen, int argc, char **argv) +{ + KdScreenInfo *screen = kdCurrentScreen; + KdCardInfo *card = screen->card; + KdPrivScreenPtr pScreenPriv; + + KdAllocatePrivates (pScreen); + + pScreenPriv = KdGetScreenPriv(pScreen); + + screen->pScreen = pScreen; + pScreenPriv->screen = screen; + pScreenPriv->card = card; + pScreenPriv->bytesPerPixel = screen->bitsPerPixel >> 3; + pScreenPriv->dpmsState = KD_DPMS_NORMAL; + + /* + * This is done in this order so that backing store wraps + * our GC functions; fbFinishScreenInit initializes MI + * backing store + */ + if (!fbSetupScreen (pScreen, + screen->frameBuffer, + screen->width, screen->height, + screen->dpix, screen->dpiy, + screen->pixelStride, + screen->bitsPerPixel)) + { + return FALSE; + } + + /* + * Set colormap functions + */ + pScreen->InstallColormap = KdInstallColormap; + pScreen->UninstallColormap = KdUninstallColormap; + pScreen->ListInstalledColormaps = KdListInstalledColormaps; + pScreen->StoreColors = KdStoreColors; + + pScreen->SaveScreen = KdSaveScreen; + pScreen->CreateWindow = KdCreateWindow; + + if (!screen->dumb && card->cfuncs->initAccel) + if (!(*card->cfuncs->initAccel) (pScreen)) + screen->dumb = TRUE; + + if (!fbFinishScreenInit (pScreen, + screen->frameBuffer, + screen->width, screen->height, + screen->dpix, screen->dpiy, + screen->pixelStride, + screen->bitsPerPixel)) + { + return FALSE; + } + + /* + * Plug in our own block/wakeup handlers. + * miScreenInit installs NoopDDA in both places + */ + pScreen->BlockHandler = KdBlockHandler; + pScreen->WakeupHandler = KdWakeupHandler; + + /* + * Wrap CloseScreen, the order now is: + * KdCloseScreen + * miBSCloseScreen + * fbCloseScreen + */ + pScreenPriv->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = KdCloseScreen; + + if (screen->softCursor || + !card->cfuncs->initCursor || + !(*card->cfuncs->initCursor) (pScreen)) + { + /* Use MI for cursor display and event queueing. */ + screen->softCursor = TRUE; + miDCInitialize(pScreen, &kdPointerScreenFuncs); + } + + if (!fbCreateDefColormap (pScreen)) + { + return FALSE; + } + + /* + * Enable the hardware + */ + if (!kdEnabled) + { + kdEnabled = TRUE; + (*kdOsFuncs->Enable) (); + } + + if (screen->mynum == card->selected) + { + (*card->cfuncs->preserve) (card); + (*card->cfuncs->enable) (pScreen); + pScreenPriv->enabled = TRUE; + if (!screen->softCursor) + (*card->cfuncs->enableCursor) (pScreen); + KdEnableColormap (pScreen); + if (!screen->dumb) + (*card->cfuncs->enableAccel) (pScreen); + } + + return TRUE; +} + +void +KdInitScreen (ScreenInfo *pScreenInfo, + KdScreenInfo *screen, + int argc, + char **argv) +{ + KdCardInfo *card = screen->card; + int i; + + (*card->cfuncs->scrinit) (screen); + + if (!screen->dpix) + screen->dpix = 75; + + if (!screen->dpiy) + screen->dpiy = 75; + if (!card->cfuncs->initAccel) + screen->dumb = TRUE; + if (!card->cfuncs->initCursor) + screen->softCursor = TRUE; + +} + +Bool +KdSetPixmapFormats (ScreenInfo *pScreenInfo) +{ + CARD8 depthToBpp[33]; /* depth -> bpp map */ + CARD8 bppToDepth[33]; /* bpp -> depth map */ + KdCardInfo *card; + KdScreenInfo *screen; + int i; + PixmapFormatRec *format; + + for (i = 1; i <= 32; i++) + { + depthToBpp[i] = 0; + bppToDepth[i] = 0; + } + + /* + * Generate mappings between bitsPerPixel and depth, + * also ensure that all screens comply with protocol + * restrictions on equivalent formats for the same + * depth on different screens + */ + for (card = kdCardInfo; card; card = card->next) + { + for (screen = card->screenList; screen; screen = screen->next) + { + if (!depthToBpp[screen->depth]) + depthToBpp[screen->depth] = screen->bitsPerPixel; + else if (depthToBpp[screen->depth] != screen->bitsPerPixel) + return FALSE; + if (!bppToDepth[screen->bitsPerPixel]) + bppToDepth[screen->bitsPerPixel] = screen->depth; + } + } + + /* + * Fill in additional formats + */ + for (i = 0; i < NUM_KD_BPP; i++) + if (!bppToDepth[kdBpp[i]] && !depthToBpp[kdBpp[i]]) + { + bppToDepth[kdBpp[i]] = kdBpp[i]; + depthToBpp[kdBpp[i]] = kdBpp[i]; + } + + pScreenInfo->imageByteOrder = IMAGE_BYTE_ORDER; + pScreenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT; + pScreenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD; + pScreenInfo->bitmapBitOrder = BITMAP_BIT_ORDER; + + pScreenInfo->numPixmapFormats = 0; + + for (i = 1; i <= 32; i++) + { + if (depthToBpp[i]) + { + format = &pScreenInfo->formats[pScreenInfo->numPixmapFormats++]; + format->depth = i; + format->bitsPerPixel = depthToBpp[i]; + format->scanlinePad = BITMAP_SCANLINE_PAD; + } + } + + return TRUE; +} + +void +KdAddScreen (ScreenInfo *pScreenInfo, + KdScreenInfo *screen, + int argc, + char **argv) +{ + int i; + /* + * Fill in fb visual type masks for this screen + */ + for (i = 0; i < pScreenInfo->numPixmapFormats; i++) + { + unsigned long visuals; + Pixel rm, gm, bm; + + if (pScreenInfo->formats[i].depth == screen->depth) + { + visuals = screen->visuals; + rm = screen->redMask; + gm = screen->greenMask; + bm = screen->blueMask; + } + else + { + visuals = 0; + rm = gm = bm = 0; + } + fbSetVisualTypesAndMasks (pScreenInfo->formats[i].depth, + visuals, + 8, + rm, gm, bm); + } + + kdCurrentScreen = screen; + + AddScreen (KdScreenInit, argc, argv); +} + +void +KdInitOutput (ScreenInfo *pScreenInfo, + int argc, + char **argv) +{ + int i; + KdCardInfo *card; + KdScreenInfo *screen; + + if (!kdCardInfo) + { + InitCard (0); + card = KdCardInfoLast (); + screen = KdScreenInfoAdd (card); + KdParseScreen (screen, 0); + } + /* + * Initialize all of the screens for all of the cards + */ + for (card = kdCardInfo; card; card = card->next) + { + if ((*card->cfuncs->cardinit) (card)) + { + for (screen = card->screenList; screen; screen = screen->next) + KdInitScreen (pScreenInfo, screen, argc, argv); + } + } + + /* + * Merge the various pixmap formats together, this can fail + * when two screens share depth but not bitsPerPixel + */ + if (!KdSetPixmapFormats (pScreenInfo)) + return; + + /* + * Add all of the screens + */ + for (card = kdCardInfo; card; card = card->next) + for (screen = card->screenList; screen; screen = screen->next) + KdAddScreen (pScreenInfo, screen, argc, argv); +} + +#ifdef XTESTEXT1 +void +XTestGenerateEvent(dev_type, keycode, keystate, mousex, mousey) + int dev_type; + int keycode; + int keystate; + int mousex; + int mousey; +{ +} + +void +XTestGetPointerPos(fmousex, fmousey) + short *fmousex, *fmousey; +{ +} + +void +XTestJumpPointer(jx, jy, dev_type) + int jx; + int jy; + int dev_type; +{ +} +#endif + +#ifdef DPMSExtension +void +DPMSSet(int level) +{ +} + +int +DPMSGet (int *level) +{ + return -1; +} + +Bool +DPMSSupported (void) +{ + return FALSE; +} +#endif |